Spring的AOP之What is AOP

在軟件開發中,散步在應用程序中多處的功能被稱為橫切關注點(cross-cutting concern)。通常來講這些橫切關注點從概念上講是與業務邏輯相分離的。把這些橫切關注點與業務邏輯分離正是面向切面編程(AOP)要做的事。

1.什么是面向切面編程

切面能夠幫助我們模塊化橫切關注點。橫切關注點可以被描述為影響應用多處的功能。下圖展現了被劃分為模塊的經典應用,每個模塊都有特定的業務邏輯,但這些模塊都需要特定的輔助功能,如日志、緩存和事務管理。

切面實現了橫切關注點(跨越多個應用對象的邏輯)的模塊化

面向切面編程提供了實現重用通用功能很好的方案。在使用面向切面編程時,我們仍然在一個地方定義通用功能,但是可以通過聲明的方式定義這個功能以何種方式在何處使用,而無需修改受影響的類。橫切關注點可以被模塊化為固定的類,這些類稱為切面(aspect)。這樣做有兩個好處:首先每個關注點都集中于一個地方,而不是分散在代碼各處;其次,服務模塊更簡潔,因為他們只包含關注點(或核心功能)的代碼,其次要關注點的代碼被轉移到切面中了。

1.1定義AOP的術語

與大多數技術一樣AOP已經形成了自己的術語。描述切面術語有通知(advice)、切點(pointcut)和連接點(joinpoint)。

通知(Advice)

在AOP術語中,切面的工作被稱為通知。通知定義了切面是什么以及何時調用。Spring切面可以應用5中類型的通知:

通知類型 描述
前置通知(Before) 在目標方法調用前調用通知
后置通知(After) 在目標方法調用后調用通知
返回通知(After-returning) 在目標方法成功執行之后調用通知
異常通知(After-throwing) 在目標方法發生異常時調用通知
環繞通知(Around) 通知包裹目標方法,在被通知的方法調用之前和調用之后執行自定義的行為
連接點(Join point)

我們的應用程序可能有數以萬計的時機應用通知,這些時機被稱為連接點。連接點是應用程序執行過程中能夠插入切面的一個點。這個點可以是調用方法、拋出異常、甚至修改一個字段時。切面代碼利用這些切入點插入到正常的流程中,并添加新的行為。

切點(Pointcut)

如果說通知定義了“什么”和“何時”的話,那么切點就定義了“何處”,切點的定義會匹配通知所要織入的一個或多個連接點。我們常常使用明確的類和方法的名稱,或使用正則表達式定義所匹配的類和方法的名稱來匹配連接點。有些AOP框架允許我們創建動態連接點,可以根據運行時的策略(比如方法的參數值)來決定是否應用通知。

切面(Aspect)

切面是通知和切點的結合--他是什么,在何時、何處完成其功能。

引入(Introduction)

引入允許我們向現有的類中添加方法和屬性。例如我們創建了一個Auditable通知類,該類記錄對象最后以此修改的狀態。只需要一個方法setLastModified(Date),和一個實例變量來保存這個狀態。然后這個方法和變量就會被引入現有的類中,從而可以在不修改現有類的情況下為他們添加心得方法和狀態。

織入(Weaving)

織入就是將切面應用到目標對象并創建新的代理對象的過程。切面在指定的連接點織入到目標對象中。在目標對象的生命周期中有多個點可以織入:
編譯器:切點在目標對象類編譯時被織入。這種方式需要特殊的編譯器。AspectJ的織入編譯器就是以這種方式織入切面的。
類加載期:切面在目標類加載到JVM時被織入。這種方式需要特殊的類加載器(ClassLoader),它可以在目標類被引入應用之前增強該目標類的字節碼。
運行期:切面在應用運行的某個時刻被織入。一般情況下,在織入切面時,AOP容器會為目標對象動態的創建一個代理對象。Spring AOP就是以這種方式被織入切面的。
在了解了AOP的這些術語后,就讓我們來看看AOP的這些概念在Spring中是如何實現的。

2.Spring對AOP的支持

并不是所有的AOP框架都是相同的,他們在連接點模型上可能有強弱之分。有些允許修飾符級別應用通知,而另一些只支持與方法調用相關的連接點。他們織入切面的方式和時機也有所不同。但無論如何,創建切點來定義切面所織入的連接點是AOP框架的基本功能。
Spring提供了4種類型的AOP支持:

  • 基于代理的經典Spring AOP
  • 純POJO切面
  • @AspectJ注解驅動的切面
  • 注入式AspectJ切面(適用于Spring各版本)

前三種都是Spring AOP實現的變體,Spring AOP構建在動態代理基礎之上,因此,Spring 對AOP的支持局限于方法攔截。下面我們來看看Spring AOP框架中一些關鍵的知識。

2.1Spring通知是Java編寫的

Spring所創建的通知都是使用標準的Java類來編寫的。這樣我們可以使用與普通Java開發一樣的集成開發環境(IDE)來開發切面。

2.2Spring在運行時通知對象

Spring是在運行期把切面織入到Spring管理的bean中。代理類封裝了目標類,并攔截被通知方法的調用,再把調用轉發給真正的目標bean。當代理攔截到方法調用時,再調用目標bean方法之前,會執行切面邏輯。直到應用真正需要被代理的bean時,Spring才能創建代理對象。因為Spring運行時才創建代理對象,所以不需要特殊的編譯器來織入Spring AOP的切面。

2.3Spring只支持方法級別的連接點

正如前面講述的,通過使用各種AOP方案可以支持多種連接點模型。但Spring是基于動態代理的,所以Spring只支持方法連接點。這與一些其他的AOP框架是不同的,例如AspectJ和Jboss,除了方法切點,他們還支持字段和構造器接入點。但是方法攔截器可以滿足絕大所數需求,如果我們需要使用方法攔截器之外的連接點可以利用Aspect來補充Spring AOP的功能。
對于什么是AOP以及Spring如何支持AOP的,我們現在已經有了一個大致的了解。下節我們將會學習如何在Spring中創建切面,是不是很期待呢??!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容