启动Spring AOP
需要配置 <aop:config>
标签或者aspectj-autoproxy
标签
<aop>
标签解析
如果使用<aop:xxxx />
标签来自动生成代理的话,入口程序是AopNamespaceHandler
|
|
- 如果使用了
<aop:config>
标签,使用ConfigBeanDefinitionParser
解析 - 如果使用了
<aop:aspectj-autoproxy>
标签,使用AspectJAutoProxyBeanDefinitionParser
解析
类结构图
这里放一张Spring AOP
代理自动生成器的类图
<aop:config>
方式使用AspectJAwareAdvisorAutoProxyCreator
创建代理,`<aop:aspectj-autoproxy>
使用AnnotationAwareAspectJAutoProxyCreator
创建代理,具体见下文
aop:config`解析
ConfigBeanDefinitionParser.java
|
|
AopNamespaceUtils.java
|
|
AspectJAwareAdvisorAutoProxyCreator.java
|
|
可见AspectJAwareAdvisorAutoProxyCreator
实现了BeanPostProcessor
接口,BeanPostProcessor
主要作用于Bean
实例化后,初始化前后,所有的Bean
都被作用到。InstantiationAwareBeanPostProcessor
虽然是BeanPostProcessor
的子接口,但它的调用时间点发生在Bean实例化前,在真正调用doCreateBean()
创建bean实例之前执行postProcessBeforeInstantiation()
postProcessBeforeInstantiation()
|
|
当我们配置TargetSourceCreator
进行自定义TargetSource
创建时,会创建代理对象并中断默认Spring
创建流程(目标对象没有创建,可见bean
创建过程: BeanDefinitionValueResolver.resolveInnerBean()
)。
getEarlyBeanReference()
Spring Bean
实例化过程,解决单例bean
之间的循环依赖问题,提前将代理对象暴露出去
|
|
详细可见bean
创建过程:AbstractAutowireCapableBeanFactory.doCreateBean() => getEarlyBeanReference()
postProcessAfterInitialization()
:创建AOP代理
默认情况下,代理是通过AbstractAutoProxyCreator
中的postProcessAfterInitialization()
创建的
|
|
可以看出 getEarlyBeanReference
和postProcessAfterInitialization
是二者选一的,而且单例Bean
目标对象只能被增强一次
当SimpleServiceImpl bean
初始化到这步后,会从容器中找出所有匹配当前bean
的通知(如果有对业务方法做增强处理),如果找到对应的通知则创建代理。
createAopProxy()
具体怎么创建代理以及用哪种方式创建代理,由 createAopProxy
决定
|
|
aspectj-autoproxy
标签解析
AspectJAutoProxyBeanDefinitionParser.java
|
|
AopNamespaceUtils.java
|
|
AnnotationAwareAspectJAutoProxyCreator.java
|
|
可以发现AnnotationAwareAspectJAutoProxyCreator
继承了AspectJAwareAdvisorAutoProxyCreator
, 执行流程和aop:config
基本一致,但是需要注意注解的特殊标签@Aspect
,下面分析@Aspect
注解是如何起作用的?
使用注解配置AOP
,需要在切面类中配置@Aspect
,再来看看AOP
代理生成过程:
|
|
不管是aop:config
还是aspectj-autoproxy
都是由AbstractAutoProxyCreator
这个类在后置处理器中生成AOP
代理,具体看看getadvicesAndAdvisorsForBean()
方法是如何获取增强
getAdvicesAndAdvisorsForBean()
getAdvicesAndAdvisorsForBean()
方法具体由子类AbstractAdvisorAutoProxyCreator
实现
|
|
这里的findCandidateAdvisors
方法,如果配置aop:config
则由AbstractAdvisorAutoProxyCreator
本类中实现,如果配置aspectj-autoproxy
则由AnnotationAwareAspectJAutoProxyCreator
子类中实现。现在来看看子类实现:
findCandidateAdvisors()
|
|
从方法中aop
可以配置在xml
中,同时也可以使用注解,2这都会同时生效。
目标对象
- 配置增强
|
|
- 业务逻辑
|
|
测试发现当配置了增强后,再去容器中获取目标bean
,结果该bean
其实是个代理,代理最终还是要通过执行invoke()
方法调用目标对象的sayHello()
方法,那么目标对象到底放在什么地方?
代理模式
下面是代理模式的结构:
- Subject:抽象主题,它是代理对象的真实对象要实现的接口,当然这可以是多个接口组成
- Proxy:代理类除了实现抽象主题定义的接口外,还必须持有所代理对象的引用
- RealSubject:被代理的类,是目标对象
JdkDynamicAopProxy
|
|
需要注意JdkDynamicAopProxy
持有的AdvisedSupport
实例,AdvisedSupport
类中包含了一个TargetSource
实例,目标对象就在TargetSource
中,也就是说代理间接持有了目标对象
|
|
回过头来,再看看动态代理的创建过程
|
|
看到这里的SingletonTargetSource
就是TargetSource
的实现类,其实在创建代理的时候就已经把目标对象放到TargetSource
中,换句话说,proxy(代理对象)代理的不是target,而是TargetSource
注意:
- 目标bean的生命周期不受
Spring
容器管理,我们以往的XML
中的AOP
配置,只是对受容器管理的bean
而言的 - 代理类会代理接口中所有方法,非增强方法同样需要通过代理类去访问(只是没有执行增强切面)
Spring
的AOP
框架默认为目标bean创建静态目标源SingletonTargetSource
,如果bean被配置为prototype
,则spring
会在每次getBean
时创建新的SingletonTargetSource
实例
参考
spring-aop组件详解——TargetSource目标源