面试必问系列之CGLIB动态代理

2,424 阅读3分钟

扫描文末二维码或者微信搜索公众号小李不秃,即可关注微信公众号,获取到更多 Java 相关内容。

1. 带着问题去学习

上一篇讲解了 JDK 的动态代理机制,JDK 动态代理的缺点:

  • 问题1:JDK 动态代理是基于接口实现的,如果类不实现接口,怎么去代理这个类呢?
  • 问题2:JDK 动态代理的目标类的内部调用自己的另一个方法,不会经过代理对象,那如何解决这个问题呢?

那就了解一下 Spring AOP 的另一个代理机制 cglib 动态代理

2. CGLIB 动态代理

内容我抽空整理,上面这些文章有的年头比较久,看一下了解怎么使用就行。我大概总结一下上面的重点:

  • JDK 动态代理生成代理类继承 Proxy 并且实现代理接口,底层原理是通过反射调用父类的方法。

  • CGLIB 动态代理生成代理类的子类,并且实现了 Factory 接口,底层是通过 ASM 进行字节码的增强,然后生成一个新的子类。调用方法就直接调用,不需要再通过反射的方式调用。

  • Spring Boot 2.0 开始代理类默认的实现方式是 cglib,如果想使用 JDK 动态代理,可以通过 spring.aop.proxy-target-class=false 来实现。

  • CGLIB 代理的目标类调用自己的另一个方法,也是会经过代理对象的,因为底层不像 JDK 动态代理的反射方式调用,而是通过动态生成子类的全新方式调用。

  • CGLIB 代理的目标类的方法满足下面条件任意一点,就不会被代理:

    • 使用 final 修饰的方法
    • 使用 private 类型的方法
    • 使用包访问权限
  • CGLIB 代理方法,想要对方法的返回值进行特殊处理,可以使用 CallbackFilter。

3. 总结

通过动态代理的方式增强目标方法,也是实现 Spring AOP 的原理。动态代理有两种方式:JDK 动态代理和 CGLIB 动态代理。这两种代理方式的原理我也已经讲过了,希望大家也可以去实践一下,也可以跟踪一下 Spring 的代码看看底层的原理。

最后头脑风暴一下:为什么 Spring Boot 默认使用 CGLIB 动态代理呢?

扫描下方二维码即可关注微信公众号小李不秃,一起高效学习 Java。