参考资料
- 视频 - AOP原理-创建AOP代理
源码分析
上篇文章的末尾有说到 AnnotationAwareAspectJAutoProxyCreator
在所有 Bean 创建之前会有一个拦截,会调用 postProcessBeforeInstantiation()
方法。本篇文章主要分析一下自定义 Bean 的创建过程。
1、分析 postProcessBeforeInstantiation()
AbstractAutoProxyCreator#postProcessBeforeInstantiation()
1.1、判断当前 Bean 是否在 advisedBeans 中(advisedBeans 保存了所有需要增强 Bean)
1.2、判断当前 Bean 是否是基础类型
AbstractAutoProxyCreator#isInfrastructureClass()
AbstractAspectJAdvisorFactory#isAspect()
从上面的方法可以知道,基础类型包括 Advice、Pointcut、Advisor、AopInfrastructureBean,以及切面(@Aspect),因此,当前 Bean 不是基础类型。
1.3、判断当前 Bean 是否应该跳过
AspectJAwareAdvisorAutoProxyCreator#shouldSkip()
1.3.1、获取候选增强器(切面通知方法) candidateAdvisors
这四个增强器就是对应了切面类里面定义的四个通知方法。
1.3.2、判断每一个增强器是否是 AspectJPointcutAdvisor
类型的
四个增强器类型都是 InstantiationModelAwarePointcutAdvisor
,所以全部返回 false。
1.3.3、调用父类方法 shouldSkip()
父类方法返回 false。
综上,回到主方法,是否应该跳过返回 false。
2、分析 postProcessAfterInitialization()
上面第 1 点全部完成后,方法会走到配置类创建 MathCalculator
对象,对象创建完成后继续调用 postProcessAfterInitialization()
方法。
AbstractAutoProxyCreator#postProcessAfterInitialization()
需要注意的方法是 wrapIfNecessary()
,直译就是必要时包装。
AbstractAutoProxyCreator#wrapIfNecessary()
2.1、获取 Bean 的所有增强器(通知方法) getAdvicesAndAdvisorsForBean()
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()
findEligibleAdvisors()
寻找符合条件的增强器。
AbstractAdvisorAutoProxyCreator#findEligibleAdvisors()
findCandidateAdvisors()
是四个候选增强器,即 1.3.1 中的四个。
findAdvisorsThatCanApply()
从候选增强器中找到可以应用的增强器,即找哪些通知方法是需要切入当前 Bean 方法的。
AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply()
AopUtils#findAdvisorsThatCanApply()
通过以上方法找到了所有能用的增强器。
AbstractAdvisorAutoProxyCreator#findEligibleAdvisors()
将所有增强器进行排序 sortAdvisors()
,然后返回,所有增强器被放在数组 Object[] specificInterceptors
中。
2.2、保存当前 Bean 在 advisedBeans
中
AbstractAutoProxyCreator#wrapIfNecessary()
2.3、创建代理对象 createProxy()
AbstractAutoProxyCreator#createProxy()
2.3.1、获取所有增强器(通知方法)保存到 proxyFactory
2.3.2、使用代理工厂创建代理对象
ProxyFactory#getProxy()
ProxyCreatorSupport#createAopProxy()
先创建AOP代理对象。
DefaultAopProxyFactory#createAopProxy()
创建AOP代理。
有两种代理方式:
- JDK动态代理
new JdkDynamicAopProxy(config)
- CGLIB动态代理
new ObjenesisCglibAopProxy(config)
经过以上方法,给容器中返回当前组件使用CGLIB增强了的代理对象。以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程。