启动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目标源