原文地址:http://www-900.ibm.com/developerWorks/cn/java/j-aopwork2/index.shtml 英文地址:http://www-128.ibm.com/developerworks/java/library/j-aopwork2/ AOP@Work: AOP 工具比較,第 2 部分 |
![]() |
![]() |
![]() | |
![]() | ||||
![]() |
![]() |
開發環境
在這個由兩部分構成的 AOP 工具比較的第 1 部分 中,介紹了 4 種領先的 AOP 工具(AspectJ、AspectWerkz、JBoss AOP、Spring AOP)實現核心 AOP 機制的方式。雖然這些工具已經集中在連接點模型、切入點、通知和類型間聲明的思想上,但是每種工具在處理 AOP 語法時,仍有各自明顯的優缺點。正如在第 1 部分介紹的,語法的決策不僅影響方面編程時的感覺 —— 繁瑣的語法 VS 更加直接、作為代碼的切入點 VS 注釋、通知保存在相同的源文件中 VS 本地化為 XML 中的方面配置 —— 而且還會對語義帶來差異。現在,這一部分將繼續探索不同技術的意義,但這次的重點是研究以上決策對 AOP 工具在整體開發過程和開發環境中的集成有什么影響。 本文從深入研究 AspectJ 對 Java? 語言擴展的發展情況開始,重點查看代碼風格在方面構建和靜態檢查方面的優勢和不足。然后討論每種工具的不同編譯方式,并用最新的 AWBench 測評結果說明它們對性能的影響。 在 AOP 工具比較的第 2 部分中,最重要的討論主題可能是 IDE 支持。本文將對每種工具的 IDE 支持逐個特性地進行比較,并對兩個實際的 IDE 插件進行看得見的比較。本文還會介紹每種工具的文檔和庫支持情況,這兩者是選擇新技術實現時的重要因素。 文章結尾提供了對這些工具未來發展方向的一些推測,概括了每種工具的核心優勢與不足。表 1 總結了整篇文章詳細討論的開發環境集成的一些關鍵因素。
如果讀者已經讀過第 1 部分,那么現在可能正想進行開發環境集成。 構建方面 從構建環境的角度看,這些技術的主要區別是:AspectJ 必須提供自己的編譯器,而其他工具可以依靠標準的 Java 編譯器。AspectJ 編譯器擴展了 Eclipse Java 編譯器,可以脫離 Eclipse 在命令行上獨立運行,也可以用作 Eclipse 和其他 IDE 的插件。AspectJ 編譯器對 “.java” 或 “.aj” 文件中聲明的 AspectJ 和 Java 代碼進行構建,并生成普通的 Java 字節碼。雖然要使用新編譯器這點有些不足,但是這么做可以提供切入點的靜態檢查,而且還會帶來很大的益處。 切入點的靜態檢查 有了 AspectJ 編譯器,方面代碼就可以得到 Java 代碼從靜態檢查得到的全部好處。如果沒有該編譯器,那么在鍵入切入點表達式時,必須非常小心,而且還要適應通過執行應用程序找出錯誤,因為切入點的表達式非常復雜,所以這很容易帶來問題。 在圖 1 中可以看到兩種工具處理切入點中括號錯誤的區別。圖的上面顯示了 AspectJ 中錯誤的出現方式,圖的下面顯示了 AspectWerkz 中錯誤的出現方式。 圖 1. 在 AspectJ 中和在 AspectWerkz 中定位語法錯誤的比較 AspectJ 的編譯器在鍵入代碼的時候就會主動解析方面代碼,立即指出括號錯誤。使用 AspectWerkz,則要到運行時才會檢查出這個錯誤。由此可以看到,在沒有切入點靜態檢查的工具中,這類語法錯誤需要更多時間調試。但是,更常見、更費時的問題則是因為在切入點中拼寫出錯誤類型名這類的錯誤造成的。在沒有進行靜態檢查的情況下,AOP 框架無法調用任何通知,因此會悄無聲息地失敗。指出錯誤在哪特別費時,尤其在初次接觸 AOP 和切入點時。有了靜態檢查,AspectJ 的編譯器會發出警告,指出無法解析的類型名稱或簽名。正如在后面討論的那樣,在即將發布的工具中,可以期盼獲得靜態檢查支持方面的提高。 未來構建環境的考慮 如果選擇了 AspectJ 作為 AOP 工具,那么所有需要使用方面的 Java 項目都必須使用 AspectJ 的編譯器。對于某些項目來說,這可能存在問題(例如在集中指定生產構建使用的編譯器的情況下)。從積極方面來說,AspectJ 編譯器打算替代 Java 編譯器。另一個有關的考慮是:每種工具因為添加對方面的支持而帶來的編譯開銷各不相同。下一節將詳細討論這一點。最后,還應當記住 AspectJ 的語言擴展方法要求項目中使用的所有與構建有關的工具都要擴展到 AspectJ。這意味著許多現成的解析 Java 代碼的工具無法用于 AspectJ 代碼(例如,基準和報告工具,依賴性和風格檢查器,以及版本控制使用的 語言擴展在構建集成上的利弊
雖然語言擴展方法生來就有不足,但是它的一些優點將來也可以應用到注釋和 XML 風格上。把這些優點提供給注釋風格,正是 AspectJ 和 AspectWerkz 兩個團隊聯合進行 @Aspect 開發工作的主要動機,而且這還表明,如果使用底層的 AOP 編譯器,那么靜態檢查也能用于注釋風格。目前,雖然還存在其他研究質量的編譯器,但是 AspectJ 編譯器是惟一達到商業質量的 AOP 編譯器。注意,與采用不同編譯器的必要性相關的許多關注點都是工具本身所固有的。在構建時、裝入時或運行時修改這些字節碼的時候,一些影響編譯新字節碼的問題也會出現。正如下一節將討論的,這個編織(weaving) 過程是所有 AOP 工具的基本過程,因為是它支持橫切關注點的模塊化實現。 編織和性能
AspectJ 和 AspectWerkz 都支持構建時和裝入時編織,但是 AspectJ 更側重于前者,而 AspectWerkz 更側重于后者。JBoss AOP 和 Spring AOP 則側重于在運行時使用動態代理和攔截器調用方面。注意,也能將 Java VM 技術擴展到支持運行時編織,但目前這仍然處在研究階段。使用運行時攔截框架的關鍵好處是:它很自然地擴展到了方面的熱部署(hot deployment)。這意味著可以在運行時激活或禁用所應用的通知。 熱部署是 JBoss AOP 的核心特性,它提供了一個應用服務器管理控制臺,可以激活和禁止某些方面。在 Spring AOP 中也有熱部署。加入 AspectWerkz 構建和裝入時編織模型的類似擴展也支持熱部署。在 AspectJ 中,用這種方式激活和禁止方面需要用通知中的 “ if” 測試或用 “if” 切入點進行。有時用術語“動態 AOP”來描述熱部署,但是請注意,這個術語可能會造成誤導,因為所有的 AOP 工具都支持動態連接點模型。而且 Spring AOP 完全基于代理機制。因此,這種工具很適合粗粒度的橫切,但是純粹基于代理的 AOP 不能用來通知精細的連接點(例如方法調用或字段設置)。另一方面,可以在沒有構建時或裝入時編織的情況下使用 Spring AOP 的代理,這對于某些應用服務器的部署會非常有用。 性能考慮 也就是說,考慮一下AWBench 最新發布的 AOP 工具基準會很有價值(請參閱參考資料)。要理解這些基準,需要考慮 AOP 工具進行方面編織和編譯的不同技術對性能的影響方式。 AspectJ 在編譯時會帶來開銷,主要是內存和時間的使用,因為它是在編譯時執行大部分通知。在大型項目中,這些開銷有可能是很可觀的,而且可能帶來一些問題,特別是面向方面編程的橫切特性通常意味著,在切入點發生變化時,大部分系統都需要重新編譯。但它也意味著在運行的時候,幾乎不需要為了匹配切入點做額外的工作。另外一個運行時的性能優勢來自 AspectJ 和 AspectWerkz 中連接點參數的靜態類型檢查。這會帶來性能飛躍,因為不需要以反射的形式訪問連接點上下文了。對比之下,JBoss AOP 和 Spring AOP 基于攔截的技術在運行時有更多的工作要做。因此,在 AWBench 基準評定中可以看到一個趨勢:AspectJ 的通知調用最快,然后是 AspectWerkz、JBoss AOP,最后是 Spring AOP。通過比較,AspectJ 的構建時開銷最多,AspectWerkz 次之,JBoss AOP 再次,Spring AOP 沒有構建時開銷。 攔截的性能利弊
與任何性能度量標準一樣,只能把這些準則當作參考,應當結合應用程序和使用情況來考慮這些準則。例如,與 Spring AOP 一起使用的典型粗粒度方面一般不會產生顯著的開銷。這里介紹的工具沒有任何一個有讓人無法接受的硬傷。與以前的一些 AspectJ 和 AspectWerkz 相比,這兩種工具進行了更多的優化,其他工具正在緊緊追趕。AOP 編譯器相對來說也是一種新發明,目前從研究社區到諸如 AspectJ 之類的實現的優化速度也在加快。當發生這些改進的時候,正如我們期望看到的那樣,構建時間會在不斷地改進。 IDE 集成 在編輯切入點時,不得不運行系統才能查看結果,尋找受影響的連接點是非常耗時的。與此類似的問題是,開發人員在初次學習 AOP 時經常會問:“怎樣才能知道方面在系統上的效果呢?如果其他人簽入的方面會影響正在處理的方面又會怎樣呢?”通過指出什么時候連接點受通知影響,AOP 工具回答了這些問題。這意味著在處理某個方法的時候,可以看到影響該方法的所有通知。反過來,在編寫方面的時候,可以立即看到這個方面影響了哪個連接點。可以想像一下現代 Java IDE 是怎樣提供方便的導航方式的,可以從一個方法導航到所有重寫它的方法。這種面向對象工具支持使得系統的繼承結構清晰可見。而 AOP IDE 支持使得橫切結構的效果清晰可見,從而使處理某些方面就像處理對象一樣容易。 插件比較 圖 2 演示了用于 Eclipse 的 AspectJ 開發工具(AJDT)如何在編輯器中呈現出橫切結構,以及如何呈現為了顯示方面聲明及其效果而擴展的視圖。關于這些特性的詳細描述以及更多截屏,請參閱參考資料中的 AJDT 文章。 圖 2. 用于 Eclipse 的 AspectJ 開發工具(AJDT)插件 V1.2.0 下面將重點介紹一些 AJDT 插件的特性;列表編號與圖中的標簽對應:
像 AJDT 插件一樣,JBoss AOP 插件也支持用視圖在橫切結構中導航。在圖 3 中可以看到,Eclipse 的 JBoss AOP 插件提供了一些與 AJDT 插件相同的功能。它還有兩個顯著的額外特性:方面管理器視圖,用于查看切入點綁定;還有一個 GUI,用于創建基于枚舉的切入點。表 2 提供了這些插件特性的完整比較。 下面將重點介紹一些 JBoss AOP 插件的特性;列表編號與圖 3 中的標簽對應:
特性比較 下面的說明介紹了每種工具的 IDE 支持的關鍵特性:
所有的工具都依賴現有的 Java 調試器進行啟動和調試。在所有的工具中,包括那些沒有成熟 IDE 支持的工具(AspectWerkz 和 Spring AOP),方面程序的調試都工作得不錯。這意味著在通知中和單步執行(single stepping)中設置斷點與在普通 Java 類中是一樣的。 有可能錯過的特性 支持在 IDE 中使用 UML 視圖的工具越來越多,盡管對這類視圖的應用目前仍然存在爭議。目前,還沒有與 AspectJ 或其他 AOP 工具兼容的 UML 查看器。如果對 AspectJ 程序使用 UML 查看器,查看器可能會崩潰,因為它要求的是普通 Java 代碼。相比之下,普通的 Java 技術會把方面作為普通的 Java 類顯示。這樣做的好處是有限的,因為它無法顯示在通知與受影響的連接點之間,或者通知與通過類型間聲明添加的附加成員之間的所有有意義的關系。 文檔和庫 Spring AOP 提供了優秀的庫支持。與 Spring 框架的集成意味著它利用了依賴注入的(dependency-injecting)方面,提供了復雜成熟的事務攔截器庫,而且支持一些有趣的第三方方面(例如 Acegi 安全性框架)。Spring 的 AOP 庫擁有在應用服務器之間移植的優點,而且精心挑選的框架組件方式使它很容易接納模塊中其他利用 AOP 支持的部分。JBoss AOP 提供了與 JBoss 框架和 JEMS 堆棧的其他部分的良好集成,而且擁有目前能夠得到的最豐富的方面庫。這些庫包括對 JBoss Cache、J2EE 按需使用、JBoss remoting、異步方面和 JMX 方面的支持。目前,雖然已經用這些工具創建了一些第三方庫,但 AspectJ 和 AspectWerkz 不包括任何庫。未來的發行版承諾將提供庫支持。 下一步是什么 沿著這條路,對 AOP 重構的研究將會提供所有技術都能使用的結果。用于圖形選擇和切入點操作的 UI 將從一些常見的直觀推斷中受益,這些直觀推斷能夠將選擇和搜索結果轉換成切入點。UML 視圖也會開始顯示 AOP 聲明和聯合。全面支持這些新特性是有可能的,這要感謝一些領先的 AOP 工具在語義上的匯集。 長遠來看,性能應該是一個不是問題的問題。就像開發人員不該擔心虛擬方法分派的開銷一樣,他們也不用擔心通知的調用開銷。目前在很大程度上這是事實,而且隨著編織器的改進,以及與 JIT 和 VM 的集成越來越緊密,情況還會變得更好。 還有另外兩個趨勢正在出現,但是還不確定。首先,AOP 的連接點模型和切入點機制的適用性超越了編程語言,對于能夠從描述運行時事件的簡潔語言中受益的其他工具來說,AOP 的連接點模型和切入點機制也很適用。隨著越來越多的人采用 AOP 工具,切入點的應用在調試器、profiler 這類工具中的應用可能越來越普遍。例如,可以在特定的控制流程中設置斷點。另一個正在出現的趨勢與模型驅動的開發(model-driven development MDD)有關。由于橫切的問題在系統中是如此基本的一個問題,所以 MDD 工具會從模型化的橫切結構以及生成的方面中獲益。 以下是期望從這些工具即將發布版本中得到的一些具體特性的列表:
底線 所有工具 VS 手工編碼的橫切
AspectJ
AspectWerkz
JBoss AOP
Spring AOP
結束語 仔細分析這篇由兩部分構成 AOP 工具比較系列文章中討論的該工具的利弊,這些有助于判斷哪種工具最適合您的項目。文中指出了工具處理方面聲明、編織以及構建集成的主要區別,概述了關鍵的性能問題;還強調了 IDE 集成的好處。本文概述了 Java 語言擴展的優勢與不足,這個主題對 Java 開發人員有深遠的意義,文章還指出了 AOP 工具的一些未來發展方向。 在閱讀本文時,讀者可能會很驚訝地發現這些工具的相同點要多于它們的不同點。這意味著不管選擇哪項技術,學習曲線可以從一個 AOP 工具轉移到另一個。每種工具的新發展會繼續相互滲透。AOP 工具目前正在迅速發展,可以滿足不斷增長的用戶社區的需求;而且它還在不斷發布新版本。不管您最后采用什么樣的 AOP 工具,都鼓勵您加入它的用戶討論列表。您的反饋會幫助這項重要的技術指明未來的發展方向。 記著下個月繼續關注 AOP@Work 系列的下一期文章:Ramnivas Laddad 的 “元數據和 AOP:天生絕配”。
![]() |