Spring aop(1)--- 尋找切面和代理對象執行流程源碼分析


1.基於注解,首先我們是通過@EnableAspectJAutoProxy()這個注解開起AOP功能,這個注解會導入AspectJAutoProxyRegistrar組件從而將AnnotationAwareAspectJAutoProxyCreator注冊到bean定義中。

 

 

 

2.如果容器有對應名字的bean定義,判斷下是不是這個class,如果不是就改成AnnotationAwareAspectJAutoProxyCreator,如果沒有就直接注冊進去,注冊bean定義名字叫org.springframework.aop.config.internalAutoProxyCreator。

 

 

 

 3.AnnotationAwareAspectJAutoProxyCreator看來這個類是比較重要的了,我們看一下它的繼承關系圖,可以看到這個類擴展了那些接口,可以看到他是BeanPostProcessor的實現類

 

 

 

 4.現在就直接來看之前在bean的實例化過程中第五點提到的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation這個方法中是尋找切面的過程。這個方法中其實就是去調用我們相應處理器的before和after方法

 

 

 applyBeanPostProcessorsBeforeInstantiation方法中我們看到其實會去調用InstantiationAwareBeanPostProcessor這個接口的postProcessBeforeInstantiation這個方法。從我們上面類圖中可以看到。我們通過@EnableAspectJAutoProxy注解注冊進去的AnnotationAwareAspectJAutoProxyCreator這個正是InstantiationAwareBeanPostProcessor這個的實現類,所以在這里必然會去調用AnnotationAwareAspectJAutoProxyCreator這個實現,但是這里使用了模板方法的設計模式,實際上的方法實現在其父類AbstractAutoProxyCreator這個中的方法。

 5.AbstractAutoProxyCreator類的postProcessBeforeInstantiation方法中會去判斷當前創建的類是否是基礎類,是否跳過設置,正是shouldSkip這個方法將切面找出來。

 

6.shouldSkip中會先調用父類的findCandidateAdvisors找事務切面,再調用自己的builder找其他的切面。

 

 

 7.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans中會獲取到所的bean,循環判斷是否是切面類,也就是是否標注了@Aspect注解的,再獲取切面類中的增強器,也就是@After,@Before,@AfterReturning,@AfterThrowing,@Around這幾個。找到了之后再加入到緩存中。

 

 

 

 

 8.后面的類再進來就直接緩存里面拿出來就行了,不需要再去尋找切面了

 

9.接下來就是在在bean創建好之后會通過bean的后置處理器創建代理對象返回,並且在代理對象中織入我們的增強器。

10.現在來看AbstractAutoProxyCreator#postProcessAfterInitialization這個方法中的一些邏輯,從緩存中拿到我們之前的找到的增強器信息,並且找到匹配當前類的增強器。

 

 

 

 11.找到之后又有一步排序的操作,這個就決定了我們增強器的執行順序。找到了增強器說明需要生成代理,沒有增強器就不需要代理。

 

 

12.如果需要創代理對象,則判斷我們代理分方式@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true),第一個參數是是否暴露我們代理對象,如果暴露了可以當前原型類中通過AopContext.currentProxy(),獲取到代理對象。如下圖兩種調用方式:一種會被切,一種不會

 

 

 第二個參數是是否強制只用cglib代理。

 

 

 

 

 判斷是何種代理

 

 13.可以看到返回的代理對象里面是有我們的增強器信息的。

 

 至此切面尋找,代理對象創建,增強器織入都完成了,接下來就是我們執行目標方法的時候,這些增強器是如何執行的。

14.代理對象調用方法的時候會將增強器轉換成攔截器鏈,就是根據上說到的排序順序。

 

 

如下圖:

 

 

 

15.然后創建一個反射方法的執行器執行proceed()方法 進行一個遞歸的調用,這里的調用有點繞,初始下標-1,然后通過前++的方式從攔截器鏈中獲取出來執行,當最后都取完了的時候才執行目標方法,通過斷點調試會發現調用順序如下圖:

 

 

 因為是遞歸的調用所以最先執行結束卻是54321的順序,這就是為什么@Before是在方法執行之前執行,可以看到@AfterThrowing是在try-catch中執行的增強器方法。@After是在一個try-finally中執行的,所以這個始終會被執行。

 

 

 

 

 

 

 

 

 這就是整個Spirng整個AOP的流程。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM