天天看點

Spring架構中的Aop是做什麼用的?

面向切面程式設計(AOP)

面向切面程式設計(也叫面向方面程式設計):Aspect Oriented Programming(AOP),是軟體開發中的一個熱點,也是Spring架構中的一個重要内容。利用AOP可以對業務邏輯的各個部分進行隔離,進而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。

AOP是OOP的延續。

主要的功能是:日志記錄,性能統計,安全控制,事務處理,異常處理等等。

主要的意圖是:将日志記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中劃分出來,通過對這些行為的分離,我們希望可以将它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的代碼。

可以通過預編譯方式和運作期動态代理實作在不修改源代碼的情況下給程式動态統一添加功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,提高代碼的靈活性和可擴充性,AOP可以說也是這種目标的一種實作。

在Spring中提供了面向切面程式設計的豐富支援,允許通過分離應用的業務邏輯與系統級服務(例如審計(auditing)和事務(transaction)管理)進行内聚性的開發。應用對象隻實作它們應該做的——完成業務邏輯——僅此而已。它們并不負責(甚至是意識)其它的系統級關注點,例如日志或事務支援。

名稱的含義

Aspect Oriented Programming(AOP)是較為熱門的一個話題。AOP,國内大緻譯作“面向方面程式設計”。

“面向方面程式設計”,這樣的名字并不是非常容易了解,且容易産生一些誤導。筆者不止一次聽到類似“OOP/OOD11即将落伍,AOP是新一代軟體開發方式”這樣的發言。顯然,發言者并沒有了解AOP的含義。Aspect,沒錯,的确是“方面”的意思。不過,華語傳統語義中的“方面”,大多數情況下指的是一件事情的不同次元、或者說不同角度上的特性,比如我們常說:“這件事情要從幾個方面來看待”,往往意思是:需要從不同的角度來看待同一個事物。這裡的“方面”,指的是事物的外在特性在不同觀察角度下的展現。而在AOP中,Aspect的含義,可能更多的了解為“切面”比較合适。是以筆者更傾向于“面向切面程式設計”的譯法。

與 OOP 區分

AOP、OOP在字面上雖然非常類似,但卻是面向不同領域的兩種設計思想。OOP(面向對象程式設計)針對業務處理過程的實體及其屬性和行為進行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。

而AOP則是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設計思想在目标上有着本質的差異。

上面的陳述可能過于理論化,舉個簡單的例子,對于“雇員”這樣一個業務實體進行封裝,自然是OOP/OOD的任務,我們可以為其建立一個“Employee”類,并将“雇員”相關的屬性和行為封裝其中。而用AOP設計思想對“雇員”進行封裝将無從談起。

同樣,對于“權限檢查”這一動作片斷進行劃分,則是AOP的目标領域。而通過OOD/OOP對一個動作進行封裝,則有點不倫不類。

換而言之,OOD/OOP面向名詞領域,AOP面向動詞領域。

和 OOP 關系

很多人在初次接觸 AOP 的時候可能會說,AOP 能做到的,一個定義良好的 OOP 的接口也一樣能夠做到,我想這個觀點是值得商榷的。AOP和定義良好的 OOP 的接口可以說都是用來解決并且實作需求中的橫切問題的方法。但是對于 OOP 中的接口來說,它仍然需要我們在相應的子產品中去調用該接口中相關的方法,這是 OOP 所無法避免的,并且一旦接口不得不進行修改的時候,所有事情會變得一團糟;AOP 則不會這樣,你隻需要修改相應的 Aspect,再重新編織(weave)即可。 當然,AOP 也絕對不會代替 OOP。核心的需求仍然會由 OOP 來加以實作,而 AOP 将會和 OOP 整合起來,以此之長,補彼之短。

應用舉例和缺點

假設在一個應用系統中,有一個共享的資料必須被并發同時通路,首先,将這個資料封裝在資料對象中,稱為Data Class,同時,将有多個通路類,專門用于在同一時刻通路這同一個資料對象。

為了完成上述并發通路同一資源的功能,需要引入鎖Lock的概念,也就是說,某個時刻,當有一個通路類通路這個資料對象時,這個資料對象必須上鎖Locked,用完後就立即解鎖unLocked,再供其它通路類通路。

使用傳統的程式設計習慣,我們會建立一個抽象類,所有的通路類繼承這個抽象父類,如下:

abstract class Worker{

abstract void locked();

abstract void accessDataObject();

abstract void unlocked();

}

accessDataObject()方法需要有“鎖”狀态之類的相關代碼。

Java隻提供了單繼承,是以具體通路類隻能繼承這個父類,如果具體通路類還要繼承其它父類,比如另外一個如Worker的父類,将無法友善實作。

重用被打折扣,具體通路類因為也包含“鎖”狀态之類的相關代碼,隻能被重用在相關有“鎖”的場合,重用範圍很窄。

仔細研究這個應用的“鎖”,它其實有下列特性:

“鎖”功能不是具體通路類的首要或主要功能,通路類主要功能是通路資料對象,例如讀取資料或更改動作。

“鎖”

“鎖”功能其實是這個系統的一個縱向切面,涉及許多類、許多類的方法。如右圖:

Spring架構中的Aop是做什麼用的?

是以,一個新的程式結構應該是關注系統的縱向切面,例如這個應用的“鎖”功能,這個新的程式結構就是aspect(方面)

在這個應用中,“鎖”方面(aspect)應該有以下職責:

提供一些必備的功能,對被通路對象實作加鎖或解鎖功能。以保證所有在修改資料對象的操作之前能夠調用lock()加鎖,在它使用完成後,調用unlock()解鎖。

應用範圍

很明顯,AOP非常适合開發J2EE容器伺服器,JBoss 4.0正是使用AOP架構進行開發。

具體功能如下:

Authentication 權限

Caching緩存

Context passing内容傳遞

Error handling 錯誤處理

Lazy loading 延時加載

Debugging 調試

logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準

Performance optimization性能優化

Persistence 持久化

Resource pooling資源池

Synchronization 同步

Transactions事務

【AOP有必要嗎?】

當然,上述應用範例在沒有使用AOP情況下,也得到了解決,例如JBoss 3.XXX也提供了上述應用功能,并且沒有使用AOP。

但是,使用AOP可以讓我們從一個更高的抽象概念來了解軟體系統,AOP也許提供一種有價值的工具。可以這麼說:因為使用AOP結構,JBoss 4.0的源碼要比JBoss 3.X容易了解多了,這對于一個大型複雜系統來說是非常重要的。

從另外一個方面說,好像不是所有的人都需要關心AOP,它可能是一種架構設計的選擇,如果選擇J2EE系統,AOP關注的上述通用方面都已經被J2EE容器實作了,J2EE應用系統開發者可能需要更多地關注行業應用方面aspect。

傳統的程式通常表現出一些不能自然地适合單一的程式子產品或者是幾個緊密相關的程式子產品的行為,AOP 将這種行為稱為橫切,它們跨越了給定程式設計模型中的典型職責界限。橫切行為的實作都是分散的,軟體設計師會發現這種行為難以用正常的邏輯來思考、實作和更改。最常見的一些橫切行為如下面這些:

日志記錄,跟蹤,優化和監控

事務的處理

持久化

性能的優化

資源池,如資料庫連接配接池的管理

系統統一的認證、權限管理等

應用系統的異常捕捉及處理

針對具體行業應用的橫切行為

前面幾種橫切行為都已經得到了密切的關注,也出現了各種有價值的應用,但也許今後幾年,AOP 對針對具體行業應用的貢獻會成為令人關注的焦點。

具體實作項目

AOP是一個概念,并沒有設定具體語言的實作,它能克服那些隻有單繼承特性語言的缺點(如Java),AOP具體實作有以下幾個項目:

AspectJ (TM): 建立于Xerox PARC. 有近十年曆史,成熟

缺點:過于複雜;破壞封裝;需要專門的Java編譯器。

動态AOP:使用JDK的動态代理API或位元組碼Bytecode處理技術。

基于動态代理API的具體項目有:

JBoss 4.0 JBoss 4.0伺服器

基于位元組碼的項目有:

aspectwerkz ,spring

帶來什麼

面向過程程式設計離我們已經有些遙遠,面向對象程式設計正主宰着軟體世界。當每個新的軟體設計師都被要求掌握如何将需求功能轉化成一個個類,并且定義它們的資料成員、行為,以及它們之間複雜的關系的時候,面向切面程式設計(Aspect-Oriented Programming,AOP)為我們帶來了新的想法、新的思想、新的模式。

如果說面向對象程式設計是關注将需求功能劃分為不同的并且相對獨立,封裝良好的類,并讓它們有着屬于自己的行為,依靠繼承和多态等來定義彼此的關系的話;那麼面向切面程式設計則是希望能夠将通用需求功能從不相關的類當中分離出來,能夠使得很多類共享一個行為,一旦發生變化,不必修改很多類,而隻需要修改這個行為即可。

面向切面程式設計和面向對象程式設計不但不是互相競争的技術而且彼此還是很好的互補。面向對象程式設計主要用于為同一對象層次的公用行為模組化。它的弱點是将公共行為應用于多個無關對象模型之間。而這恰恰是面向方面程式設計适合的地方。有了 AOP,我們可以定義交叉的關系,并将這些關系應用于跨子產品的、彼此不同的對象模型。AOP 同時還可以讓我們階層化功能性而不是嵌入功能性,進而使得代碼有更好的可讀性和易于維護。它會和面向對象程式設計合作得很好。

實作

AOP 是一個概念,一個規範,本身并沒有設定具體語言的實作,這實際上提供了非常廣闊的發展的空間。AspectJ是AOP的一個很悠久的實作,它能夠和 Java 配合起來使用。

介紹 AspectJ 的使用和編碼不是本文的目的,你可以在 Google 上找到很多有關它的材料。

這裡隻是重溫 AspectJ 中幾個必須要了解的概念:

Aspect: Aspect 聲明類似于 Java 中的類聲明,在 Aspect 中會包含着一些 Pointcut 以及相應的 Advice。

Joint point:表示在程式中明确定義的點,典型的包括方法調用,對類成員的通路以及異常處理程式塊的執行等等,它自身還可以嵌套其它 joint point。

Pointcut:表示一組 joint point,這些 joint point 或是通過邏輯關系組合起來,或是通過通配、正規表達式等方式集中起來,它定義了相應的 Advice 将要發生的地方。

Advice:Advice 定義了在 pointcut 裡面定義的程式點具體要做的操作,它通過 before、after 和 around 來差別是在每個 joint point 之前、之後還是代替執行的代碼。

下面要讨論的這些問題,也許正是接觸了 AOP 之後所困惑的。

AOP 幫助我們解決了新的問題沒有?

AOP 并沒有幫助我們解決任何新的問題,它隻是提供了一種更好的辦法,能夠用更少的工作量來解決現有的一些問題,并且使得系統更加健壯,可維護性更好。同時,它讓我們在進行系統架構和子產品設計的時候多了新的選擇和新的思路。

工業化應用

這個問題很難回答,其實最好的答案就是嘗試,用成功的項目或是産品來回答。Jboss 4.0 就是完全采用 AOP 的思想來設計的 EJB 容器,它已經通過了 J2EE 的認證,并且在工業化應用中證明是一個優秀的産品。相信在不遠的将來,會出現更多采用 AOP 思想設計的産品和行業應用。

小結

AOP 正向我們走來,我們需要關注的是怎麼樣使得它能夠為我們的軟體系統的設計和實作帶來幫助。本文旨在給大家一點啟發,能夠在更多的領域更深入的應用 AOP 的思想。

本編文章參考百度百科以及維基百科。