Spring框架之AOP原始碼完全解析
Spring框架之AOP原始碼完全解析
Spring可以說是Java企業開發裡最重要的技術。Spring兩大核心IOC(Inversion of Control控制反轉)和AOP(Aspect Oriented Programming面向切面程式設計)。IOC技術我們在上一篇文章“Spring框架之beans原始碼完全解析”中進行了分析,本文對Spring框架的AOP原始碼進行分析。
AOP面向切面程式設計是通過預編譯方式和執行其動態代理,實現在不修改原始碼的情況下給程式動態統一新增功能的一種技術,是OOP面向物件程式設計的有效補充。利用AOP技術將日誌記錄,效能統計,安全控制,事務處理,異常處理等程式碼從業務邏輯程式碼中劃分出來,通過對這些行為的分離,可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不會影響業務邏輯的程式碼,實現瞭解耦,提高了程式碼的靈活性和可擴充套件性。
下面就Spring框架的AOP原始碼進行解析,主要從以下幾個方面進行剖析:一是對Spring的幾個關鍵概念進行闡述;二是對AOP原始碼檔案清單進行梳理,一共9大類,204個java檔案。三是Spring主要使用JDK動態代理來實現AOP,對JDK動態代理做了一個簡單的介紹。四是結合原始碼對Spring AOP的實現原理進行了分析。
文章目錄
一、Spring AOP幾個關鍵概念
1、AOP聯盟
2、AOP、Spring AOP、AspectJ的區別
3、Spring AOP 10個常見概念
4、Advice(通知/增強)
5、Advisor(顧問/增強器)
6、Pointcut(切點)
7、TargetSource(目標物件)
8、Interceptor(攔截器)
二、AOP原始碼檔案清單
1、aopalliance包含的介面和類
2、AOP包含的介面和類
3、AOP/aspectj包含的介面和類
4、AOP/config包含的介面和類
5、AOP/framework包含的介面和類
6、AOP/interceptor包含的介面和類
7、AOP/scope包含的介面和類
8、AOP/support包含的介面和類
9、AOP/target包含的介面和類
三、JDK動態代理
(一)什麼是代理
(二)Java的動態代理類
(三)動態代理的步驟
四、Spring AOP的實現原理
(一)標籤的解析
(二)獲取增強方法或者增強器
(三)根據獲取的增強建立代理
(四)織入
一、Spring AOP幾個關鍵概念
1、AOP聯盟
AOP聯盟規範了一套用於規範AOP實現的底層API,通過這些統一的底層API,可以使得各個AOP實現及工具產品之間實現相互移植。這些API主要以標準介面的形式提供,是AOP程式設計思想所要解決的橫切交叉關注點問題各部件的最高抽象。Spring的AOP框架中也直接以這些API為基礎構建。下面我們來看看當前AOP聯盟釋出的AOP相關的標準介面。
AOP聯盟的API主要包括四個部分,第一個是aop包,定義了一個表示通知Advice的標識介面,各種各樣的通知都繼承或者實現了該介面。aop包中還包括了一個用於描述AOP系統框架錯誤執行時異常AspectException。
第二個部分是intercept包,也就是攔截器包,這個包中規範了AOP核心概念中的連線點及通知Advice的型別。
第三部分及第四部分是instrument及reflect包。這兩個包中的API主要包括AOP框架或者產品為了實現把橫切關注點的模組和核心應用模組組合整合,所需要使用的設施、技術及底層實現規範等。
aopalliance1.0.jar類結構如下圖所示(未包括第三、四部分):
aopalliance有三個主要的業務實體:Joinpoint 、Advice、Interceptor。這三個介面構成了aopalliance功能結構。
1、Joinpoint:程式在執行過程中一個執行時Joinpoint,在這些點關聯的靜態位置通常會安裝有一些Interceptor,當程式執行到這個執行時Joinpoint時,AOP框架會攔截執行時Joinpoint的執行,把執行時Joinpoint交給已經安裝的Interceptor們進行處理。JoinPoint介面有三個方法:
proceed():該方法用於執行攔截器邏輯;
getThis():返回保持當前連線點的靜態部分的物件;
getStaticPart():返回此連線點的靜態部分(通常包含建構函式,成員變數,方法等資訊)
2、Advice只是起到一個超類標記功能。Advice(通知)定義了AOP框架在某個Joinpoint(連線點)的通用處理邏輯。
3、Interceptor(攔截器)。Interceptor繼承了Advice,可以看成是對Advice的特殊功能實現。Interceptor只是Advice處理邏輯中的一種型別或者方式,表示的僅僅是採用攔截處理機制實現了Advice這種功能。
Advice和Interceptor兩個介面沒有任何操作,都是標記介面。(標識介面就是空方法的介面。與其他介面的區別是:這個接口裡面什麼方法都沒有,只是標記而已。例如serilizeabled就是這樣一個介面,他只是告訴jvm,繼承於這個介面的CLASS需要序列化處理,我們不用實現這個介面的方法。)
2、AOP、Spring AOP、AspectJ的區別
(1)AOP:Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期間動態代理實現程式功能的統一維護的一種技術。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
(2)AspectJ:AspectJ來自於 Eclipse 基金會,屬於靜態植入,它是通過修改程式碼來實現的,它的植入時機可以是:Compile-time weaving編譯期織入;Post-compile weaving編譯後織入,也就是已經生成了.class 檔案,或已經達成 jar 包了;Load-time weaving指的是在載入類的時候進行織入。AspectJ 能幹很多 Spring AOP 幹不了的事情,它是 AOP 程式設計的完全解決方案。
(3)SpringAOP:它基於動態代理來實現AOP。如果使用介面的,用JDK提供的動態代理實現,如果沒有介面,使用 CGLIB 實現。Spring AOP 致力於解決的是企業級開發中最普遍的 AOP 需求(方法織入),而不是力求成為一個像 AspectJ 一樣的 AOP 程式設計完全解決方案。
AOP是一種概念,springAOP、AspectJ都是AOP的實現,Spring AOP有自己的語法,但是語法複雜,所以SpringAOP藉助了AspectJ的註解,但是底層實現還是自己的。
3、Spring AOP 10個常見概念
(1)Joinpoint(連線點)
程式執行的某個特定位置,比如某個方法呼叫前、呼叫後,方法丟擲異常後,對類成員的訪問以及異常處理程式塊的執行等。一個類或一段程式程式碼擁有一些具有邊界性質的特定點,這些程式碼中的特定點就是連線點。它自身還可以巢狀其他的Joinpoint。AOP中的Joinpoint可以有多種型別:構造方法呼叫,欄位的設定和獲取,方法的呼叫,方法的執行,異常的處理執行,類的初始化。Spring僅支援方法執行型別的Joinpoint。
(2)Pointcut(切點)
如果連線點相當於資料中的記錄,那麼切點相當於查詢條件,一個切點可以匹配多個連線點。所以切點表示一組Joinpoint,這些Jointpoint或是通過邏輯關係組合起來,或是通過通配、正則表示式等方式集中起來,它定義了相應的 Advice 將要發生的地方。
(3)Advice(通知/增強)
通知是織入到目標類連線點上的一段程式程式碼。Spring提供的通知介面都是帶方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。我們通過AOP將橫切關注功能加到原有的業務邏輯上,這是對原有業務邏輯的一種增強,可以是前置、後置、返回後、丟擲異常時等。其實Advice翻譯成“增強”更合理,更能準確表達其本質。既然大部分文獻都是稱為通知,我們這裡也稱為通知。
(4)Introduction(引介)
引介是一種特殊的通知,它為類新增一些屬性和方法。這樣,即使一個業務類原本沒有實現某個介面,通過引介功能,可以動態的為該業務類新增介面的實現邏輯,讓業務類成為這個介面的實現類。
(5)Interceptor(攔截器)
在Advice的基礎上擴充套件定義,定義了通知的增強方式,也就是通過對Joinpoint(連線點)的攔截。一個通用的攔截器可以攔截髮生在基礎程式中的執行時事件。
(6)Aspect(切面)
切面是由Pointcut(切點)和Advice(通知)組成的,它包括了對橫切關注功能的定義,也包括了對連線點的定義。
(7)Advisor(顧問/增強器)
Advisor是切面的另一種實現,繫結通知跟切點。沒有指定切點的通知是沒有意義的,Advisor可以說就是一個繫結在指定切點上的通知。它能夠將通知以更為複雜的方式織入到目標物件中,是將通知包裝為更復雜切面的裝配器。
(8)TargetSource(目標物件)
包含連線點的物件。也被稱作被通知或被代理物件。
(9)Proxy(代理物件)
包含了原始物件的程式碼(是在合適的位置呼叫目標物件的方法)和增加後的程式碼(Advice通知的內容)的那個物件。
(10)Weaving(織入)
織入是將Advice通知新增到目標類具體連線點上的過程,AOP有三種織入方式:①編譯期織入:需要特殊的Java編譯期(例如AspectJ的ajc);②裝載期織入:要求使用特殊的類載入器,在裝載類的時候對類進行增強;③執行時織入:在執行時為目標類生成代理實現增強。
AspectJ採用了編譯期織入和裝載期織入的方式,Spring採用了動態代理的方式實現了執行時織入。
4、Advice(通知/增強)
Advice有以下幾種常見的型別:
1、AspectJMethodBeforeAdvice:前置通知。AspectJ中 before 屬性對應的通知(@Before標註的方法會被解析成該通知),在切面方法執行之前執行。
2、AspectJAfterReturningAdvice:後置通知。AspectJ中 afterReturning 屬性對應的通知(@AfterReturning 標註的方法會被解析成該通知),在切面方法執行之後執行,如果有異常,則不執行。注意:該通知與AspectJMethodBeforeAdvice對應。
3、AspectJAroundAdvice:環繞通知。AspectJ中 around 屬性對應的通知(@Around標註的方法會被解析成該通知),在切面方法執行前後執行。
4、AspectJAfterAdvice:返回通知。AspectJ中 after 屬性對應的通知(@After 標註的方法會被解析成該通知),不論是否異常都會執行。
5、AspectJAfterThrowingAdvice:異常通知,AspectJ中 after 屬性對應的通知(@AfterThrowing標註的方法會被解析成該通知),在連線點丟擲異常後執行。
5、Advisor(顧問/增強器)
advisor:顧問(切面的另一種實現),封裝了spring aop中的切點和通知。通知(advice)中包含了增強的橫切程式碼,切點(pointcut)包含了連線點的描述資訊。
1、StaticMethodMatcherPointcut:靜態方法切面。定義了一個classFilter,通過重寫getClassFilter()方法來指定切面規則。另外實現了StaticMethodMatcher介面,通過重寫matches來指定方法匹配規則。
2、StaticMethodMatcherPointcutAdvisor:靜態方法匹配切面顧問。擴充套件了切面排序方法。
3、NameMatchMethodPointcut:名稱匹配切面。通過指定方法集合變數mappedNames,模糊匹配。
4、NameMatchMethodPointcutAdvisor:方法名稱切面顧問。內部封裝了NameMatchMethodPointcut,通過設定方法名稱模糊匹配規則和通知來實現切面功能。
5、RegexpMethodPointcutAdvisor:正則表示式切面顧問。可設定多個正則表示式規則,通過內部封裝的JdkRegexpMethodPointcut解析正則表示式。
6、DefaultPointcutAdvisor:預設切面顧問。比較靈活,可自由組合切面和通知。
7、InstantiationModelAwarePointcutAdvisorImpl:springboot自動裝配的顧問型別。是最常用的一種顧問實現。在註解實現的切面中,所有@Aspect類,都會被解析成該物件。
advisorCreator:繼承 spring ioc的擴充套件介面 beanPostProcessor,主要用來掃描獲取advisor。
1、AbstractAutoProxyCreator:Spring 為Spring AOP 模組暴露的可擴充套件抽象類,也是 AOP 中最核心的抽象類。
2、BeanNameAutoProxyCreator:根據指定名稱建立代理物件。通過設定 advisor,可以對指定的 beanName 進行代理。支援模糊匹配。
3、AbstractAdvisorAutoProxyCreator:功能比較強大,預設掃描所有Advisor的實現類。相對於根據Bean名稱匹配,該類更加靈活。動態的匹配每一個類,判斷是否可以被代理,並尋找合適的增強類,以及生成代理類。
4、DefaultAdvisorAutoProxyCreator:AbstractAdvisorAutoProxyCreator的預設實現類。可以單獨使用,在框架中使用AOP,儘量不要手動建立此物件。
5、AspectJAwareAdvisorAutoProxyCreator:AspectJ的實現方式,也是Spring Aop中最常用的實現方式,如果用註解方式,則用其子類AnnotationAwareAspectJAutoProxyCreator。
6、AbstractAutoProxyCreator:Spring 為Spring AOP 模組暴露的可擴充套件抽象類,也是 AOP 中最核心的抽象類。
7、AnnotationAwareAspectJAutoProxyCreator:目前最常用的AOP使用方式。spring aop 開啟註解方式之後,該類會掃描所有@Aspect()註釋的類,生成對應的advisor。目前SpringBoot框架中預設支援的方式,自動配置。
6、Pointcut(切點)
1、AnnotationMatchingPointcut:註解匹配切點。根據類上或方法上是否存在指定的註解判斷切點的匹配性,如果沒有顯示指定註解,則匹配所有。
2、DynamicMethodMatcherPointcut:動態方法匹配器切點。它本質上是一個方法匹配器,但同時具有了切點的功能。
3、ComposablePointcut:可組合的切點。這種切點可以與或邏輯,任意組合其他的Pointcut、ClassFilter和MethodMatcher。其本質是通過ClassFilters和MethodMatchers兩個工具類進行Pointcut內部元件的組合。
4、JdkRegexpMethodPointcut: JDK正則表示式切點,即使用正則表示式描述方法的攔截規則和排除規則。
5、AspectJExpressionPointcut:AspectJ切點表示式切點。顧名思義,使用AspectJ的切點表示式描述篩選規則。表示式基本語法如下(非完整語法):execution(<方法修飾符>? <方法返回值型別> <包名>.<類名>.<方法名>(<引數型別>) [throws <異常型別>]?)
其中,‘*’代表0個或多個任意字元,包名中的..(兩個點)代表當前包及其子包,引數列表中的..代表任意個引數。如:execution(public static * *..*.*(..) throws *),此表示式匹配所有方法。
7、TargetSource(目標物件)
TargetSource被用於獲取當前MethodInvocation(方法呼叫)所需要的target(目標物件),這個target通過反射的方式被呼叫(如:method.invode(target,args))。換句話說,proxy(代理物件)代理的不是target,而是TargetSource。
為什麼Spring AOP代理不直接代理target,而需要通過代理TargetSource(target的來源,其內部持有target),間接代理target呢?
通常情況下,一個proxy(代理物件)只能代理一個target,每次方法呼叫的目標也是唯一固定的target。但是,如果讓proxy代理TargetSource,可以使得每次方法呼叫的target例項都不同(當然也可以相同,這取決於TargetSource實現)。這種機制使得方法呼叫變得靈活,可以擴展出很多高階功能,如:target pool(目標物件池)、hot swap(執行時目標物件熱替換)等等。
TargetSource元件本身與Spring IoC容器無關,target的生命週期不一定是受spring容器管理的,我們以往的XML中的AOP配置,只是對受容器管理的bean而言的,我們當然可以手動建立一個target,同時使用Spring的AOP框架(而不使用IoC容器)
TargetSource包含4個簡單實現和3大類實現。
4個簡單實現包括:
(1)EmptyTargetSource:靜態目標源,當不存在target目標物件,或者甚至連targetClass目標類都不存在(或未知)時,使用此類例項。
(2)HotSwappableTargetSource:動態目標源,支援熱替換的目標源,支援spring應用執行時替換目標物件。
(3)JndiObjectTargetSource:spring對JNDI管理bean的支援,static屬性可配置。
(4)SingletonTargetSource:靜態目標源,單例目標源。Spring的AOP框架預設為受IoC容器管理的bean建立此目標源。換句話說,SingletonTargetSource、proxy與目標bean三者的宣告週期均相同。如果bean被配置為prototype,則spring會在每次getBean時建立新的SingletonTargetSource例項。
3大類實現包括:
(1)AbstractBeanFactoryBasedTargetSource:此類目標源基於IoC容器實現,也就是說target目標物件可以通過beanName從容器中獲取。此類又擴展出:① SimpleBeanTargetSource:簡單實現,直接呼叫getBean從容器獲取目標物件;② LazyInitTargetSource:延遲初始化目標源,子類可重寫postProcessTargetObject方法後置處理目標物件;③AbstractPrototypeBasedTargetSource:原型bean目標源,此抽象類可確保beanName對應的bean的scope屬性為prototype。其子類做了簡單原型、池化原型、執行緒隔離原型這3種實現。
(2)AbstractRefreshableTargetSource:可重新整理的目標源。此類實現可根據配置的重新整理延遲時間,在每次獲取目標物件時自動重新整理目標物件。
(3)AbstractLazyCreationTargetSource:此類實現在呼叫getTarget()獲取時才建立目標物件
8、Interceptor(攔截器)
Interceptor(攔截器)定義了通知的增強方式,也就是通過對Joinpoint(連線點)的攔截。一個通用的攔截器可以攔截髮生在基礎程式中的執行時事件。這些事件被連線點具體化。執行時連線點可以是一次方法呼叫、欄位訪問、異常產生等等。Interceptor介面也在強調概念而非功能,也是一個標記介面。 由Interceptor擴展出的ConstructorInterceptor和MethodInterceptor兩個子介面,才具體定義了攔截方式。它們一個用於攔截構造方法,一個用於攔截普通方法。 但是,spring框架並沒有支援AOP聯盟對構造方法的攔截,因為spring框架本身,通過BeanPostProcessor的定義,對bean的生命週期擴充套件已經很充分了。
MethodInterceptor只定義了增強方式,我們可以通過實現此介面,自定義具體的增強內容。當然,spring框架也提供了3種預定義的增強內容:BeforeAdvice(前置通知)、AfterAdvice(後置通知)和DynamicIntroductionAdvice(動態引介通知)。BeforeAdvice和AfterAdvice更確切地說是定義了增強內容的執行時機(方法呼叫之前還是之後);而DynamicIntroductionAdvice比較特殊,它可以編輯目標類要實現的介面列表。最後,spring預定義的通知還是要通過對應的介面卡,適配成MethodInterceptor介面型別的物件(如:MethodBeforeAdviceInterceptor負責適配MethodBeforeAdvice)。
幾個常用攔截器:
(1)MethodBeforeAdviceInterceptor:MethodBeforeAdvice(前置通知,其父介面是BeforeAdvice)介面的介面卡,用於支援spring預定義的前置通知,在目標方法呼叫前呼叫MethodBeforeAdvice.before()。
(2)AspectJAfterAdvice :AspectJ框架的後置通知實現,在目標方法執行結束後,return之前,呼叫配置指定的方法(注意:此方法呼叫被寫在finally塊中,無論如何都會得到執行)。
(3)AfterReturningAdviceInterceptor :AfterReturningAdvice介面的介面卡,用於支援spring預定義的後置通知,在目標方法執行結束後,return之前,呼叫AfterReturningAdvice.afterReturning()執行(注意:如果目標方法丟擲異常,則不會執行這個方法)。
(4)AspectJAfterThrowingAdvice :AspectJ框架的異常通知,當目標方法執行時產生異常的時候,指定配置指定的方法。
(5)AspectJAroundAdvice :AspectJ框架的環繞通知,直接執行配置指定的方法。
(6)ThrowsAdviceInterceptor :spring框架預定義的異常通知的介面卡,此介面卡接受任意型別的物件,但是要求物件所在類必須宣告public的名稱為afterThrowing,且引數個數為1個或4個,且最後一個引數為Throwable型別的方法。該介面卡會儲存該Throwable物件的實際型別到該方法之間的對映,當目標方法執行產生異常時,根據產生的異常型別找到對應的通知方法進行呼叫。
(7)DelegatingIntroductionInterceptor:通過構造方法傳入指定的引介物件,每當呼叫的目標方法是引介介面定義的方法時,都會呼叫該引介物件的對應方法。
(8)DelegatePerTargetObjectIntroductionInterceptor:通過建構函式傳入指定的引介介面和介面對應的實現類,該攔截器會為每個目標物件建立新的引介物件(通過呼叫實現類的預設無參構造)。當呼叫的方法是引介介面定義的方法時,則呼叫該新建的引介物件對應的方法。
二、AOP原始碼檔案清單
本文進行梳理的AOP原始碼檔案清單是基於版本號為5.2.4.BUILD-SNAPSHOT的Spring原始碼。一共9大類,204個java檔案。
1、aopalliance
aopalliance/aop
1.1 Advice:定義了一個表示通知的標識介面,各種各樣的通知都繼承或實現了該介面。
1.2 AspectException:描述AOP系統框架錯誤的執行時異常。
aopalliance/intercept
1.3 Joinpoint:連線點。在攔截器中使用,封裝了原方法呼叫的相關資訊,如引數、原物件資訊,以及直接呼叫原方法的proceed方法。
1.4 Invocation 執行時的方法呼叫,繼承自joinpoint。
1.5 ConstructorInvocation:Invocation的子類,包含了獲取構造器的方法。
1.6 MethodInvocation:Invocation的子類,返回被呼叫的方法資訊。
1.7 Interceptor:攔截器,Advice的子介面,標記攔截器。攔截器是增強器的一種。
1.8 ConstructorInterceptor:構造器攔截器,Interceptor的子介面,攔截構造器並處理。
1.9 MethodInterceptor:方法攔截器,Interceptor的子介面,攔截方法並處理,核心類。
2、AOP
2.1 Pointcut:切點的一個頂層抽象。切點的主要作用是定義通知所要應用到的類跟方法。具體的哪些類、哪些方法由ClassFilter和MethodMatcher匹配,只有滿足切入點的條件時才插入advice。
2.2 TruePointcut:Pointcut(切點)介面的一個最簡單的實現類,匹配到所有。
2.3 AfterAdvice:無論一個 join point 是正常退出還是發生了異常, 都會被執行的 advice。
2.4 AfterReturningAdvice:後置通知(After Returning Advice)後置通知相比較於前置通知,主要有以下幾點不同:後置通知可以訪問目標方法的返回值,但是不能修改,後置通知是在方法執行完成後執行。
2.5 BeforeAdvice:在 join point 前被執行的 advice。雖然 before advice 是在 join point 前被執行,但是它並不能夠阻止 join point 的執行,除非發生了異常(即我們在 before advice 程式碼中, 不能人為地決定是否繼續執行 join point 中的程式碼)。
2.6 MethodBeforeAdvice:前置通知(Before Advice)跟環繞通知不同的是,這個介面中定義的方法的返回值是void,所以前置通知是無法修改方法的返回值的。如果在前置通知中發生了異常,那麼會直接終止目標方法的執行以及打斷整個攔截器鏈的執行。
2.7 ThrowsAdvice:異常通知(Throws Advice),其中沒有定義任何方法,它更像一個標記介面。我們在定義異常通知時需要實現這個介面,同時方法的簽名也有要求:1、方法名稱必須是afterThrowing。2、方法的引數個數必須是1個或者4個。
2.8 Advisor:顧問,封裝了spring aop中的切點和通知。 就是我們常用的@Aspect 註解標記的類。
2.9 PointcutAdvisor:代表具有切點的切面,它包含Advice和Pointcut兩個類,這樣就可以通過類、方法名以及方法方位等資訊靈活地定義切面的連線點,提供更具適用性的切面。其有6種實現類:
DefaultPointcutAdvisor:最常用的切面型別,它可以通過任意Pointcut和Advice定義一個切面,唯一不支援的是引介的切面型別,一般可以通過擴充套件該類實現自定義的切面;
NameMatchMethodPointcutAdvisor:通過該類可以定義,按方法名定義切點的切面;
RegexpMethodPointcutAdvisor:按正則表示式匹配方法名進行切點定義的切面;
StaticMethodMatcherPointcutAdvisor:靜態方法匹配器切點定義的切面;
AspecJExpressionPointcutAdvisor:Aspecj切點表示式定義切點的切面;
AspecJPointcutAdvisor:使用AspecJ語法定義切點的切面。
2.10 MethodMatcher:用來匹配方法。MethodMatcher中一共有三個核心方法:
matches(Method method, @Nullable Class<?> targetClass),這個方法用來判斷當前定義的切點跟目標類中的指定方法是否匹配,它可以在建立代理的時候就被呼叫,從而決定是否需要進行代理,這樣就可以避免每次方法執行的時候再去做判斷。
isRuntime(),如果這個方法返回true的話,意味著每次執行方法時還需要做一次匹配。
matches(Method method, @Nullable Class<?> targetClass, Object... args),當之前的isRuntime方法返回true時,會呼叫這個方法再次進行一次判斷,返回false的話,意味著不對這個方法應用通知。
介面的實現類有很多,如StaticMethodMatcher(只支援靜態匹配,兩個引數的matchs)、AspectJExpressionPointcut(AOP重要元件)、TrueMethodMatcher(總是匹配)、AnnotationMethodMatcher(註解匹配)。
2.11 TrueMethodMatcher:MethodMatcher介面的一個最簡單的實現類,匹配到所有的方法。
2.12 ClassFilter:主要作用是在類級別上對通知的應用進行一次過濾,如果它的match方法對任意的類都返回true的話,說明在類級別上我們不需要過濾,這種情況下,通知的應用,就完全依賴MethodMatcher的匹配結果。ClassFilter有4中簡單方式的實現:
(1)TypePatternClassFilter:基於AspectJ的型別匹配實現;
(2)AnnotationClassFilter:通過檢查目標類是否存在指定的註解,決定是否匹配;
(3)RootClassFilter:通過判斷目標類是否是指定型別(或其子型別),決定是否匹配;
(4)TrueClassFilter:這是最簡單實現,matches方法總會返回true。此類設計使用了單例模式,且其物件引用直接被在ClassFilter介面中宣告成了常量。
2.13 TrueClassFilter:ClassFilter介面的一個最簡單的實現類,匹配到所有的類。
2.14 IntroductionInfo:描述一個引介需要的基本資訊。引介(Introduction)是指在不更改原始碼的情況,給一個現有類增加屬性、方法,以及讓現有類實現其它介面或指定其它父類等,從而改變類的靜態結構。是另一種型別的增強,和通知是並列的兩種不同的增強。
2.15 IntroductionAdvisor:advisor顧問,封裝了spring aop中的切點和通知。這個介面是用來處理一個或者多個引入的顧問的父介面。
2.16 DynamicIntroductionAdvice:引介通知(Introduction Advice)。
2.17 IntroductionAwareMethodMatcher:繼承自MethodMatcher,在進行方法匹配時考慮了引入。
2.18 IntroductionInterceptor:AOP聯盟中的MethodInterceptor(方法攔截器,攔截方法並處理)的子介面。
2.19 TargetSource:TargetSource(目標源)是被代理的target(目標物件)例項的來源。
2.20 TargetClassAware:在代理中用來公開目標類的最小介面,主要被代理物件和代理工廠所實現.。所有的Aop代理物件或者代理工廠(proxy factory)都要實現的介面,該介面用於暴露出被代理目標物件型別。
2.21 RawTargetAccess:AOP代理的標記介面,用來返回原始的目標物件。
2.22 SpringProxy:標記介面,Spring使用JDK動態代理或者CGLIB的方式來生成代理物件,其中每個代理物件都會實現SpringProxy介面。用來判定是否是Spring產生的代理物件。
2.23 ProxyMethodInvocation:MethodInvocation介面的拓展,能夠返回一個代理物件,而當前的Method Invocation是通過該代理物件辦到的。
2.24 AopInvocationException:因為錯誤的配置或者始料不及的執行時出現的問題,導致AOP執行時方法呼叫失敗時丟擲的異常。
3、AOP/aspectj
3.1 AbstractAspectJAdvice:AOP基類,用來包裝AspectJ切面(AspectJ aspect)或AspectJ註解(AspectJ-annotated)的通知方法。
3.2 AspectJAfterAdvice:返回通知,AspectJ中 after 屬性對應的通知(@After 標註的方法會被解析成該通知),不論是否異常都會執行。
3.3 AspectJAfterReturningAdvice:後置通知,AspectJ中 afterReturning 屬性對應的通知(@AfterReturning 標註的方法會被解析成該通知),在切面方法執行之後執行,如果有異常,則不執行。注意:該通知與AspectJMethodBeforeAdvice對應。
3.4 AspectJMethodBeforeAdvice:前置通知,AspectJ中 before 屬性對應的通知(@Before標註的方法會被解析成該通知),在切面方法執行之前執行。
3.5 AspectJAfterThrowingAdvice:異常通知,AspectJ中 after 屬性對應的通知(@AfterThrowing標註的方法會被解析成該通知),在連線點丟擲異常後執行。
3.6 AspectJAroundAdvice:環繞通知,AspectJ中 around 屬性對應的通知(@Around標註的方法會被解析成該通知),在切面方法執行前後執行。
3.7 AspectJPointcutAdvisor:繼承自介面PointcutAdvisor,該類用來調整AbstractAspectJAdvice 使其適應PointcutAdvisor介面 。
3.8 AspectJExpressionPointcutAdvisor:用來處理對應 AspectJ 的 advice 和切點的,有advice的設定和獲取、切點表示式的一些處理、設定切點的Bean工廠,獲取該切點等方法。該類建立了一個 AspectJExpressionPointcut,它們之間的關係是一對一的組合關係。
3.9 DeclareParentsAdvisor:Spring AOP提供的@Before、@After、@AfterReturning、@AfterThrowing、@Around只對類的現有方法進行增強處理。如果需要對現有類增加新的方法,有兩種方法可實現:(1)擴充套件現有類:實現簡單,但如果對多個現有類進行擴充套件時,需增加多個類。(2)使用@DeclareParents註解實現:實現複雜,可使用萬用字元匹配。
3.10 InstantiationModelAwarePointcutAdvisor:由spring aop顧問實現的介面,封裝了可能具有延遲初始化策略的AspectJ 切面。
3.11 AspectJExpressionPointcut:AspectJ表示式切點(通過解析XML配置檔案中的<aop:pointcut>元素生成的就是此型別的bean)。它是一種切點,但與一般的切點不同,一般的切點需要持有單獨的ClassFilter和MethodMatcher。但是AspectJ表示式切點本身就兼具了這兩個元件的功能。因為切點表示式,就是用來描述要代理的目標類和目標方法的。
3.12 MethodInvocationProceedingJoinPoint:AspectJ的ProceedingJoinPoint介面的一個實現類,包裝了MethodInvocation。Proceedingjoinpoint介面 繼承自 JoinPoint,是在JoinPoint的基礎上暴露出 proceed 這個方法。環繞通知=前置+目標方法執行+後置通知,proceed方法就是用於啟動目標方法執行的,暴露出這個方法,就能支援 aop:around 這種切面。
3.13 AspectInstanceFactory:切面工廠,實現該介面的工廠用來生成AspectJ切面的一個例項。
3.14 SimpleAspectInstanceFactory:該介面主要用於從給定的類(或者 beanName 等)獲取一個切面例項,這是AspectInstanceFactory介面的一個實現類。
3.15 SingletonAspectInstanceFactory:AspectInstanceFactory介面的一個實現類,用來支援單例的物件,對於每次呼叫getAspectInstance(),都返回同一個切面例項。
3.16 AspectJAopUtils:相比於AopUtils,AspectJAopUtils是專門針對於AspectJ advisors的工具類。
3.17 AspectJProxyUtils:它相對於AopProxyUtils,它只是專門處理AspectJ代理物件的工具類。
3.18 AspectJAdviceParameterNameDiscoverer:從切點表示式、返回值、丟擲異常來推斷一個AspectJ通知方法的引數名,如果不存在一個明確的推斷,返回Null。
3.19 AspectJPrecedenceInformation:儲存用來給通知、顧問根據AspectJ的排序規則進行排序用的相關資訊。
3.20 AspectJWeaverMessageHandler:實現自AspectJ的IMessageHandler介面,與常規Spring訊息一樣,使用相同的日誌系統來對AspectJ編織訊息進行路由。
3.21 RuntimeTestWalker:這個類用來封裝一些AspectJ內部的結果,在將來解壓中再重新推送到AspectJ專案中。
3.22 TypePatternClassFilter:ClassFilter類過濾器。基於AspectJ的型別匹配實現。
AOP/aspectj/annotation
3.23 AspectJAdvisorFactory:該類主要用於對切面的校驗,從切面中解析 Advisor, Advice 等。
3.24 AbstractAspectJAdvisorFactory:作為父類完成了 是否切面、切面校驗、方法切面註解獲取、切面註解封裝、切面引數解析等一些列工作,將核心的解析 Advisors Advice 交給了 ReflectiveAspectJAdvisorFactory。
3.25 ReflectiveAspectJAdvisorFactory:獲取 Advisors,從 MetadataAwareAspectInstanceFactory (包含有切面的元資料資訊)中獲取切面元資料資訊,將方法切點解析為對應的 AspectJExpressionPointcut(通過切點表示式),然後封裝成 InstantiationModelAwarePointcutAdvisorImpl 返回。
3.26 AspectJProxyFactory:建立AspectJ的AOP物件,用於Spring整合AspectJ的作用,此時,就不需要使用AspectJ特定的編譯器了。
3.27 MetadataAwareAspectInstanceFactory:AspectInstanceFactory的子介面,返回與AspectJ annotated相關的AspectMetedata。本來AspectInstanceFactory包含該方法是最好的,但是AspectMetedata僅僅使用Java 5,所以我們需要單獨分離出該子介面。
3.28 LazySingletonAspectInstanceFactoryDecorator:簡單的裝飾,使MetadataAwareAspectInstanceFactory例項化一次。
3.29 SingletonMetadataAwareAspectInstanceFactory:MetadataAwareAspectInstanceFactory的一個實現類,每次呼叫getAspectInstance()函式時,都會返回同一個例項。
3.30 BeanFactoryAspectInstanceFactory:該類就是AspectInstanceFactory介面的一個實現類,用來生成AspectJ切面的一個例項。需要注意的是如果使用原型模式,例項化多次,可能返回的不是你想要的。使用LazySingletonAspectInstanceFactoryDecorator包裝該類,這樣就可以確保每次都可以得到一個新的切面例項。
3.31 PrototypeAspectInstanceFactory:多例專用的工廠。
3.32 SimpleMetadataAwareAspectInstanceFactory:MetadataAwareAspectInstanceFactory的一個實現類,每次呼叫getAspectInstance()函式時,都會建立指定的切面類的例項。
3.33 AspectMetadata:AspectJ切面類的元資料,每個切面附加一個額外的Spring AOP切點。該類有屬性:aspectName、aspectClass、ajType(transient修飾,表示該屬性不需要序列,序列化物件的時候,這個屬性就不會被序列化)、perClausePointcut。
3.34 InstantiationModelAwarePointcutAdvisorImpl:AspectJPointcutAdvisor的內部實現,注意對於每一個目標方法都會有一個該顧問的例項。
3.35 BeanFactoryAspectJAdvisorsBuilder: Spring AOP內部工具類,用來從bean容器也就是BeanFactory中獲取所有使用了@AspectJ註解的bean,最終用於自動代理機制(auto-proxying)。
該工具內部使用了快取機制,雖然公開的查詢方法可能會被呼叫多次,但並不是每次都會真正查詢,而是會利用快取。最核心的邏輯在其方法buildAspectJAdvisors中,該方法查詢容器中所有@AspectJ註解的bean,然後將其中每個advice方法包裝成一個Spring Advisor。最終結果以一個List<Advisor>的形式返回給呼叫者。
3.36 AnnotationAwareAspectJAutoProxyCreator:目前最常用的AOP使用方式。spring aop 開啟註解方式之後,該類會掃描所有@Aspect()註釋的類,生成對應的advisor。目前SpringBoot框架中預設支援的方式,自動配置。
3.37 NotAnAtAspectException:AopConfigException類的拓展,當試圖對一個類生成顧問,但是該類又不是AspectJ 註解型別的切面的時候丟擲異常。
AOP/aspectj/autoproxy
3.38 AspectJAwareAdvisorAutoProxyCreator:AspectJ的實現方式,也是Spring Aop中最常用的實現方式,如果用註解方式,則用AnnotationAwareAspectJAutoProxyCreator(該類的一個子類)。
3.39 AspectJPrecedenceComparator:排序比較器。它優先比較兩個增強器所屬的切面大小,如果是同一個切面產生的兩個增強器,他們的大小是相同的,則需要拿到它們的宣告順序即InstantiationModelAwarePointcutAdvisorImpl的declarationOrder屬性。
4、AOP/config
4.1 PointcutComponentDefinition:建立一個切點的資訊。
4.2 AspectComponentDefinition:建立一個切面的資訊,包括了巢狀的切點。
4.3 AdvisorComponentDefinition:建立一個顧問的資訊,用來彌合通過<aop:advisor>配置的顧問的bean definition和架構中的部件定義。
4.4 AbstractInterceptorDrivenBeanDefinitionDecorator:BeanDefinitionDecorator(介面)裝飾相關的自定義屬性。該抽象類繼承自BeanDefinitionDecorator,用於註冊相應的Interceptor bean 定義。
4.5 ScopedProxyBeanDefinitionDecorator:<aop:scoped-proxy>標籤是spring<bean>標籤的裝飾標籤,AOP名稱空間的三大標籤之一,它的作用是對生命週期短的bean提供裝飾,使其能被生命週期長的bean正確呼叫。該類負責對該標籤進行解析。
4.6 PointcutEntry:實現了介面ParseState.Entry,代表一個切點的入口。
ParseState(在包org.springframework.beans.factory.parsing中)在解析程序中作為一個簡單的基於棧結構的追蹤邏輯位置類。該類中有一個內部標記介面Entry,為了進入ParseState,要實現該內部標記介面。
4.7 AdviceEntry:實現了介面ParseState.Entry,代表一個通知的入口。
4.8 AdvisorEntry:實現了介面ParseState.Entry,代表一個顧問的入口。
4.9 AspectEntry:實現了介面ParseState.Entry,代表一個切面的入口。
4.10 SpringConfiguredBeanDefinitionParser:實現了介面BeanDefinitionParser,專門用來解析<aop:spring-configured/>標籤。
4.11 AspectJAutoProxyBeanDefinitionParser:是一個實現了BeanDefinitionParser介面的類,專門用於解析切面自動代理的Bean定義的解析工作,重點在其parse方法。
4.12 ConfigBeanDefinitionParser:用來解析<aop:config />標籤,並將標籤相應的BeanDefinition註冊BeanFactory(DefaultListableBeanFactory)。
4.13 AopConfigUtils:這個是關於AOP配置的工具類。因為配置AOP的方式有多種(比如xml、註解等),此工具類就是針對不同配置,提供不同的工具方法的。它的好處是不管什麼配置,最終走底層邏輯都歸一了。
4.14 AopNamespaceHandler:AOP名稱空間處理器,Spring為了開放性提供了NamespaceHandler機制,這樣我們就可以根據需求自己來處理我們設定的標籤元素。我們使用基於xml的spring配置時,可能需要配置如<aop:config />這樣的標籤,在配置這個標籤之前,通常我們需要引入這個aop所在的名稱空間。只有通過配置aop的名稱空間才會找到AOP標籤的處理器AopNamespaceHandler,在AOP的jar中的spring.handlers配置檔案中配置了名稱空間和名稱空間處理器之間的關係。
4.15 AopNamespaceUtils:處理Spring AOP名稱空間的工具類。
4.16 MethodLocatingFactoryBean:實現了FactoryBean介面,通過呼叫getObject()方法獲取MethodLocatingFactory物件。主要作用是通過Bean的名稱和方法名定位到這個Method,然後通過反射進行呼叫。
4.17 SimpleBeanFactoryAwareAspectInstanceFactory:繼承自AspectInstanceFactory(切面例項工廠),該類在bean工廠中通過bean的名字可以定位到切面。
5、AOP/framework
5.1 AopProxy:代表一個AopProxy代理物件,可以通過這個物件構造代理物件例項。
5.2 AopProxyUtils:對org.springframework.aop.support.AopUtils的一個補充。其中比較重要的方法: completeProxiedInterfaces(判斷一個advised真正需要代理的目標介面列表 )和ultimateTargetClass(獲取一個代理物件的最終物件型別)。
5.3 ProxyConfig:AOP配置類,是所有的AOP代理工廠的父類,它包含了建立一個AOP代理所需要的基礎的通用的一些配置資訊。它有五個屬性:
proxyTargetClass 是否直接對目標類進行代理,而不是通過介面產生代理;
optimize 標記是否對代理進行優化;
opaque 標記是否需要阻止通過該配置建立的代理物件轉換為Advised型別;
exposeProxy 標記代理物件是否應該被aop框架通過AopContext以ThreadLocal的形式暴露出去;
frozen 標記是否需要凍結代理物件,即在代理物件生成之後,是否允許對其進行修改。
5.4 ProxyProcessorSupport:提供為代理建立器提供了一些公共方法實現。
5.5 ProxyCreatorSupport:這個類的主要作用是為建立一個AOP代理物件提供一些功能支援,通過它的getAopProxyFactory能獲取一個建立代理物件的工廠。
5.6 ProxyFactory:ProxyFactory繼承自ProxyCreatorSupport,使用它來建立一個代理物件也是要先去設定相關的配置資訊,然後再呼叫建立代理的方法。
5.7 ProxyFactoryBean:ProxyFactoryBean的功能:初始化通知器鏈,獲取單例、原型的Aop代理物件。
5.8 AbstractSingletonProxyFactoryBean:FactoryBean的一個超類,主要用來生成singleton-scoped代理物件。
5.9 AopProxyFactory:AopProxy代理工廠類,用於生成代理物件AopProxy。
5.10 DefaultAopProxyFactory AopProxyFactory:AopProxyFactory預設實現類,核心函式createAopProxy。
5.11 JdkDynamicAopProxy:生成jdk動態代理。可以看到這個類本身就是一個InvocationHandler,這意味著當呼叫代理物件中的方法時,最終會呼叫到JdkDynamicAopProxy的invoke方法。
5.12 CglibAopProxy:生成Cglib動態代理。
5.13 ObjenesisCglibAopProxy :該類繼承自CglibAopProxy,重寫了createProxyClassAndInstance方法。
objenesis是一個小型Java類庫用來例項化一個特定class的物件。Java已經支援使用class.newinstance()的類動態例項化,但是必須要有一個合適的建構函式。而很多場景下類不能夠用這種方式去例項化,例如:建構函式需要引數(Constructors that require arguments)、有副作用的建構函式(Constructors that have side effects)、會丟擲異常的建構函式(Constructors that throw exceptions)。
因此,常見的是在類庫中看到類必須要有一個預設的建構函式的限制,Objenesis旨在通過繞過物件例項化的建構函式來克服這些限制。典型用途:(1)序列化,遠端呼叫和持久化-物件需要被例項化並恢復到特定的狀態,而不需要呼叫程式碼。(2)代理、 AOP 庫和 mock 物件-類可以被子類繼承而子類不用擔心父類的構造器。(3)容器框架-物件可以以非標準的方式動態地例項化。
5.14 Advised:代表被Advice增強的物件,包括新增advisor的方法、新增advice等的方法。
5.15 AdvisedSupport:ProxyConfig類的子類,封裝了AOP中通用的對增強(Advice)和通知器(Advisor)的相關操作,對於所有生成AOP代理物件都通用,而代理物件的生成由子類完成。
5.16 AdvisedSupportListener:監聽器,註冊在ProxyCreatorSupport物件(用來註冊和觸發監聽器)中,捕獲第一個代理建立時和代理建立後通知狀態發生改變的事件。
5.17 AopInfrastructureBean:免被AOP代理的標記介面。是一個標記介面。若Bean實現了此介面,表明它是一個Spring AOP的基礎類,那麼這個類是不會被AOP給代理的,即使它能被切面切進去。
5.18 AbstractAdvisingBeanPostProcessor:繼承自BeanPostProcessor,自身內建一個 Advisor,檢查當前bean是否符合應用該 Advisor 的條件,符合的話將自己的 Advisor 包裹到當前bean(必要的時候為當前bean建立代理物件以便包裹自己的Advisor)。其中呼叫了函式AopUtils.canApply(this.advisor, targetClass),用來檢查某個 Advisor 是否可應用到某個 bean 上的。
5.19 AopConfigException:AOP配置引數非法時丟擲的異常。
5.20 AopContext:代表AOP的上下文。主要是提供我們訪問上下文中當前AOP物件的快速方法。
5.21 AdvisorChainFactory:獲取增強器鏈的工廠介面。提供方法返回所有增強器,以陣列返回。
5.22 DefaultAdvisorChainFactory:這個工廠類負責生成攔截器鏈。藉助DefaultAdvisorAdapterRegistry將Advisor集合轉換成MethodInterceptor集合。
5.23 InterceptorAndDynamicMethodMatcher:框架的內部類,組合MethodInterceptor例項和MethodMatch作為增強器鏈中的一個元素。
5.24 ReflectiveMethodInvocation:核心類,激發攔截鏈工作實現。該類實現了aop聯盟的MethodInvocation,間接實現了Invocation和Joinpoint。
AOP/framework/adapter
5.25 AdvisorAdapter:一個介面卡介面,它定義了自己支援的Advice型別,並且能把一個Advisor適配成MethodInterceptor。
spring aop框架對BeforeAdvice、AfterAdvice、ThrowsAdvice三種通知型別的支援實際上是藉助介面卡模式來實現的,這樣的好處是使得框架允許使用者向框架中加入自己想要支援的任何一種通知型別。
5.26 AdvisorAdapterRegistry:顧問介面卡註冊的介面,這是一個SPI介面,不會被任何Spring使用者所實現。java spi就是提供這樣的一個機制:為某個介面尋找服務實現的機制。
5.27 DefaultAdvisorAdapterRegistry:它用來完成各種通知的適配和註冊過程。將Advice包裝成Advisor(DefaultPointCutAdvisor),藉助AdvisorAdapter,將Advisor包裝成MethodInterceptor。
5.28 GlobalAdvisorAdapterRegistry:負責攔截器的適配和註冊過程。
5.29 AdvisorAdapterRegistrationManager:繼承自BeanPostProcessor後置處理器,利用AdvisorAdapterRegistry在Bean工廠中註冊AdvisorAdapter(通知介面卡)。
5.30 AfterReturningAdviceAdapter:後置通知介面卡。
在 Spring 的 Aop 中,介面卡模式應用的非常廣泛。Spring 使用 Advice(通知)來增強被代理類的功能,Advice 的型別主要有 BeforeAdvice、AfterReturningAdvice、ThrowsAdvice。每種 Advice 都有對應的攔截器,即 MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor。各種不同型別的 Interceptor,通過介面卡統一對外提供介面。最終呼叫不同的 advice來實現被代理類的增強。
5.31 AfterReturningAdviceInterceptor:後置通知攔截器。
5.32 MethodBeforeAdviceAdapter:前置通知介面卡。
5.33 MethodBeforeAdviceInterceptor:前置通知攔截器。
5.34 ThrowsAdviceAdapter:異常通知介面卡。
5.35 ThrowsAdviceInterceptor:異常通知攔截器。
5.36 UnknownAdviceTypeException:當嘗試使用一個不支援的顧問或者通知時丟擲的異常。
AOP/framework/autoproxy
5.37 AbstractAdvisorAutoProxyCreator:預設掃描所有Advisor的實現類,相對於根據Bean名稱匹配,該類更加靈活。動態的匹配每一個類,判斷是否可以被代理,並尋找合適的增強類,以及生成代理類。
5.38 AbstractAutoProxyCreator:Spring 為Spring AOP 模組暴露的可擴充套件抽象類,也是 AOP 中最核心的抽象類。自動代理機制的實現其實很簡單,就是通過Bean的後置處理器,在建立Bean的最後一步對Bean進行代理,並將代理物件放入到容器中。實現自動代理的核心類就是AbstractAutoProxyCreator。
它的三個具體的實現類來進行分析,分別是BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator。
5.39 BeanNameAutoProxyCreator:根據指定名稱建立代理物件。通過設定 advisor,可以對指定的 beanName 進行代理。支援模糊匹配。
5.40 DefaultAdvisorAutoProxyCreator:AbstractAdvisorAutoProxyCreator的預設實現類。可以單獨使用,在框架中使用AOP,儘量不要手動建立此物件。
5.41 InfrastructureAdvisorAutoProxyCreator :自動代理建立器,所有的建立器都是AbstractAutoProxyCreator抽象類的子類。該類是Spring給自己內部使用的一個自動代理建立器。它主要是讀取Advisor類,並對符合的bean進行二次代理。
5.42 AutoProxyUtils:為自動代理元件準備的工具類。主要用於框架內部使用(AbstractAutoProxyCreator)。
5.43 ProxyCreationContext:當前代理建立的上下文,主要給自動代理建立器使用。比如AbstractAdvisorAutoProxyCreator。
5.44 AbstractBeanFactoryAwareAdvisingPostProcessor:該抽象類定義了這樣一類BeanPostProcessor:擁有一個Advisor,對每個bean進行後置處理,如果該bean符合包裹自己所擁有的Advisor的條件,則將該Advisor包裹該bean。
這裡將bean和Advisor包裹該bean的又分兩種情況:目標bean是Advised,此時直接使用Advised介面定義的方法新增Advisor到目標bean。目標bean不是Advised,此時為目標物件建立代理物件,並將Advisor新增到目標bean的代理物件上。
以上主要邏輯基本實現在其父類AbstractAdvisingBeanPostProcessor 中,而該類主要是在此基礎上實現了BeanFactoryAware介面。並覆蓋實現父類的方法prepareProxyFactory,isEligible。
5.45 BeanFactoryAdvisorRetrievalHelper:這個類很重要,是一個Spring AOP內部工具類,用來從bean容器(BeanFactory)中獲取所有Spring的Advisor bean(這裡的 Spring Advisor bean指的是實現了介面org.springframework.aop.Advisor的bean)。是真正去容器中找出所有的Advisor的類。該工具內部使用了快取機制,雖然公開的查詢方法可能會被呼叫多次,但並不是每次都會真正查詢,而是會利用快取。
5.46 TargetSourceCreator:建立專用的target source。
AOP/framework/autoproxy/target
5.47 AbstractBeanFactoryBasedTargetSourceCreator:TargetSourceCreator的一個超類,對於一個原型bean需要建立多個例項時使用。使用一個內部的bean工廠去管理這些target例項。
5.48 LazyInitTargetSourceCreator:建立的代理物件並沒有初始化,直到第一次呼叫時才進行初始化。
5.49 QuickTargetSourceCreator:根據beanName的不同字首建立三種常用的TargetSource型別(bean必須為多例)。(1)CommonsPoolTargetSource:池化TargetSource,每次執行方法時從池中取代理物件,執行完方法再返回池中。(2)ThreadLocalTargetSource:執行緒級的TargetSource。(3)PrototypeTargetSource:多例TargetSource,每次執行方法建立新的代理物件,執行完銷燬該物件。
6、AOP/interceptor
6.1 AbstractTraceInterceptor:MethodInterceptor的實現類,主要用於日誌記錄。預設情況下,寫入日誌中的訊息是記錄攔截器類而不是被攔截的類。當把bean屬性開關useDynamicLogger設定為true時,攔截器類和被攔截的類日誌都會被記錄下來。該抽象類的實現子類必須實現方法invokeUnderTrace。
6.2 SimpleTraceInterceptor:繼承自AbstractTraceInterceptor, 該攔截器可以引入攔截器鏈中,用來顯示被攔截的方法呼叫的詳細跟蹤資訊,包括方法進入和退出的資訊。 如果想要更高階的需求,可以考慮使用自定義的跟蹤攔截器CustomizableTraceInterceptor。
6.3 CustomizableTraceInterceptor:方法級示蹤器。 MethodInterceptor的實現類,使用佔位符,來進行自定義的方法層級的示蹤器。跟蹤在方法入口處訊息是否寫入,在方法退出時判斷方法呼叫是否成功。如果調用出現異常,那麼一個異常訊息記錄下來。這些跟蹤訊息和佔位符是高度定製化的,你可以將一些執行時資訊寫入日誌系統中。
6.4 DebugInterceptor:這個攔截器可以引入鏈中用來將攔截的呼叫的一些詳細資訊顯示到日誌記錄器中。在進行除錯時,可以將方法入口和出口處的一些呼叫細節詳細的記錄下來,包括呼叫的引數和呼叫的次數。
6.5 ExposeInvocationInterceptor:暴露當前MethodInvocation的攔截器。作為執行緒本地物件, 我們偶爾需要這樣做, 比如切入點時需要知道完整的呼叫上下文。除非確實有必要,否則不要使用此攔截器。 目標物件應該通常不瞭解Spring AOP,因為這會產生對Spring API的依賴。目標物件應儘可能是普通的POJO。如果要使用這個攔截器,要將這個攔截器放在攔截鏈中的開頭。
6.6 AbstractMonitoringInterceptor:監控攔截器的基類,比如效能監控器。
6.7 PerformanceMonitorInterceptor:效能監控的攔截器,這個攔截器對於被攔截的方法不會有任何附加的作用。其在實際的效能測量時,使用了簡潔的耗時統計小工具org.springframework.util.StopWatch。
6.8 JamonPerformanceMonitorInterceptor:效能監控的攔截器,使用了JAMon庫對被攔截的方法和輸出的狀態資訊進行效能的監測。另外它也可以對被攔截的方法丟擲的異常進行跟蹤計數,這些堆疊跟蹤足跡可以在JAMopn的web應用中顯示出來。
Jamon的全名是:Java Application Monitor。它是一個小巧的,免費的,高效能的,執行緒安全的效能監測工具。它可以用來測定系統的效能瓶頸,也可以用來監視使用者和應用程式之間的互動情況。 Jamon主要是用來檢測jee的應用程式。
6.9 ConcurrencyThrottleInterceptor:繼承自ConcurrencyThrottleSupport,spring控制併發數的工具類。在ConcurrencyThrottleSupport類中,簡單的通過synchronized和wati and notify達到控制執行緒數量的效果,從而實現限流的策略。
該攔截器中的invoke()方法中,在執行目標方法的前後分別執行beforeAccess()和 afterAccess()方法。在beforeAccess方法中通過內部計數器concurrencyCount來對比設定的閥值concurrencyLimit,如果超過設定值,則阻塞;若沒有超過設定值,則concurrencyCount自加。在afterAccess方法中自減concurrencyCount。
6.10 AsyncExecutionAspectSupport:非同步任務執行切面的一個基類。核心方法determineAsyncExecutor(),返回一個執行非同步任務的執行緒池AsyncTaskExecutor。
6.11 AsyncExecutionInterceptor:非同步任務選擇執行器。其核心方法是invoke,主要流程;(1)獲取攔截的方法。(2)根據被攔截的方法來選取執行非同步任務的執行器。(3)構建任務(新增異常的處理方式)。(4)執行構建的任務並返回任務執行結果。
6.12 AsyncUncaughtExceptionHandler:非同步任務執行丟擲的異常catch不到時通過此介面進行處理。一個非同步任務通常會返回一個java.util.concurrent.Future例項,以訪問潛在的異常,當這個非同步任務不提供這個返回值時,這個控制代碼就負責處理此類捕獲不到的異常。
6.13 SimpleAsyncUncaughtExceptionHandler:AsyncUncaughtExceptionHandler介面的一個預設實現,用來簡單記錄這個異常。
6.14 ExposeBeanNameAdvisors:當Spring IOC容器建立自動代理bean時可以使用,使得建立顧問更加便捷,將bean name繫結到當前的呼叫。通常在spring自動代理中使用,在代理建立時,bean的名稱就是已知的。
7、AOP/scope
7.1 ScopedObject:用於作用域物件的AOP引介介面。ScopedProxyFactoryBean建立的物件可以轉換到這個介面,能夠得到原始的目標物件,從它的目標scopt中剝離出該物件。Spring的Bean是有scope屬性的,表示bean的生存週期。scope的值有prototype、singleton、session、request。
7.2 DefaultScopedObject:ScopedObject介面的預設實現。
7.3 ScopedProxyFactoryBean:便捷的代理工廠bean,用於作用域物件。被這個工廠bean建立的代理是單例的,執行緒安全,可以會被注入到共享的物件中。
7.4 ScopedProxyUtils:建立作用域代理的一些功能性類。主要被ScopedProxyBeanDefinitionDecorator 和 ClassPathBeanDefinitionScanner使用。
8、AOP/support
8.1 AbstractExpressionPointcut:表示式切點型別的抽象超類,提供定位和表示式兩個屬性。
8.2 ExpressionPointcut:表示式切點型別,通過表示式匹配,用於支援AspectJ的表示式。
8.3 NameMatchMethodPointcut:名稱匹配切面,通過指定方法集合變數mappedNames,模糊匹配。
8.4 DynamicMethodMatcherPointcut :動態方法匹配器切點。它本質上是一個方法匹配器,但同時具有了切點的功能。
8.5 StaticMethodMatcherPointcut:靜態方法切面,抽象類。定義了一個classFilter,通過重寫getClassFilter()方法來指定切面規則。另外實現了StaticMethodMatcher介面,通過重寫matches來指定方法匹配規則。子類:NameMatchMethodPointcut(簡單字串匹配方法簽名)和 AbstractRegexpMethodPointcut(正則表示式匹配方法簽名)。
8.6 AbstractRegexpMethodPointcut:正則表示式匹配方法簽名。
8.7 JdkRegexpMethodPointcut:JDK正則表示式切點,即使用正則表示式描述方法的攔截規則和排除規則。
8.8 ControlFlowPointcut:流程切點。
8.9 ComposablePointcut:複合切點。這種切點可以與或邏輯,任意組合其他的Pointcut、ClassFilter和MethodMatcher。其本質是通過ClassFilters和MethodMatchers兩個工具類進行Pointcut內部元件的組合。
8.10 AbstractPointcutAdvisor:PointcutAdvisor介面的抽象基類,其子類可以返回指定的切點/通知,或者是一個可自由配置的切點/通知。
8.11 AbstractGenericPointcutAdvisor:一般的、通用的PointcutAdvisor。
8.12 DefaultPointcutAdvisor:預設切面顧問,比較靈活。可自由組合切面和通知。
8.13 NameMatchMethodPointcutAdvisor:方法名稱切面顧問,內部封