Spring註解 AOP
AOP原理分析就是看給容器中注入了什麼組件,這個組件什麼時候工作,這個組件工作時候的功能
AOP的使用
實現AOP的詳細步驟
-
導入aop模塊
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.5.RELEASE</version> </dependency>
-
定義一個業務邏輯類(MathCalculator)
-
定義一個日誌切面類
- 加@Aspect 註解 表明這是一個切面類
- 在對應的方法上加對應的通知註解
- 配置類
- 將切面類和業務邏輯類加入到容器中
- 開啓基於註解的aop模式 @EnableAspectJAutoProxy
測試:
結果:
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy註解利用AspectJAutoProxyRegistrar給容器中創建了AnnotationAwareAspectJAutoProxyCreator的beandefinition信息,IOC容器在註冊後置處理器的時候就會根據這個beandefinition信息創建AnnotationAwareAspectJAutoProxyCreator的bean 實例
- @EnableAspectJAutoProxy
EnableAspectJAutoProxy上導入了AspectJAutoProxyRegistrar
AnnotationAwareAspectJAutoProxyCreator的定義信息beandefinition的註冊
-
AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar, 也就是自定義方式給容器中註冊組件
AspectJAutoProxyRegistrar 給容器中加入的是beanDefinition ,也就是告訴容器要創建的類型是AnnotationAwareAspectJAutoProxyCreator,名字是
internalAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //通過這個方法註冊的bean
這個函數裏具體註冊bean的 是registerOrEscalateApcAsRequired方法
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
通過上面這一句給容器中注入了AnnotationAwareAspectJAutoProxyCreator的定義信息beanDefinition
AnnotationAwareAspectJAutoProxyCreator 的註冊
AnnotationAwareAspectJAutoProxyCreator是 註解模式的AspectJ切面自動代理創建器
父類
通過追溯AnnotationAwareAspectJAutoProxyCreator 的父類 我們可以看到
它其實 實現了兩個接口
- SmartInstantiationAwareBeanPostProcessor 後置處理器
- BeanFactoryAware Aware接口的實現類
AnnotationAwareAspectJAutoProxyCreator
-> AspectJAwareAdvisorAutoProxyCreator
-> AbstractAdvisorAutoProxyCreator
->AbstractAutoProxyCreator
->ProxyProcessorSupport
實現SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
其中SmartInstantiationAwareBeanPostProcessor的父類
SmartInstantiationAwareBeanPostProcessor
->InstantiationAwareBeanPostProcessor
->BeanPostProcessor
可以看到就是後置處理器
創建ioc容器
AnnotationConfigApplicationContext:
做了三步
- 調用無參構造器
- 註冊配置類
- 調用refresh() 刷新容器
refresh() :
中註冊bean的後置處理器 用來攔截bean的創建
registerBeanPostProcessors 註冊BeanPostProcessor
registerBeanPostProcessors 方法:
-
先獲取ioc容器中已經定義了的需要創建對象的所有BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
現在這些 BeanPostProcessor 都是BeanDefinetion 還沒有創建對象
-
給容器中加入別的BeanPostProcessor
beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
-
將BeanPostProcessor分類 , 並註冊
-
實現了PriorityOrdered接口的 priorityOrderedPostProcessors[實現這個接口的有優先級排序]
-
實現了Ordered接口的orderedPostProcessors
-
沒有實現Oredered接口的nonOrderedPostProcessors
-
是MergedBeanDefinitionPostProcessor的 internalPostProcessors
這個internalPostProcessors 遍歷前面的時候都往這裏加,我還沒搞懂爲這個處理器是個什麼東西上面的順序就是註冊順序,即優先註冊實現了PriorityOrdered接口的 BeanPostProcessor,再給容器中註冊實現了Ordered接口的BeanPostProcessor,再註冊實現Oredered接口的,最後實現是MergedBeanDefinitionPostProcessor的
上面這些註冊調用的registerBeanPostProcessors如下:
拿到所有的後置處理器,調用beanFactory.addBeanPostProcessor ,即把BeanPostProcessor註冊到BeanFactory中
-
-
把容器applicationContext加入
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
創建BeanPostProcessor對象
註冊BeanPostProcessor,實際上就是創建BeanPostProcessor對象,保存在容器中
從registerBeanPostProcessors方法中
會調用beanFactory.getBean 來獲取對象(名字爲internalAutoProxyCreator,類型爲後置處理器),那我們第一次是沒有這個對象的 ,所以就會創建一個對象
-
beanFactory.getBean()
會調用doGetBeanpublic <T> T getBean(String name, Class<T> requiredType) throws BeansException { return this.doGetBean(name, requiredType, (Object[])null, false); }
-
doGetBean
首先通過getSingleton 獲取 這個單實例對象, 獲取不到,就用 createBean() 創建bean
-
getSingleton 先去獲取bean
首先通過getSingleton 用singletonFactory.getObject()獲取beansingletonObject = singletonFactory.getObject();
我們第一次訪問 肯定是沒有的, 所以肯定是要去創建
-
createBean() 創建bean
通過這一句調用return this.createBean(beanName, mbd, args);
參數:
調用doCreateBean
-
-
doCreateBean
-
創建bean的實例
-
屬性賦值
this.populateBean(beanName, mbd, instanceWrapper);
-
初始化bean initializeBean
-
invokeAwareMethods
處理Aware接口的方法回調(利用這些Aware接口對應的方法進行處理) -
applyBeanPostProcessorsBeforeInitialization
應用後置處理器的postProcessBeforeInitialization方法
-
invokeInitMethods
執行自定義的初始化方法 -
applyBeanPostProcessorsAfterInitialization
執行後置處理器的postProcessAfterInitialization方法
-
-
BeanFactoryAware
通過分析AnnotationAwareAspectJAutoProxyCreator的父類,我們知道它實現了 BeanFactoryAware,所以我們分析它作爲Aware做了哪些工作
實現了BeanFactoryAware的setBeanFactory方法的父類
首先找到所有實現了BeanFactoryAware的setBeanFactory方法的父類:
AbstractAdvisorAutoProxyCreator
AbstractAutoProxyCreator
所以上面創建IOC容器走到了doCreateBean 創建AnnotationAwareAspectJAutoProxyCreator類型的名爲internalAutoProxyCreator 的 bean 時
初始化initializeBean 中 先調用了invokeAwareMethods方法
invokeAwareMethods
由於 實現了BeanFactoryAware,所以這裏時true 就去調用setBeanFactory方法
setBeanFactory
調用的AnnotationAwareAspectJAutoProxyCreator的父類AbstractAdvisorAutoProxyCreator的setBeanFactory方法
- 父類的setBeanFactory方法
AbstractAdvisorAutoProxyCreator的父類AbstractAutoProxyCreator也實現了BeanFactoryAware,所以會調用 AbstractAutoProxyCreator的setBeanFactory方法 - AnnotationAwareAspectJAutoProxyCreator重寫的initBeanFactory方法
這個方法中調用了initBeanFactory方法,這個方法被AnnotationAwareAspectJAutoProxyCreator重寫了,所以調用的是AnnotationAwareAspectJAutoProxyCreator重寫的initBeanFactory方法
AnnotationAwareAspectJAutoProxyCreator 作爲後置處理器所做的工作
AnnotationAwareAspectJAutoProxyCreator 是一個後置處理器, 上面我們已經把它放在容器中了,之後任何組件在創建對象的時候 它就可以發揮作用
AnnotationAwareAspectJAutoProxyCreator 的父類AbstractAutoProxyCreator實現的是SmartInstantiationAwareBeanPostProcessor:
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
InstantiationAwareBeanPostProcessor 的方法是BeforeInstantiation
這個方法是BeforeInstantiation, 而我們之前接觸的BeanPostProcessor的BeforInitialization方法不一樣
因爲兩種後置處理器類型不一樣
- BeanPostProcessor
方法是BeforInitialization
是在Bean對象創建完成初始化前後調用的 - InstantiationAwareBeanPostProcessor
方法是BeforeInstantiation
是在創建Bean實例之前嘗試用後置處理器返回對象的
因此,AnnotationAwareAspectJAutoProxyCreator 會在任何bean創建之前嘗試返回bean的實例
finishBeanFactoryInitialization
首先還是創建ioc容器, 在refresh() 方法中調的是finishBeanFactoryInitialization
finishBeanFactoryInitialization 方法是用來完成beanFactory初始化的,也就是來創建剩下的單實例bean.(因爲之前已經創建了後置處理器之類的bean)
finishBeanFactoryInitialization 方法如下:
調用preInstantiateSingletons 創建剩餘的單實例
- preInstantiateSingletons
獲取容器中所有的bean 放到beanNames裏
然後遍歷beanNames, 通過getBean(beanName)來獲取對象
創建bean
-
getBean
getBean會調用doGetBeanpublic Object getBean(String name) throws BeansException { return this.doGetBean(name, (Class)null, (Object[])null, false); }
-
doGetBean
-
先從緩存中獲取當前bean
-
緩存中獲取不到再創建
-
-
createBean
-
resolveBeforeInstantiation 解析BeforeInstantiation
給後置處理器一個機會來返回代理對象,而不是target bean instance.也就是希望後置處理器能在此返回一個代理對象. 如果能返回代理對象就使用,如果不能就調用doCreateBean
-
doCreateBean
-
applyBeanPostProcessorsBeforeInstantiation
resolveBeforeInstantiation 中通過applyBeanPostProcessorsBeforeInstantiation方法嘗試返回代理對象
拿到所有的後置處理器,如果這個後置處理器是InstantiationAwareBeanPostProcessor,就調用postProcessBeforeInstantiation方法
postProcessBeforeInstantiation
關心我們的MathCalculator和LogAspect的創建
- 判斷當前bean是否在advisedBeans中
advisedBeans中保存了所有需要增強的bean, - 判斷當前bean是否是基礎類型isInfrastructureClass
基礎類型也就是是否實現了Advice\ PointCut\Advisor\AopInfrastructureBean