【Spring專場】「AOP容器」不看源碼就帶你認識核心流程以及運作原理

前提回顧

前一篇文章主要介紹了spring核心特性機制的IOC容器機制和核心運作原理,接下來我們去介紹另外一個較爲核心的功能,那就是AOP容器機制,主要負責承接前一篇代理模式機制中動態代理:JDKProxy和CglibProxy的功能機制之後,我們開始研究一下如何實現一下相關的AOP容器代理機制的。

AOP入口機制

如何實現將Aspectj的動態weave織入到Spring容器的Bean中?

實現的基本實現原理就是後置處理器:BeanPostProcessor機制,實現動態化植入機制。

如何實現相關的Aspectj的weave織入時機

bean在初始化的時候會進行調用對應的BeanPostProcessor的對應的方法會進行織入。

判斷的基本流程

主要取決於wrapIfNecessary方法:

判斷當前的Bean是AOP的基礎設施類型

如果是基礎設施類型,則直接回進行返回該bean對象,不會進行相關的初始化對應的aspectj的動態織入機制。

如果屬於定製化的bean對象類型

會進行尋找相關的Bean對應的何時的加強通知類。

如果對應該對象的通知增強數組集合不爲空

則會對該bean對象,額外進行增強操作生成相關的代理對象,並返回該執行之後的對象,否則會直接返回該對象即可。

篩選何時的通知器

getAdvicesAndAdvisorsForBean方法是我們篩選Advice增強類的核心方法,主要用於過濾和篩選對應該bean的何時的增強器數組信息。

查找對應Bean的通知增強器

主要用於調用AnnotationAwareAspectJAutoProxyCreatorfindCandidateAdvisors()方法,其內部會進行先關的核心構建相關的Aspectj的類的相關實現操作

構建先關Aspectj類buildAspectJAdvisors方法

  1. 首先先進行獲取先關的所有容器的BeanName數據集合
  2. 在根絕上面的BeanName名稱集合獲取相關的BeanType類型集合
  3. 根據BeanType判斷當前的Bean是否屬於一個Aspectj的註解.類,如果不是則類不做任何處理。

構建實際的相關的Advisors類機制

advisorsFactory.getAdvisors獲取通知器

切點處理

切點類處理操作到此爲止,還不完整接下來纔是構建動態代理對象的真正執行操作,

  1. 獲取上面操作中獲取到的Aspectj類中的除了PointCut註解修飾的其他的方法列表。
  2. 根據對應的Aspectj類和相關的Advisors方法列表,創建相關的Advisor實現類,其中內部會進行遍歷相關上一步的方法列表,並且調用對應的方法method對應的getAdvisor方法,建立Advisor對象。
  3. 創建相關的AspectJExpressionPointCut對象,並且從方法裏的註解表達式進行解析,這最後設置到對應的門面層的Advisor對象實例。
  4. 實際的Advisor對象實現類對象的實際:InstantitationModelAwarePoincutAdvisorImpl實例,並且調用其內部的instantiateAdvice方法構建通知機制。
  5. 其內部仍然會調用getAdvice方法,並且構建相關的註解的類型創建相應的通知。

篩選何時的通知器並且執行應用

findAdvisorsThatCanApply方法

擴展相關的篩選出的通知器列表,extendAdvisors方法,通知器列表首部添加一個DefaultPointcutAdivosr類型的通知器,也就是ExposeInvocationInterceptor.ADVISOR的實現機制。

創建代理對象

  • jdk動態代理
  • cglib動態代理
proxy-target-class

proxy-target-class的屬性值,代表是否可以支持代理實現類,默認採用的false代表着,當bean有實現接口的時候,會直接採用jdk的動態代理機制生成代理對象,如果是true,則代表着使用cglib進行生成代理對象。

例如:
<aop:aspectj-autoproxy proxy-target-class = "true" /></aop>
AopProxy接口
  • CglibAopProxy接口實現
  • JdkDynamicAopProxy接口實現

AOP代理對象調用同類的方法問題解決方案

expose-proxy作用

前提是必須要配置相關的expose-proxy屬性配置值爲true,纔會進行暴露對應的代理機制。

爲了解決目標方法調用同對象中的其他方法,其他方法的切面邏輯是無法實現,因爲會涉及到相關的this操作而不是proxy對象機制。

可以實現使用AopContext.currentProxy()強制轉換爲當前的代理對象。

攔截器鏈路執行

intercept方法機制

獲取相關的對應方法的攔截器棧鏈路,如果沒有獲取到相關的緩存鏈路,則會直接調用相關的getInterceptorsAndDynamicInterceptorAdvice獲取先關的攔截器鏈。

方法攔截器相關的攔截操作連接點

會進行先關的PointcutAdvisor類型通知器,這裏會調用相關的通知器所持有的切點(Pointcut)對類和方法進行匹配,匹配衝過這說明相關的向當前的方法進行織入邏輯控制。此外還會通過geIntercptors()方法對非MethodIntercptor類型的通知進行轉換。返回相關的攔截器數組,並且隨後存入緩存中。

執行目標方法的方式

如果攔截器爲空

則會直接通過代理機制的反射控制進行調用執行即可。

如果不爲空

則例如jdkDynamicAutoProxy對象進行調用構建ReflectiveMethodInvocation對象,例如它的process方法啓動攔截器棧的invoke方法。

  • invoke:執行攔截器棧
  • invokeJoinpoin():執行目標方法

處理返回值,並且返回該值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章