AOP

AOP

程序功能維護技術
在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期動态代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要内容,是函數式編程的一種衍生範型。面向切面編程(AOP)作為面向對象編程的補充和完善,通過把橫切代碼織入到業務組件,能夠很好地解決"橫切關注點"問題。[1]利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率。
  • 中文名:面向切面編程
  • 外文名:Aspect Oriented Programming
  • 簡稱:AOP
  • 屬性:軟件開發技術
  • 衍生範型:函數式編程

名稱含義

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

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

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

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

主要功能

日志記錄,性能統計,安全控制,事務處理,異常處理等等

主要意圖

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

聯系區别

區分

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

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

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

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

關系

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

應用舉例

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

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

使用傳統的編程習慣,我們會創建一個抽象類,所有的訪問類繼承這個抽象父類,如下圖:

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

Java隻提供了單繼承,因此具體訪問類隻能繼承這個父類,如果具體訪問類還要繼承其它父類,比如另外一個如Worker的父類,将無法方便實現。

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

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

“鎖”功能不是具體訪問類的首要或主要功能,訪問類主要功能是訪問數據對象,例如讀取數據或更改動作。

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

因此,一個新的程序結構應該是關注系統的縱向切面,例如這個應用的“鎖”功能,這個新的程序結構就是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 并沒有幫助我們解決任何新的問題,它隻是提供了一種更好的辦法,能夠用更少的工作量來解決現有的一些問題,并且使得系統更加健壯,可維護性更好。同時,它讓我們在進行系統架構和模塊設計的時候多了新的選擇和新的思路。

工業化應用

AOP應用非常廣泛,具體來說,其實最好的答案就是嘗試,用成功的項目或是産品來回答。業内已出現完全采用 AOP 的思想來設計的 EJB 容器,它已經通過了 J2EE 的認證,并且在工業化應用中證明是一個優秀的産品。

總結

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

相關詞條

相關搜索

其它詞條