1. 程式人生 > >知識儲備:詳解Spring中AOP原理(基於註解版)2

知識儲備:詳解Spring中AOP原理(基於註解版)2

接著上一篇部落格講,上一篇部落格地址:https://blog.csdn.net/qq_36625757/article/details/83652173

8.之前我們說過,測試方法在執行時new了一個AnnotationConfigApplicationContext傳入一個配置類,呼叫了refresh()方法,在refresh()方法中,首先呼叫registerBeanPostProcessors(beanFactory);建立並初始化後置處理器,也就是1-6步,之後又呼叫了finishBeanFactoryInitialization(beanFactory);完成BeanFactory的初始化工作,就是來建立剩下的單例項bean,在建立的過程中就會被各個後置處理器攔截掉,下面我們就看看finishBeanFactoryInitialization(beanFactory);

9.進入到finishBeanFactoryInitialization(beanFactory);中,就會看到來到beanFactory.preInstantiateSingletons();建立bean

進入preInstantiateSingletons()方法中,看到在迴圈所有bean建立物件,通過getBean(beanName);建立。

最後來到doGetBean(name, null, null, false);方法,首先檢查單例項的快取中是否存在當前物件

如果存在就直接返回,否則就通過呼叫 getSingleton()獲得單例項bean,只要建立好的bean就會被快取起來,保證單例項bean

之後呼叫createBean(beanName,mbd,args);建立bean

進入到createBean()後就會呼叫resolveBeforeInstantiation(beanName, mbdToUse);方法,希望後置處理器再此能返回一個代理物件,如果能返回就是使用,否則就呼叫下面的doCreateBean()建立,對於doCreateBean()方法之前已經詳細介紹過了,就是先建立bean例項,然後為bean屬性賦值,然後在呼叫bean的init方法前後呼叫後置處理器等等操作。

我們來到resolveBeforeInstantiation(beanName, mbdToUse);中看看是如何建立代理物件的

先呼叫applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);方法,進入其中,看到

先迴圈所有後置處理器,判斷是不是InstantiationAwareBeanPostProcessor型別的後置處理器,如果是就呼叫他的postProcessBeforeInstantiation(beanClass, beanName);方法,而我們之前已經說過AnnotationAwareAspectJAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor型別的後置處理器,而SmartInstantiationAwareBeanPostProcessor又繼承了InstantiationAwareBeanPostProcessor所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor這種型別的後置處理器,最後就會呼叫AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation()方法,我們就來看看postProcessBeforeInstantiation()方法都幹了寫啥?

10.現在我們就關心我們自己建立的LogAspect和MathCal是怎樣建立的?我們的MathCal來到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法(AnnotationAwareAspectJAutoProxyCreator中沒有postProcessBeforeInstantiation()方法的實現,只能呼叫父類的方法),首先判斷是否在advisedBeans中,advisedBeans中儲存了所有需要增強的bean。第一次建立是不會包含的,所有if沒進去。

 然後就來到第二個判斷,首先判斷當前bean是否是基礎型別即判斷是否是實現了Advice,Pointcut,Advisor,AopInfrastructureBean這幾個介面,其次還會判斷是否是加了@Aspect註解的

最後再通過shouldSkip(beanClass, beanName)判斷是否需要跳過

在shouldSkip()中首先獲得四個增強器即切面中的四個通知方法,將通知方法包裝為InstantiationModelAwarePointcutAdvisor型別的,判斷增強器是否是AspectJPointcutAdvisor型別的,而我們的型別不是,機會呼叫父類的super.shouldSkip(beanClass, beanName);返回false,最後就返回null,來到我們的logConfig配置中

之後又來到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

呼叫wrapIfNecessary(bean, beanName, cacheKey);進入其中

獲得所有候選增強器,然後獲得當前bean增強器(通知方法),如何獲取呢?

獲得增強器後進行排序,最後將增強器封裝為Object[]陣列

儲存當前bean到advisedBeans中表示當前bean已經增強,之後通過createProxy()建立代理物件,進入其中

現獲得所有增強器(通知方法),儲存到proxyFactory中,通過proxyFactory.getProxy(getProxyClassLoader());獲得代理物件

進入其中

spring自動決定使用JDK方式代理還是使用Cglib方式代理

至此就創建出代理物件啦,並返回回去了,以後容器中拿到的就是代理物件了,接下來拿到代理物件,如何呼叫增強方法,將會在下一篇部落格中繼續解析。