首頁 >Java >java教程 >關於SpringAOP的理解

關於SpringAOP的理解

高洛峰
高洛峰原創
2017-02-08 10:54:211417瀏覽

AOP(Aspect Orient Programming),作為物件導向程式設計的一種補充,廣泛應用於處理一些具有橫切性質的系統級服務,如事務管理、安全檢查、快取、物件池管理等。 AOP 實現的關鍵就在於AOP 框架自動創建的AOP 代理,AOP 代理則可分為靜態代理和動態代理兩大類,其中靜態代理是指使用AOP 框架提供的命令進行編譯,從而在編譯階段就可生成AOP 代理類,因此也稱為編譯時增強;而動態代理則在運行時藉助於JDK 動態代理、CGLIB 等在內存中「臨時」生成AOP 動態代理類,因此也被稱為運行時增強。

AOP 的存在價值

在傳統OOP 編程里以對象為核心,整個軟體系統由系列相互依賴的對象所組成,而這些對象將被抽象成一個一個的類,並允許使用類繼承來管理類與類別之間一般到特殊的關係。隨著軟體規模的增大,應用的逐漸升級,慢慢出現了一些 OOP 很難解決的問題。

我們可以透過分析、抽像出一系列具有一定屬性與行為的對象,並透過這些對象之間的協作來形成一個完整的軟體功能。由於物件可以繼承,因此我們可以把具有相同功能或相同特性的屬性抽像到一個層次分明的類別結構體系中。隨著軟體規格的不斷擴大,專業化分工越來越系列,以及 OOP 應用實踐的不斷增多,隨之也暴露出了一些 OOP 無法很好解決的問題。

現在假設系統中有3 段完全相似的程式碼,這些程式碼通常會採用「複製」、「貼上」方式來完成,透過這種「複製」、「貼上」方式開發出來的軟體如圖1 所示。

圖1.多個地方包含相同程式碼的軟體

關於SpringAOP的理解

看到如圖1 所示的示意圖,可能有的讀者已經發現了這種做法的不足之處:如果有一天,圖1 中的深色程式碼段需要修改,那是不是要打開3 個地方的程式碼來修改?如果不是 3 個地方包含這段程式碼,而是 100 個地方,甚至是 1000 個地方包含這段程式碼片段,那會是什麼後果?

為了解決這個問題,我們通常會採用將如圖 1 所示的深色程式碼部分定義成一個方法,然後在 3 個程式碼段中分別呼叫該方法即可。在這種方式下,軟體系統的結構如圖 2 所示。

圖2 透過方法呼叫實現系統功能

關於SpringAOP的理解

對於如圖2 所示的軟體系統,如果需要修改深色部分的程式碼,只要修改一個地方即可,不管整個系統中有多少地方調用了該方法,程式無須修改這些地方,只需修改被呼叫的方法即可——透過這種方式,大大降低了軟體後期維護的複雜度。

對於如圖 2 所示的方法 1、方法 2、方法 3 依然需要明確調用深色方法,這樣做能夠解決大部分應用場景。但對於一些更特殊的情況:應用需要方法 1、方法 2、方法 3 徹底與深色方法分離——方法 1、方法 2、方法 3 無須直接呼叫深色方法,那如何解決?

因為軟體系統需求變更是很頻繁的事情,系統前期設計方法1、方法2、方法3 時只實現了核心業務功能,過了一段時間,我們需要為方法1、方法2、方法3 都增加事務控制;又過了一段時間,客戶提出方法1、方法2、方法3 需要進行用戶合法性驗證,只有合法的用戶才能執行這些方法;又過了一段時間,客戶又提出方法1、方法2、方法3 應該增加日誌記錄;又過了一段時間,客戶又提出…面對這樣的情況,我們該怎麼辦?通常有兩種做法:

依照需求說明書,直接拒絕客戶要求。

擁抱需求,滿足顧客的需求。

第一種做法顯然不好,客戶是上帝,我們應該盡量滿足客戶的需求。通常會採取第二種做法,那該如何解決呢?是不是每次先定義新方法,然後修改方法 1、方法 2、方法 3,增加呼叫新方法?這樣做的工作量也不小!我們希望有一個特殊的方法:我們只要定義該方法,無須在方法 1、方法 2、方法 3 中明確地呼叫它,系統就會「自動」執行該特殊方法。

上面想法聽起來很神奇,甚至有一些不切實際,但其實是完全可以實現的,實現這個需求的技術就是 AOP。 AOP 專門用於處理系統中分佈於各個模組(不同方法)中的交叉關注點的問題,在Java EE 應用中,常常透過AOP 來處理一些具有橫切性質的系統級服務,如事務管理、安全檢查、快取、物件池管理等,AOP 已成為一種非常常用的解決方案。

Spring AOP 原理剖析

透過前面介紹可以知道:AOP 代理其實是由 AOP 框架動態產生的一個對象,該對象可作為目標對象使用。 AOP 代理包含了目標物件的全部方法,但 AOP 代理程式中的方法與目標物件的方法存在差異:AOP 方法在特定切入點新增了增強處理,並回調了目標物件的方法。

AOP 代理所包含的方法與目標物件的方法示意圖如圖 3 所示。

圖 3.AOP 代理的方法與目標對象的方法

關於SpringAOP的理解

Spring 的 AOP 代理由 Spring 的 IoC 容器負責產生、管理,其依賴關係也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實例作為目標,這種關係可由 IoC 容器的依賴注入提供。

縱觀 AOP 編程,其中需要程式設計師參與的只有 3 個部分:

定義普通業務組件。

定義切入點,一個切入點可能橫切多個業務元件。

定義增強處理,增強處理就是在 AOP 框架為普通業務組件織入的處理動作。

上面 3 個部分的第一個部分是最平常不過的事情,無須額外說明。那麼進行 AOP 程式設計的關鍵就是定義切入點和定義增強處理。一旦定義了適當的切入點和增強處理,AOP 框架將會自動產生AOP 代理,而AOP 代理的方法大致有如下公式:

代理對象的方法= 增強處理+ 被代理對象的方法

在上面這個在業務定義中,不難發現Spring AOP 的實現原理其實很簡單:AOP 框架負責動態地產生AOP 代理類,這個代理類的方法則由Advice 和回呼目標對象的方法所組成。

對於前面提到的圖2 所示的軟體呼叫結構:當方法1、方法2、方法3 …都需要去呼叫某個具有「橫切」性質的方法時,傳統的做法是程式設計師去手動修改方法1、方法2、方法3 …、透過程式碼來呼叫這個具有「橫切」性質的方法,但這種做法的可擴展性不好,因為每次都要改程式碼。

於是AOP 框架出現了,AOP 框架則可以“動態的”生成一個新的代理類,而這個代理類所包含的方法1、方法2、方法3 …也增加了調用這個具有“橫切”性質的方法-但這種呼叫由AOP 框架自動產生的代理類別來負責,因此具有了極佳的擴展性。程式設計師無需手動修改方法1、方法2、方法3 的程式碼,程式設計師只要定義切入點即可- AOP 框架所產生的AOP 代理程式類別包含了新的方法1、訪法2、方法3,而AOP 框架會根據切入點來決定是否要在方法1、方法2、方法3 中回調具有「橫切」性質的方法。

簡而言之:AOP 原理的奧妙就在於動態地產生了代理類,這個代理類實現了圖 2 的呼叫-這種呼叫無需程式設計師修改程式碼。

小結

AOP 廣泛應用於處理一些具有橫切性質的系統級服務,AOP 的出現是對 OOP 的良好補充,它使得開發者能用更優雅的方式處理具有橫切性質的服務。不管是那種AOP 實現,不論是AspectJ、還是Spring AOP,它們都需要動態地產生一個AOP 代理類,區別只是生成AOP 代理類的時機不同:AspectJ 採用編譯時生成AOP 代理類,因此具有更好的效能,但需要使用特定的編譯器進行處理;而Spring AOP 則採用執行時間產生AOP 代理類,因此無需使用特定編譯器進行處理。由於 Spring AOP 需要在每次運行時產生 AOP 代理,因此效能略差一些。

更多關於SpringAOP的理解相關文章請關注PHP中文網!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn