CGLIB 动态代理的实现原理、实现步骤、源码实例

参考答案

CGLIB 动态代理的实现原理

  • 利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

 

CGLIB 动态代理的实现步骤

  • 先实现一个 MethodInterceptor,方法调用会被转发到该类的intercept() 方法。
  • 在要使用时,通过 CGLIB 动态代理,来获取代理对象。

 

CGLIB 动态代理的实现源码实例

public class HelloService {
 
    public HelloService() {
        System.out.println("HelloService构造");
    }
 
    /**
     * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
     */
    final public String sayOthers(String name) {
        System.out.println("HelloService:sayOthers>>"+name);
        return null;
    }
 
    public void sayHello() {
        System.out.println("HelloService:sayHello");
    }
}
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import java.lang.reflect.Method;
 
/**
 * 自定义MethodInterceptor
 */
public class MyMethodInterceptor implements MethodInterceptor{
 
    /**
     * sub:cglib生成的代理对象
     * method:被代理对象方法
     * objects:方法入参
     * methodProxy: 代理方法
     */
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("======插入前置通知======");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("======插入后者通知======");
        return object;
    }
}
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;
 
public class Client {
    public static void main(String[] args) {
        // 代理类class文件存入本地磁盘方便我们反编译查看源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(HelloService.class);
        // 设置enhancer的回调对象
        enhancer.setCallback(new MyMethodInterceptor());
        // 创建代理对象
        HelloService proxy= (HelloService)enhancer.create();
        // 通过代理对象调用目标方法
        proxy.sayHello();
    }
}

CGLIB 代理时,做了以下操作:

  • 生成的代理类继承被代理类。注:如委托类被final修饰,则不可被继承(被代理);同样,如委托类中存在final修饰的方法,则该方法也不可被代理。
  • 代理类会为委托方法生成两个方法,一个是与委托方法签名相同的方法,它在方法中会通过super调用委托方法;另一个是代理类独有的方法
  • 执行代理对象的方法时,先判断是否存在实现了MethodInterceptor接口的CGLIB$CALLBACK_0 ; 如存在,则将调用MethodInterceptor中的intercept方法。
intercept方法中,除了会调用委托方法,还会进行一些增强操作。在Spring AOP 中。典型的应用场景,是在某些敏感方法执行前后,进行操作日志记录。

在 CGLIB 中,方法的调用不是通过反射来完成的,是直接对方法进行调用,通过 FastClass 机制对 Class 对象进行特别的处理。例如,用数组保存 method 的引用,每次调用方法时,都通过一个 index 下标,来保持对方法的引用。

以上,是Java面试题【CGLIB代理的实现、以及使用案例(代码实例)】的参考答案。

输出,是最好的学习方法

欢迎在评论区留下你的问题、笔记或知识点补充~

—end—

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧