前提回顧
前一篇文章主要介紹了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的通知增強器
主要用於呼叫AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors()方法,其內部會進行先關的核心構建相關的Aspectj的類的相關實現操作
構建先關Aspectj類buildAspectJAdvisors方法
- 首先先進行獲取先關的所有容器的BeanName資料集合
- 在根絕上面的BeanName名稱集合獲取相關的BeanType型別集合
- 根據BeanType判斷當前的Bean是否屬於一個Aspectj的註解.類,如果不是則類不做任何處理。
構建實際的相關的Advisors類機制
advisorsFactory.getAdvisors獲取通知器
切點處理
切點類處理操作到此為止,還不完整接下來才是構建動態代理物件的真正執行操作,
- 獲取上面操作中獲取到的Aspectj類中的除了PointCut註解修飾的其他的方法列表。
- 根據對應的Aspectj類和相關的Advisors方法列表,建立相關的Advisor實現類,其中內部會進行遍歷相關上一步的方法列表,並且呼叫對應的方法method對應的getAdvisor方法,建立Advisor物件。
- 建立相關的AspectJExpressionPointCut物件,並且從方法裡的註解表示式進行解析,這最後設定到對應的門面層的Advisor物件例項。
- 實際的Advisor物件實現類物件的實際:InstantitationModelAwarePoincutAdvisorImpl例項,並且呼叫其內部的instantiateAdvice方法構建通知機制。
- 其內部仍然會呼叫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():執行目標方法
處理返回值,並且返回該值。