- Spring 5.x中AOP默认依旧使用JDK动态代理
- SpringBoot 2.x开始,为了解决使用JDK动态代理可能导致的类型转换异常,而使用CGLIB。
- 在SpringBoot 2.x中,如果需要替换使用JDK动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxyTargetClass配置已无效。
1. springboot 2.x 版本分析
在 SpringBoot 中,通过AopAutoConfiguration来自动装配 AOP。搜索这个类,查看源码:
默认情况下,是没有spring.aop.proxy-target-class这个配置项的。而此时,在 SpringBoot 2.x 中会默认使用 Cglib 来实现。如果需要修改 AOP 的实现,需要通过spring.aop.proxy-target-class这个配置项来修改。
#在application.properties文件中通过spring.aop.proxy-target-class来配置
spring.aop.proxy-target-class=false
这里提一下META-INF/spring-configuration-metadata.json文件的作用:在使用application.properties或application.yml文件时,IDEA 就是通过读取这些文件信息来提供代码提示的,SpringBoot 框架自己是不会来读取这个配置文件的。
Springboot 2.x内嵌Spring版本为Spring5.x:
但是Spring5中默认还是使用jdk,查看官网,地址为:
https://docs.spring.io/spring/docs/5.2.4.RELEASE/spring-framework-reference/core.html#spring-core:
Spring AOP 默认使用 JDK 动态代理,如果对象没有实现接口,则使用 CGLIB 代理。当然,也可以强制使用 CGLIB 代理。
2. Springboot 1.x 版本分析
搜索AopAutoConfiguration:
在 SpringBoot 1.5.x 版本中,默认还是使用 JDK 动态代理的
3. SpringBoot 2.x 为何默认使用 Cglib
假设,我们有一个UserServiceImpl和UserService类,此时需要在UserContoller中使用UserService。在 Spring 中通常都习惯这样写代码:
@Autowired
UserService userService;
在这种情况下,无论是使用 JDK 动态代理,还是 CGLIB 都不会出现问题。但是,如果代码是这样的:
@Autowired
UserServiceImpl userService;
这个时候,如果使用 JDK 动态代理,启动时就会报错,因为 JDK 动态代理是基于接口的,代理生成的对象只能赋值给接口变量。
而 CGLIB 就不存在这个问题。因为 CGLIB 是通过生成子类来实现的,代理对象无论是赋值给接口还是实现类,这两者都是代理对象的父类。
SpringBoot 正是出于这种考虑,于是在 2.x 版本中,将 AOP 默认实现改为了 CGLIB。
4. 总结
- Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理
- SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB
- 在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改
原文地址:https://blog.csdn.net/fei1234456/article/details/106933600/