Toc
  1. 基本原理
    1. JDK 动态代理
    2. CGLIB 动态代理
  2. 应用
    1. JDK 动态代理和 CGLIB 字节码生成的区别
    2. 效率比较
    3. Spring 如何选择用 JDK 还是 CGLIB
  3. 三连问
Toc
0 results found
BOBO
动态代理
2020/08/20 Spring

基本原理

JDK 动态代理

利用拦截器(拦截器必须实现 InvocationHanlder) + 反射机制生成一个实现代理接口的匿名类。根据反射获取到的信息动态生成.java 文件,然后动态编译生成.class 文件。

CGLIB 动态代理

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


应用

JDK 动态代理和 CGLIB 字节码生成的区别

  1. JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。
  2. CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。

所以 CGLib 不能对声明为 final 的方法进行代理。

效率比较

  1. CGLib 底层采用 ASM 字节码生成框架,使用字节码技术生成代理类,在 jdk6 之前比使用 Java 反射效率要高/
  2. 在 jdk6、jdk7、jdk8 逐步对 JDK 动态代理优化之后,在调用次数较少的情况下,JDK 代理效率高于 CGLIB 代理效率。
  3. 优先 jdk 代理,每一次 jdk 版本升级,jdk 代理效率都得到提升,而 CGLIB 代理消息确有点跟不上步伐。

Spring 如何选择用 JDK 还是 CGLIB

  1. 当 Bean 实现接口时,Spring 就会用 JDK 的动态代理。
  2. 当 Bean 没有实现接口时,Spring 使用 CGlib 是实现。
  3. 可以强制使用 CGlib(在 spring 配置中加入<aop:aspectj-autoproxy proxy-target-class=”true”/>)

三连问

  1. JDK 动态代理有什么使用条件?

JDK 动态代理只能对实现了接口的类进行代理

  1. 为什么 JDK 动态代理对象类必须要实现接口?

因为这种方式生成的代理类继承了 Proxy 类,且 JAVA 无法多继承,只能通过实现接口的方式来代理。

  1. 为什么 JDK 动态代理生成的类继承 Proxy,导致代理对象必须要有接口。
    • 代理模式中的代理类只做转发处理,方法执行转发给原类,增强程序的执行转发给拦截器。
    • 从效率上来看直接代理类比转发接口更消耗内存。
    • 这也是为什么 JDK 动态代理需要传入被代理类的实例划对象,而不是直接传入被代理类 Class 对象。
支付宝
微信
Simple is Awesome