向您圖文并茂生動講解Spring AOP 源碼(2)

前言

往期文章:

在上一章向您生動地講解Spring AOP 源碼(1)中捏浊,作者介紹了【開啟AOP自動代理的玄機】和【自動代理的觸發(fā)時機】。

在本章中,作者會向您介紹溉跃,Spring AOP 是如何解析我們配置的Aspect撇吞,生成 Advisors 鏈的吸申?

閑話不多說胖齐,讓我們直接開始肠套。

獲取對應 Bean 適配的Advisors 鏈

獲取對應 Bean 適配的 Advisors 鏈根竿,分為兩步陵像。

  1. 獲取容器所有的 advisors 作為候選,即解析Spring 容器中所有 Aspect 類中的 advice 方法寇壳,包裝成 advisor醒颖;
  2. 從候選的 Advisors 中篩選出適配當前 Bean的 Advisors 鏈;

未免讀者閱讀不連貫壳炎,我們重新貼一下上篇文章中我們最后講解的一段源碼泞歉,由此繼續(xù)往下講述。

源碼位置:AbstractAutoProxyCreator#wrapIfNecessary(..)

wrapIfNecessary

源碼位置:AspectJAwareAdvisorAutoProxyCreator#shouldSkip(..)

shouldSkip.png

源碼位置:AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(..)冕广、AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(..)

getAdvicesAndAdvisorsForBean.png

可以看到兩個方法都調用了findCandidateAdvisors()方法疏日,也就是去獲取候選的 Advisors,我們進去看看里面干了什么撒汉。

1. 獲取候選的 Advisors

findCandidateAdvisors.png
image.png
image.png

從Debug 出來的線程椆涤牛可以看出,AnnotationAwareAspectJAutoProxyCreator 通過 持有 BeanFactoryAspectJAdvisorsBuilder對象睬辐,來獲取Advisor鏈挠阁。

再往下看。源碼位置:BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

內容較長溯饵,請大家跟著注釋耐心看下去侵俗。

buildAspectJAdvisors1.png

這個方法除了等下要講 advisorFactory.getAdvisors(..)以外,需要注意的就是其為了避免每次都去獲取所有的beanName丰刊,解析判斷隘谣,引入了緩存的機制;還有就是Aspect類是根據(jù)Spring Bean 是否被 @Aspect注解修飾來判斷的。

我們接下去看寻歧,真正的去獲取我們的Advisor的方法掌栅,this.advisorFactory.getAdvisors(factory) 方法如下:

源碼位置:ReflectiveAspectJAdvisorFactory#getAdvisors(..)

getAdvisors.png

解析advice 方法成 advisor對象,

源碼位置:ReflectiveAspectJAdvisorFactory#getAdvisor(..)

getAdvisor.png
生成advisor

如何生成advisor也值得一提码泛。

注釋方式下猾封,我們聲明的advice 方法是這樣的。(不熟悉范例的可以看上一篇文章)

@Aspect
@Component
public class PointCutConfig {
    // ... 省略
    // service 層
    @Pointcut("within(ric.study.demo.aop.svc..*)")
    public void inSvcLayer() {}
    // ... 省略
}
@Aspect
@Component
public class GlobalAopAdvice {

    @Before("ric.study.demo.aop.PointCutConfig.inSvcLayer()")
    public void logBeforeSvc(JoinPoint joinPoint) {
        System.out.println("在service 層前打印日志");
        System.out.println("攔截的service 方法的方法簽名: " + joinPoint.getSignature());
    }
}
advice方法.png

生成之后是這樣的噪珊,

image.png

advice 的對象類型是InstantiationModelAwarePointcutAdvisorImpl晌缘,我們來看下生成advisor時調用的這個類的構造函數(shù),

InstantiationModelAwarePointcutAdvisorImpl.png

里面包括了一個重要的方法instantiateAdvice痢站,即創(chuàng)建Advice磷箕,這也是我要強調的重點,怎么解析出來一個advice瑟押。

源碼位置:InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice(..)

image

源碼位置:ReflectiveAspectJAdvisorFactory#getAdvice(..)

image
第一次解析Advisor的時機

關于第一次解析Advisor的時機搀捷,我剛開始也搞混了。所以在這里說明一下多望。

這個圖是之前貼過的,第一次觸發(fā)的截圖氢烘。

AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現(xiàn)了InstantiationAwareBeanPostProcessor接口:

image.png

會在生成target class 對象之前怀偷,調用 postProcessBeforeInstantiation(..),具體的代碼可以去看AbstractAutowireCapableBeanFactory#createBean(..)方法播玖。我們這邊直接看一下 postProcessBeforeInstantiation(..)AbstractAutoProxyCreator中的實現(xiàn)椎工。

postProcessBeforeInstantiation.png

2. 篩選 出 適配當前類的 Advisors

這里來一條分割線,至此蜀踏,findCandidateAdvisors()算是解析完畢了维蒙。

但是我們通過這個方法只是獲得了所有候選的advisors,還記得我們這一節(jié)的標題不果覆?

【獲取對應 Bean 適配的Advisors 鏈】

那么我們下一步就是要過濾出適配當前這個 target class 的 advisors颅痊。

findEligibleAdvisors.png

也就是上圖的findAdvisorsThatCanApply(..)

Search the given candidate Advisors to find all Advisors that can apply to the specified bean.

從給出的候選 Advisors 找出可以作用在 當前bean 的 Advisors 鏈

Debug階段,篩選之前的候選 advisors 和篩選之后的可用的 advisors局待,

image.png

源碼位置:AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply(..)

findAdvisorsThatCanApply.png

源碼位置:AopUtils#findAdvisorsThatCanApply(..)

image

我們接下去看篩選的關鍵方法``AopUtils#canApply(..)`

image
image

篩選的工作主要由 ClassFilter 和 MethodMatcher 完成斑响,比如AspectJExpressionPointcut的實現(xiàn)了ClassFilter和MethodMatcher接口,最終由AspectJ表達式解析钳榨,這個地方就復雜了舰罚,也不是核心點。


又是一條分割線薛耻。

到這里之后营罢,Advisor的篩選過程我們算是講完了。

findEligibleAdvisors2.png

經(jīng)過排序之后饼齿,我們算是拿到了這個目標類使用的 Advisors 鏈饲漾。

小結

到這里瘟滨,大家可以回顧一下,我們總算是把TODO-1【Spring AOP 如何 獲取對應 Bean 適配的Advisors 鏈】介紹完畢了能颁,總結一下核心邏輯就是:

  1. 獲取當前 IoC 容器中所有的 Aspect 類
  2. 給 每個Aspect 類的advice 方法創(chuàng)建一個 Spring Advisor杂瘸,這一步又能細分為
    1. 遍歷所有advice 方法
    2. 解析方法的注解和pointcut
    3. 實例化 Advisor 對象
  3. 獲取到 候選的 Advisors,并且緩存起來伙菊,方便下一次直接獲取
  4. 從候選的 Advisors 中篩選出與目標類 適配的Advisor
    1. 獲取到 Advisor 的 切入點 pointcut
    2. 獲取到 當前 target 類 所有的 public 方法
    3. 遍歷方法败玉,通過 切入點 的 methodMatcher 匹配當前方法,只有有一個匹配成功就相當于當前的Advisor 適配
  5. 對篩選之后的 Advisor 鏈進行排序
  6. 結束

下一節(jié)中镜硕,我們會介紹 【代理類的創(chuàng)建過程】运翼,我們下次再會。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末兴枯,一起剝皮案震驚了整個濱河市血淌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌财剖,老刑警劉巖悠夯,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異躺坟,居然都是意外死亡沦补,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門咪橙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夕膀,“玉大人,你說我怎么就攤上這事美侦〔瑁” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵菠剩,是天一觀的道長易猫。 經(jīng)常有香客問我,道長赠叼,這世上最難降的妖魔是什么擦囊? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮嘴办,結果婚禮上瞬场,老公的妹妹穿的比我還像新娘。我一直安慰自己涧郊,他們只是感情好贯被,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般彤灶。 火紅的嫁衣襯著肌膚如雪看幼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天幌陕,我揣著相機與錄音诵姜,去河邊找鬼。 笑死搏熄,一個胖子當著我的面吹牛棚唆,可吹牛的內容都是我干的。 我是一名探鬼主播心例,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼宵凌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了止后?” 一聲冷哼從身側響起瞎惫,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎译株,沒想到半個月后瓜喇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡古戴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年欠橘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片现恼。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖黍檩,靈堂內的尸體忽然破棺而出叉袍,到底是詐尸還是另有隱情,我是刑警寧澤刽酱,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布喳逛,位于F島的核電站,受9級特大地震影響棵里,放射性物質發(fā)生泄漏润文。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一殿怜、第九天 我趴在偏房一處隱蔽的房頂上張望典蝌。 院中可真熱鬧,春花似錦头谜、人聲如沸骏掀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽截驮。三九已至笑陈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間葵袭,已是汗流浹背涵妥。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坡锡,地道東北人蓬网。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像娜氏,于是被迫代替她去往敵國和親拳缠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容