本文使用的AOP版本如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
首先官方文档中有说明:
小结一下:
1.默认使用 JDK 动态代理,这样便可以代理所有的接口类型(interface)
2.Spring AOP也支持CGLIB的代理方式。如果我们被代理对象没有实现任何接口,则默认是CGLIB
3.我们可以强制使用CGLIB,指定proxy-target-class = “true” 或者 基于注解@EnableAspectJAutoProxy(proxyTargetClass = true)
疑问
看到这里其实已经很清楚了,但是有的同学可能会有疑问,上述第2点里,实现接口指的是什么呢?是随便写一个interface,让我们的bean实现他就可以了吗?
其实不然,Spring源码中,在选择代理的方式之前,其实对
proxyTargetClass
属性有这样一步处理:
org.springframework.aop.framework.ProxyProcessorSupport
这里
对bean所实现的所有接口进行循环
(前面两个判断这里不解释,有兴趣的同学点进去看下就知道了),从这里可以看出,如果bean所实现的所有接口都为空接口(没有方法),那么最后会走else分支,调用setProxyTargetClass(true),其实也就是设置了proxyTargetClass为true。
因此在选择代理方式的时候:
org.springframework.aop.framework.DefaultAopProxyFactory
config.isProxyTargetClass() 为true,会进入第一个if分支里面。在这个分支里面,如果bean它本身是一个interface或者是本身已经是一个代理对象,那么就会创建JDK代理,否则会使用CGLIB的方式创建代理对象。
至此,最后在总结一下:
1.默认使用 JDK 动态代理,这样便可以代理所有的接口类型(interface)
2.Spring AOP也支持CGLIB的代理方式。如果我们被代理对象没有实现任何接口或者实现的接口都是空接口,则是CGLIB
3.我们可以强制使用CGLIB,指定proxy-target-class = “true” 或者 基于注解@EnableAspectJAutoProxy(proxyTargetClass = true)