Spring AOP 一:基本概念

一、Java平臺上AOP實現(xiàn)機(jī)制

1、jdk動態(tài)代理:利用攔截器(攔截器必須實現(xiàn)InvocationHanlder) + 反射機(jī)制? 生成一個實現(xiàn)代理接口的匿名類,在調(diào)用具體方法前調(diào)用InvokeHandler來處理。要求目標(biāo)對象實現(xiàn)了接口。

2、動態(tài)字節(jié)碼增強(qiáng):利用ASM/CGLIB,在程序運行期間,對動態(tài)構(gòu)建的字節(jié)碼文件生成相應(yīng)的子類,將橫切邏輯加入自類中。不需要目標(biāo)對象實現(xiàn)接口,但擴(kuò)展類以及方法不能為final。

????????Spring AOP在無法采用動態(tài)代理機(jī)制進(jìn)行AOP功能擴(kuò)展的時候,會使用CGLIB庫的動態(tài)字節(jié)碼增強(qiáng)支持來實現(xiàn)AOP的功能擴(kuò)展。

????????在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>強(qiáng)制使用cglib。

3、java代碼生成

4、自定義類加載器

二、基本概念

1、JointPoint(連接點/織入點):在系統(tǒng)運行之前,AOP的功能模塊都需要織入到OOP的功能模塊中。所以,要進(jìn)行這種織入過程, 我們需要知道在系統(tǒng)的哪些執(zhí)行點上進(jìn)行織入操作,這些將要在其之上進(jìn)行織入操作的系統(tǒng)執(zhí)行點就 稱之為Joinpoint。

圖1

常用的JointPoint類型:

1)方法調(diào)用(Method Call)。當(dāng)某個方法被調(diào)用的時候所處的程序執(zhí)行點,上圖1中的后面三個“圓 圈”所標(biāo)記的時點都屬于這種類型。

2)方法調(diào)用執(zhí)行(Method Call execution) 。稱之為方法執(zhí)行或許更簡潔,該Joinpoint類型代表的是某個方法內(nèi)部執(zhí)行開始時點,應(yīng)該與方法調(diào)用類型的Joinpoint進(jìn)行區(qū)分。

圖2

方法調(diào)用(method call)是在調(diào)用對象上的執(zhí)行點,而方法執(zhí)行(method execution)則是在被調(diào)用到的方法邏輯執(zhí)行的時點。對于同一對象,方法調(diào)用要先于方法執(zhí)行。

構(gòu)造方法調(diào)用(Constructor Call)。程序執(zhí)行過程中對某個對象調(diào)用其構(gòu)造方法進(jìn)行初始化的時點,也就是圖1中如下代碼所在的執(zhí)行點。

HelioBean helloBean = new HelloBean( "Hello! ");

構(gòu)造方法執(zhí)行(Constructor Call Execution)。構(gòu)造方法執(zhí)行和構(gòu)造方法調(diào)用之間的關(guān)系類似于方法執(zhí)行和方法調(diào)用之間的關(guān)系,指的是某個對象構(gòu)造方法內(nèi)部執(zhí)行的開始時點。

字段設(shè)置(FieldSet)。對象的某個屬性通過setter方法被設(shè)置或者直接被設(shè)置的時點。該Joinpoint 的本質(zhì)是對象的屬性被設(shè)置,而通過setter方法設(shè)置還是直接設(shè)置觸發(fā)的時點是相同的。

字段獲取(FieldGet)。相對于字段設(shè).置型的Joinpoint,字段獲取型的Joinpoint,對應(yīng)的是某個對象相應(yīng)屬性被訪問的時點。可以通過getter方法訪問,當(dāng)然也可以直接訪問。

異常處理執(zhí)行(Exception Handler Execution該類型的Joinpoin說t應(yīng)程序執(zhí)行過程中,在某些類型異常拋出后,對應(yīng)的異常處理邏輯執(zhí)行的時點。

類初始化(Class initialization)?類初始化型的Joinpoint,指的是類中某些靜態(tài)類型或者靜態(tài)塊的初始化時點。比如,如下代碼中的log4j初始化位置即屬于該類型Joinpoint對應(yīng)位置的一種。

class FooBar{

????????static{

????????????//初始化Iog4j?

????????????BasicConfigurator.configure();

? ??????}

????????private Foo attribute;

????????//其他方法定義

}

2、Pointcut(切點):Pointcui概念代表的是Joinpoint的表述方式。將橫切邏輯織入當(dāng)前系統(tǒng)的過程中,需要參照Pointcut 規(guī)定的Joinpoint信息,才可以知道應(yīng)該往系統(tǒng)的哪些Joinpoint上織入橫切邏輯

????????以圖1中的helloBean.helloMethod()所在位置的Joinpoint為例,該方法在程序中兩個地方被調(diào)用,而我們系統(tǒng)在這兩個地方都要織入相應(yīng)的橫切邏輯,那么,我們就可以通過以下Pointcut表述來指定這兩個Joinpoint:系統(tǒng)中HelloBean類的helloMechod()方法被調(diào)用的所有Joinpoint。

????????Pointcut的表述方式:直接指定Joinpoint所在方法名稱、正則表達(dá)式、使用特定的Pointcut表述語言。

3、Advice(通知、增強(qiáng)處理):按照Advice在Joinpoint位置執(zhí)行時機(jī)的差異或者完成功能的不同,Advice可以分成多種具體形式。

1)Before Advice

Before Advice是在Joinpoint指定位置之前執(zhí)行的Advice類型。通常,它不會中斷程序執(zhí)行流程,但如果必要,可以通過在Before Advice中拋出異常的方式來中斷當(dāng)前程序流程。如果當(dāng)前Before Advice 將被織入到方法執(zhí)行類型的Joinpoint,那么這個Before Advice就會先于方法執(zhí)行而執(zhí)行。

????????通常,可以使用Before Advice做一些系統(tǒng)的初始化工作,比如設(shè)置系統(tǒng)初始值,獲取必要系統(tǒng)資源等。當(dāng)然,并非就限于這些情況。如果要用Before Advice來封裝安全檢查的邏輯,也不是不可以的,但通常情況下,我們會使用另一種形式的Advice。

2)After Advice

顧名思義,After Advice就是在相應(yīng)連接點之后執(zhí)行的Advice類型,但該類型的Advice還可以細(xì)分為以下三種。

? ? ????????After returning Advice,只有當(dāng)前Joinpoint處執(zhí)行流程正常完成后,After returning Advice才會執(zhí)行。比如方法執(zhí)行正常返回而沒有拋出異常。?

????????????After throwing Advice, 又稱Throws Advice,只有在當(dāng)前Joinpoint執(zhí)行過程中拋出異常的情況下,才會執(zhí)行。比如某個方法執(zhí)行類型的Joinpoint拋出某異常而沒有正常返回。

????????????After Advice ,或許叫After (Finally) Advice更為確切,該類型Advice不管Joinpoint處執(zhí)行流程是正常終了還是拋出異常都會執(zhí)行,就好像Java中的finally塊一樣。

如果以方法執(zhí)行類型的Joinpoint為例,我們的各種Advice的執(zhí)行時機(jī)可以基本如圖3所示。


圖3

3)Around Advice

AOP Alliance屬下的AOP實現(xiàn)大都采用攔截器(Interceptor)的叫法,但完成的功能是一樣的。Around Advice對附加其上的Joinpoint進(jìn)行“包裹”,可以在Joinpoint之前和之后都指定相應(yīng)的邏輯,甚至于中斷或者忽略Joinpoint處原來程序流程的執(zhí)行。

Around Advice的行為可以因為你而發(fā)生改變。呵呵,就好像這“居心叵測”的“叵”字,中間的 那一 “口 ”就是Joinpoint,上下一橫就好像是要執(zhí)行的邏輯。當(dāng)我們只是希望在Joinpoint之前和之后執(zhí)行橫切邏輯,而忽略原來Joinpoint處的邏輯執(zhí)行的時候,就是居心“叵”測了。而正常情況下,Around Advice應(yīng)該像一個“巨"字,我們執(zhí)行完Joinpoint之前的邏輯之后,會接著走Joinpoint,然后才是Joinpoint 之后的邏輯。

既然Around Adviceoj以在Joinpoin之前和之后都能執(zhí)行相應(yīng)的邏輯,那么,它自然可以完成Before Advice和After Advice的功能。不過,通常情況下,還是應(yīng)該根據(jù)場景選用更為具體的Advice類型。

Around Advice應(yīng)用場景非常廣泛,我想大家對于J2EE中的Servlet規(guī)范提供的Filter功能應(yīng)該很熟悉吧。實際上,它就是Around Advice的一種體現(xiàn)。使用它,我們就可以完成“資源初始化”、“安全檢 查”之類橫切系統(tǒng)的關(guān)注點了。

4)Introduction

????????在Aspect!中稱Inter-Type Declaration,在JBoss AOP中稱Mix-in.都指的是這同一種類型的Advice. 與之前的幾種Advice類型不同,Introduction不是根據(jù)橫切邏輯在Joinpoint處的執(zhí)行時機(jī)來區(qū)分的,而是根據(jù)它可以完成的功能而區(qū)別于其他Advice類型。?

????????Introduction可以為原有的對象添加新的特性或者行為,這就好像你是一個普通公民,當(dāng)讓你穿軍裝,帶軍帽,添加了軍人類型的Introduction之后,你就擁有軍人的特性或者行為。

4、Aspect(切面):Aspect是對系統(tǒng)中的橫切關(guān)注點邏輯進(jìn)行模塊化封裝的AOP概念實體。通常情況下,Aspect可以包含多個Pointcut以及相關(guān)Advice定義。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容