Spring AOP默认采用哪种动态代理方式?JDK动态代理和CGLIB动态代理的区别是什么?请解释其实现原理及适用场景。
考察说明
考查对Spring AOP底层代理机制的理解及两种动态代理方式的区别。
回答思路
- 【回答框架 1】Spring AOP默认在目标类实现接口时使用JDK动态代理,否则使用CGLIB代理;自Spring Framework 6起,默认转向基于CGLIB的代理模式。JDK动态代理基于接口,通过Proxy类和InvocationHandler生成代理对象,只能代理接口方法。
- 【回答框架 2】CGLIB代理通过生成目标类的子类并重写方法实现代理,可代理具体类,但无法代理final类和方法。CGLIB使用ASM字节码操作,性能较高,但创建代理对象时开销较大。
- 【回答框架 3】选择原则:目标类有接口时优先JDK动态代理,无接口或需代理非接口方法时使用CGLIB。JDK代理优势在于原生和接口解耦,CGLIB优势在于无接口约束。
- 【回答框架 4】运行时差异:JDK代理基于反射调用,性能略低于CGLIB(但现代JVM优化后差距缩小);CGLIB生成子类,需注意final方法不生效。事务管理等场景需根据代理方式调整配置。
- 【回答框架 5】在Spring Boot 2.x+默认使用CGLIB代理(spring.aop.proxy-target-class=true),无需额外配置;若需JDK代理可显式设置。理解代理方式影响切面拦截范围。
- 【关键点 1】Spring AOP默认通过接口判断选择JDK或CGLIB代理
- 【关键点 2】JDK动态代理基于接口,CGLIB基于子类继承并重写方法
- 【关键点 3】CGLIB无法代理final类和方法,JDK代理无法代理无接口的类
- 【关键点 4】Spring Framework 6开始默认采用CGLIB(或类似代理)以满足无接口场景
- 【关键点 5】选择代理方式需考虑目标类结构、性能及框架默认配置(如Spring Boot默认CGLIB)
- 【易错点 1】混淆JDK代理和CGLIB的适用前提,误以为JDK代理可处理所有场景
- 【易错点 2】忽略final方法无法被CGLIB增强,导致切面不生效
- 【易错点 3】在Spring Boot中未认识到默认代理方式已改变,导致配置偏差