几种代理模式简介

代理模式大家应该清楚,接下来深入挖掘一下这种设计模式

静态代理

  • 静态代理里面,代理类是确定的,也就是说我们需要一个普通类和一个代理类,代码如下

首先是一个接口Animal,有一个eat()方法

package org.example.proxy.Static;

public interface Animal {
    void eat();
}

然后我们写一个实现类Cat

package org.example.proxy.Static;

public class Cat implements Animal{
    @Override
    public void eat() {
        System.out.println("The cat is eating");
    }
}

现在如果要生成一个类对象,应该使用new Cat(),但是我希望借助一个代理,那么现在就通过一个代理类来访问对象

package org.example.proxy.Static;

public class StaticProxyAnimal implements Animal{

    private final Animal animal;
    public StaticProxyAnimal(Animal animal){
        this.animal = animal;
    }
    @Override
    public void eat() {
        System.out.println("The cat is hungry");
        animal.eat();
    }
}

调用测试

package org.example.proxy.Static;

public class StaticProxyAnimalDemo {
    public static void main(String[] args) {
        Animal cat = new StaticProxyAnimal(new Cat());
        cat.eat();
    }
}

动态代理

  • 动态代理有两种方式,一种是JDK,另一种是CGlib

JDK

  • JDK的动态代理主要是通过实现InvocationHandler接口的invoke方法创建自己的调用处理器;通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理;通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数输入
  • JDK动态代理是面向接口的代理模式
package org.example.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TargetInvoker implements InvocationHandler {

    private final Object target;

    public TargetInvoker(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before jdk handles");
        Object result = method.invoke(target, args);
        System.out.println("after jdk handles");
        return result;
    }
}

CGLib

  • 实现机制是生成目标类的子类,通过调用父类(目标类)的方法实现,在调用父类方法时在代理中进行增强。换句话说就是继承父类方法并重写父类方法达到生成代理类的目的。这样你就会知道如果父类是final的肯定是无法继承,如果父类方法是private的也没法重写
  • 它最大的好处是可以为没有实现接口的类提供代理的实现,你可以在上面JDK动态代理的Cat类里面加上一个普通方法,尝试使用JDK动态代理来调用这个普通方法,你会发现报错
  • 接下来使用CGLib来进行动态代理,核心是重写一个MethodInterceptor类的intercept方法
package org.example.proxy.CGLib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class TargetInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before cglib");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("after cglib");
        return result;
    }
}

package org.example.proxy.CGLib;

import net.sf.cglib.proxy.Enhancer;

public class CGLibProxy {
    public static Object getProxy(Class<?> cls){
        Enhancer enhancer = new Enhancer();
//        设置类加载
        enhancer.setClassLoader(cls.getClassLoader());
//        设置被代理类
        enhancer.setSuperclass(cls);
//        设置方法拦截器
        enhancer.setCallback(new TargetInterceptor());
//        创建代理类
        return enhancer.create();
    }
}

package org.example.proxy.Static;

public class Cat implements Animal{
    @Override
    public void eat() {
        System.out.println("The cat is eating");
    }
    public void play(){
        System.out.println("The cat is playing");
    }
}

调用普通方法

package org.example.proxy.CGLib;

import org.example.proxy.Static.Animal;
import org.example.proxy.Static.Cat;

public class CGLibDemo {
    public static void main(String[] args) {
        Cat cat = (Cat) CGLibProxy.getProxy(Cat.class);
        cat.play();// 新添加的普通方法
    }
}

  • 发现可以调用

有兴趣可以深入研究一下源码实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值