静态代理/JDK动态代理/CGLIB动态代理

静态代理

// 接口
interface ClothFactory {
    void productCloth();
}


// 被代理类
class NikeClothFactory implements ClothFactory{
    @Override
    public void productCloth() {
        System.out.println("我是被代理类-Nike工厂生产了一批衣服");
    }
}


// 代理类
class ProxyFactory implements ClothFactory {
    ClothFactory cf;
    public ProxyFactory(ClothFactory cf) {  // 创建代理类对象时,实际要传入被代理类的对象
        this.cf = cf;
    }

    @Override
    public void productCloth() {
        System.out.println("代理类开始执行,收取代理费!");
        cf.productCloth();
    }
}


// 测试
public class TestStaticProxy {
    public static void main(String[] args) {
        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        ProxyFactory proxy = new ProxyFactory(nikeClothFactory);

        proxy.productCloth(); // 调用代理类的方法就行
    }
}

缺点:

  • 每一个接口都要写一个代理类,繁琐
  • 每一个都要配对使用,麻烦


JDK动态代理

接口:

public interface Subject {
    int action();
}

被代理类:

public class RealSubject implements Subject{
    @Override
    public int action() {
        System.out.println("我是被代理类!");
        return 10;
    }
}

代理类工厂:

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

// 代理类工厂类 - 需要实现JDK里面的InvocationHandler接口
public class ProxyFactory implements InvocationHandler {

    Object obj;  // obj是实现类接口的被代理类的对象声明

    /**
     * 给被代理类的对象实例化(这个方法名字随便写的)
     * @param obj  被代理类
     * @return 动态返回代理类的对象,这个动态返回的对象和被代理对象实现了同一个接口或者多个
     */
    public Object blind(Object obj) {
        this.obj = obj;
        // newProxyInstance方法参数分别是:
        // 类加载器来定义代理类,代理类实现的接口列表,调度方法调用的调用处理函数(传入InvocationHandler实现类)
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                                      obj.getClass().getInterfaces(), this);
    }

    /**
     * 当通过代理类的对象发起对被重写的方法的调用时,都会转化为对一下invoke对象的调用
     * @return 接口中抽象方法的返回值+处理后代理类返回的值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 如果接口里面有多个方法,这里可以根据方法名(即method参数)进行判断,做出不同的扩展内容!!!
        System.out.println("执行jdk代理中加上的扩展功能"); 
        Object returnVal = method.invoke(obj, args);
        return returnVal;
    }
}

测试:

public class TestProxy {
    public static void test01() {
        // 1.创建被代理对象
        RealSubject real = new RealSubject();
        // 2.创建代理工厂,即创建实现InvocationHandler接口的类对象
        ProxyFactory proxyFactory = new ProxyFactory();
        // 3.调用blind方法,传入被代理类(RealSubject类对象),
        //   动态返回一个实现了 和被代理类同样接口(Subject接口) 的代理类对象
        Object obj = proxyFactory.blind(real); // 这里是Subject类型,可以强转一下
        Subject sub = (Subject) obj; // 此时sub就是代理类的对象

        Object returnVal = sub.action(); // 这个执行就会转到 InvocationHandler接口实现类 的的invoke()方法调用
        System.out.println(returnVal);
    }

    
    // 去代理上面的那个静态的例子
    public static void test02() {
        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        ProxyFactory proxyFactory = new ProxyFactory();
        ClothFactory clothFactory = (ClothFactory) proxyFactory.blind(nikeClothFactory);

        clothFactory.productCloth();  // 执行,代理类中订单扩展内容和被代理类的方法都被执行了
    }
}

优点:只需要写一个通用的代理类就行了!!

缺点:目标对象需要有实现接口



CGLIB动态代理

依赖:

<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.3</version>
</dependency>

被代理类(可以不用实现接口了,但被代理类不能使用final修饰):

public class RealSubject {
    public int action() {
        System.out.println("我是被代理类!");
        return 10;
    }
}

代理类工厂:

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

import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {
    private Object obj;

    /**
     * 传入被代理类,返回代理对象
     * @param obj 被代理类
     * @return 代理对象
     */
    public Object blind(Object obj) {
        this.obj = obj;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass()); // 设置父类
        enhancer.setCallback(this); // 设置回调方法
        return enhancer.create();   // 创建子类对象,即代理对象
    }

    /**
     * 当通过代理类的对象发起对要代理的方法的调用时,都会转化为对一下intercept()的调用
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行cglib代理中加上的扩展功能");
        Object returnVal = method.invoke(obj, args);
        return returnVal;
    }
}

测试:

public class TestProxy {
    public static void main(String[] args) {
        // 1.创建被代理对象
        RealSubject realSubject = new RealSubject();
        // 2.创建代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        // 3.获取代理类
        Object obj = proxyFactory.blind(realSubject);
        RealSubject sub = (RealSubject) obj; // 这里是RealSubject类型,可以强转一下

        Object returnVal = sub.action(); // 这个执行就会转到 MethodInterceptor接口实现类的的intercept()方法调用
        System.out.println(returnVal);
    }
}

优点:只需要写一个通用的代理类就行了,而且目标对象不需要有实现接口

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值