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

参考答案

CGLIB 动态代理的实现原理

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

 

CGLIB 动态代理的实现步骤

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

 

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

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

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

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

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

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

输出,是最好的学习方法

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

—end—

0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧