https://www.163.com/dy/article/J8871AJ5055616YO.html
假设,我们有一个UserServiceImpl和UserService,此时需要在UserContoller中使用UserService。在 Spring 中通常都习惯这样写代码:
@Autowired UserService userService;
在这种情况下,无论是使用 JDK 动态代理,还是 CGLIB 都不会出现问题。
但是,如果你的代码是这样的呢:
@Autowired UserServiceImpl userService;
这个时候,如果我们是使用 JDK 动态代理,那在启动时就会报错:
启动报错
因为 JDK 动态代理是基于接口的,代理生成的对象只能赋值给接口变量。
而 CGLIB 就不存在这个问题。因为 CGLIB 是通过生成子类来实现的,代理对象无论是赋值给接口还是实现类这两者都是代理对象的父类。
SpringBoot 正是出于这种考虑,于是在 2.x 版本中,将 AOP 默认实现改为了 CGLIB。
更多的细节信息,读者可以自己查阅上述 issue。
总结
- Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理。
- SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB。
- 在 SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项spring.aop.proxy-target-class=false来进行修改,proxyTargetClass配置已无效。