 |
 |
內(nèi)容: |
 |
|
 |
相關(guān)內(nèi)容: |
 |
|
 |
訂閱: |
 |
|
| 開發(fā)環(huán)境
Mik Kersten (beatmik@cs.ubc.ca) AOP 工具構(gòu)建師、咨詢顧問, University of British Columbia 2005 年 3 月
在這個(gè)由兩部分構(gòu)成的 AOP 工具比較的第 2 部分中,面向方面專家 Mik Kersten 將把重點(diǎn)放在工具與開發(fā)環(huán)境的集成以及構(gòu)建過程上,包括對(duì) AOP 工具 IDE 特性的逐點(diǎn)比較。為了幫助制定最終決策,在進(jìn)行總結(jié)的時(shí)候,作者將介紹這些快速發(fā)展的工具近期的發(fā)展情況,并提供每種工具優(yōu)缺點(diǎn)的總結(jié)。注意,本文將解釋最近宣布的 AspectJ 和 AspectWerkz 項(xiàng)目合并的意義。
在這個(gè)由兩部分構(gòu)成的 AOP 工具比較的第 1 部分 中,介紹了 4 種領(lǐng)先的 AOP 工具(AspectJ、AspectWerkz、JBoss AOP、Spring AOP)實(shí)現(xiàn)核心 AOP 機(jī)制的方式。雖然這些工具已經(jīng)集中在連接點(diǎn)模型、切入點(diǎn)、通知和類型間聲明的思想上,但是每種工具在處理 AOP 語(yǔ)法時(shí),仍有各自明顯的優(yōu)缺點(diǎn)。正如在第 1 部分介紹的,語(yǔ)法的決策不僅影響方面編程時(shí)的感覺 —— 繁瑣的語(yǔ)法 VS 更加直接、作為代碼的切入點(diǎn) VS 注釋、通知保存在相同的源文件中 VS 本地化為 XML 中的方面配置 —— 而且還會(huì)對(duì)語(yǔ)義帶來差異。現(xiàn)在,這一部分將繼續(xù)探索不同技術(shù)的意義,但這次的重點(diǎn)是研究以上決策對(duì) AOP 工具在整體開發(fā)過程和開發(fā)環(huán)境中的集成有什么影響。
本文從深入研究 AspectJ 對(duì) Java? 語(yǔ)言擴(kuò)展的發(fā)展情況開始,重點(diǎn)查看代碼風(fēng)格在方面構(gòu)建和靜態(tài)檢查方面的優(yōu)勢(shì)和不足。然后討論每種工具的不同編譯方式,并用最新的 AWBench 測(cè)評(píng)結(jié)果說明它們對(duì)性能的影響。
在 AOP 工具比較的第 2 部分中,最重要的討論主題可能是 IDE 支持。本文將對(duì)每種工具的 IDE 支持逐個(gè)特性地進(jìn)行比較,并對(duì)兩個(gè)實(shí)際的 IDE 插件進(jìn)行看得見的比較。本文還會(huì)介紹每種工具的文檔和庫(kù)支持情況,這兩者是選擇新技術(shù)實(shí)現(xiàn)時(shí)的重要因素。
文章結(jié)尾提供了對(duì)這些工具未來發(fā)展方向的一些推測(cè),概括了每種工具的核心優(yōu)勢(shì)與不足。表 1 總結(jié)了整篇文章詳細(xì)討論的開發(fā)環(huán)境集成的一些關(guān)鍵因素。
表 1. AOP 工具比較:開發(fā)環(huán)境集成

關(guān)于本系列 AOP@Work 系列面對(duì)的是那些在面向方面編程上有些基礎(chǔ),并且想擴(kuò)展或加深了解的開發(fā)人員(有關(guān) AOP 的背景,請(qǐng)參閱參考資料)。同 developerWorks 的大多數(shù)文章一樣,本系列的文章非常實(shí)用:讀完每篇介紹新技術(shù)的文章,都可以立即將該技術(shù)投入實(shí)用。
本系列文章所選擇的每位作者,都在面向方面編程領(lǐng)域內(nèi)處于領(lǐng)先地位,或者具有這方面的專家水準(zhǔn)。許多作者都是本系列文章中介紹的項(xiàng)目和工具的參與者。每篇文章都力圖提供一個(gè)中立的評(píng)述,以確保這里所表達(dá)觀點(diǎn)的公正性與正確性。
請(qǐng)分別就這些文章的評(píng)論或問題與它們的作者聯(lián)系。要對(duì)本系列進(jìn)行整體評(píng)論,可以與連載的負(fù)責(zé)人 Nicholas Lesiecki 聯(lián)系。
關(guān)于本文 本文并不想突出某一種工具,而是想用一種批判的、沒有偏見的方式突出每種工具的優(yōu)勢(shì)與不足。雖然作者是 AspectJ 項(xiàng)目的參與者之一,但是在編寫本文的時(shí)候,也咨詢了其他 AOP 工具項(xiàng)目的領(lǐng)導(dǎo)人,以確保公平地展示所討論的技術(shù)。 |
如果讀者已經(jīng)讀過第 1 部分,那么現(xiàn)在可能正想進(jìn)行開發(fā)環(huán)境集成。
構(gòu)建方面 在使用 AOP 工具時(shí),不管是使用工具的 IDE 支持,還是通過 Ant 和命令行進(jìn)行構(gòu)建,您會(huì)注意到的第一件事是:AOP 工具與構(gòu)建環(huán)境集成得怎么樣?在談到構(gòu)建環(huán)境集成的時(shí)候,AOP 工具之間的關(guān)鍵區(qū)別在于該工具是否采用了語(yǔ)言擴(kuò)展。雖然 AspectJ 提供了一種代碼風(fēng)格,這種風(fēng)格是 Java 語(yǔ)言的一種擴(kuò)展,但是其他三種技術(shù)都采用了普通 Java 語(yǔ)言與基于 XML 和注釋的方面語(yǔ)言的組合。從集成的觀點(diǎn)來看,AspectJ 對(duì) Java 語(yǔ)言的擴(kuò)展更有利,因?yàn)榉矫媛暶鲹碛信c類聲明一樣簡(jiǎn)潔的格式和易于編輯的方式。但從負(fù)面來看,擴(kuò)展 Java 語(yǔ)言是個(gè)挑戰(zhàn),因?yàn)槊糠N解析 Java 源代碼的工具都必須擴(kuò)展,才能理解方面。結(jié)果,雖然目前有一套 AspectJ 工具(正如在特性比較中討論的),但這個(gè)套件仍不完整。
從構(gòu)建環(huán)境的角度看,這些技術(shù)的主要區(qū)別是:AspectJ 必須提供自己的編譯器,而其他工具可以依靠標(biāo)準(zhǔn)的 Java 編譯器。AspectJ 編譯器擴(kuò)展了 Eclipse Java 編譯器,可以脫離 Eclipse 在命令行上獨(dú)立運(yùn)行,也可以用作 Eclipse 和其他 IDE 的插件。AspectJ 編譯器對(duì) “.java” 或 “.aj” 文件中聲明的 AspectJ 和 Java 代碼進(jìn)行構(gòu)建,并生成普通的 Java 字節(jié)碼。雖然要使用新編譯器這點(diǎn)有些不足,但是這么做可以提供切入點(diǎn)的靜態(tài)檢查,而且還會(huì)帶來很大的益處。
切入點(diǎn)的靜態(tài)檢查 在處理類時(shí),Java 程序員對(duì)靜態(tài)檢查的依賴很重。這意味著,不用過多考慮方法名稱的拼寫錯(cuò)誤,因?yàn)榫幾g器能夠立即指出這類錯(cuò)誤。如果沒有進(jìn)行靜態(tài)檢查,那么這類錯(cuò)誤到了運(yùn)行的時(shí)候才會(huì)被捕獲。AspectJ 對(duì)于所有的方面聲明都有完整的靜態(tài)檢查,所以 AspectJ 編譯器會(huì)立即指出切入點(diǎn)中拼寫錯(cuò)誤的引用。其他 AOP 工具可以檢查方面聲明的合格程度,但是,不管是用注釋還是用 XML 聲明,它們都沒有提供切入點(diǎn)的靜態(tài)檢查。對(duì)于典型的 Java 開發(fā)人員來說,這樣做的后果是要投入大量精力查看 XML 值,而且還會(huì)在運(yùn)行時(shí)帶來大量調(diào)試錯(cuò)誤。如果切入點(diǎn)中放錯(cuò)一個(gè)括號(hào),那么不會(huì)顯示容易修改的編譯錯(cuò)誤,只會(huì)造成很難閱讀和調(diào)試的運(yùn)行時(shí)堆棧跟蹤。
有了 AspectJ 編譯器,方面代碼就可以得到 Java 代碼從靜態(tài)檢查得到的全部好處。如果沒有該編譯器,那么在鍵入切入點(diǎn)表達(dá)式時(shí),必須非常小心,而且還要適應(yīng)通過執(zhí)行應(yīng)用程序找出錯(cuò)誤,因?yàn)榍腥朦c(diǎn)的表達(dá)式非常復(fù)雜,所以這很容易帶來問題。
在圖 1 中可以看到兩種工具處理切入點(diǎn)中括號(hào)錯(cuò)誤的區(qū)別。圖的上面顯示了 AspectJ 中錯(cuò)誤的出現(xiàn)方式,圖的下面顯示了 AspectWerkz 中錯(cuò)誤的出現(xiàn)方式。
圖 1. 在 AspectJ 中和在 AspectWerkz 中定位語(yǔ)法錯(cuò)誤的比較

AspectJ 的編譯器在鍵入代碼的時(shí)候就會(huì)主動(dòng)解析方面代碼,立即指出括號(hào)錯(cuò)誤。使用 AspectWerkz,則要到運(yùn)行時(shí)才會(huì)檢查出這個(gè)錯(cuò)誤。由此可以看到,在沒有切入點(diǎn)靜態(tài)檢查的工具中,這類語(yǔ)法錯(cuò)誤需要更多時(shí)間調(diào)試。但是,更常見、更費(fèi)時(shí)的問題則是因?yàn)樵谇腥朦c(diǎn)中拼寫出錯(cuò)誤類型名這類的錯(cuò)誤造成的。在沒有進(jìn)行靜態(tài)檢查的情況下,AOP 框架無(wú)法調(diào)用任何通知,因此會(huì)悄無(wú)聲息地失敗。指出錯(cuò)誤在哪特別費(fèi)時(shí),尤其在初次接觸 AOP 和切入點(diǎn)時(shí)。有了靜態(tài)檢查,AspectJ 的編譯器會(huì)發(fā)出警告,指出無(wú)法解析的類型名稱或簽名。正如在后面討論的那樣,在即將發(fā)布的工具中,可以期盼獲得靜態(tài)檢查支持方面的提高。
未來構(gòu)建環(huán)境的考慮 AOP 工具的方面聲明的簡(jiǎn)潔性,應(yīng)當(dāng)有助于判斷該工具靜態(tài)檢查的優(yōu)勢(shì)。例如,Spring AOP 創(chuàng)建通知時(shí)要進(jìn)行大量 XML 的搭配。某種工具要求的手工搭配越多,花在編寫和調(diào)試這個(gè)搭配的時(shí)間就會(huì)越多,尤其在有許多方面的時(shí)候。從積極的方面來看,可以通過自動(dòng)生成 XML 搭配來解決這個(gè)問題。稍后將討論 JBoss AOP 的 Eclipse 插件,它能夠做到這一點(diǎn)。
如果選擇了 AspectJ 作為 AOP 工具,那么所有需要使用方面的 Java 項(xiàng)目都必須使用 AspectJ 的編譯器。對(duì)于某些項(xiàng)目來說,這可能存在問題(例如在集中指定生產(chǎn)構(gòu)建使用的編譯器的情況下)。從積極方面來說,AspectJ 編譯器打算替代 Java 編譯器。另一個(gè)有關(guān)的考慮是:每種工具因?yàn)樘砑訉?duì)方面的支持而帶來的編譯開銷各不相同。下一節(jié)將詳細(xì)討論這一點(diǎn)。最后,還應(yīng)當(dāng)記住 AspectJ 的語(yǔ)言擴(kuò)展方法要求項(xiàng)目中使用的所有與構(gòu)建有關(guān)的工具都要擴(kuò)展到 AspectJ。這意味著許多現(xiàn)成的解析 Java 代碼的工具無(wú)法用于 AspectJ 代碼(例如,基準(zhǔn)和報(bào)告工具,依賴性和風(fēng)格檢查器,以及版本控制使用的 diff 工具)。
語(yǔ)言擴(kuò)展在構(gòu)建集成上的利弊
這一節(jié)將從構(gòu)建集成的角度描繪 AspectJ 的語(yǔ)言擴(kuò)展方法的一些主要利弊:
- 使用普通 Java 源代碼的工具必須擴(kuò)展才能用來處理方面代碼。
- 需要使用不同的編譯器。
+ 擴(kuò)展的 Java 編譯器提供了全部方面代碼的完整靜態(tài)檢測(cè)。
+ 編寫和調(diào)試切入點(diǎn)變得更加容易。
雖然語(yǔ)言擴(kuò)展方法生來就有不足,但是它的一些優(yōu)點(diǎn)將來也可以應(yīng)用到注釋和 XML 風(fēng)格上。把這些優(yōu)點(diǎn)提供給注釋風(fēng)格,正是 AspectJ 和 AspectWerkz 兩個(gè)團(tuán)隊(duì)聯(lián)合進(jìn)行 @Aspect 開發(fā)工作的主要?jiǎng)訖C(jī),而且這還表明,如果使用底層的 AOP 編譯器,那么靜態(tài)檢查也能用于注釋風(fēng)格。目前,雖然還存在其他研究質(zhì)量的編譯器,但是 AspectJ 編譯器是惟一達(dá)到商業(yè)質(zhì)量的 AOP 編譯器。注意,與采用不同編譯器的必要性相關(guān)的許多關(guān)注點(diǎn)都是工具本身所固有的。在構(gòu)建時(shí)、裝入時(shí)或運(yùn)行時(shí)修改這些字節(jié)碼的時(shí)候,一些影響編譯新字節(jié)碼的問題也會(huì)出現(xiàn)。正如下一節(jié)將討論的,這個(gè)編織(weaving) 過程是所有 AOP 工具的基本過程,因?yàn)槭撬С謾M切關(guān)注點(diǎn)的模塊化實(shí)現(xiàn)。
編織和性能 正如可以用不同的機(jī)制(例如,解釋或編譯成字節(jié)碼或?qū)ο蟠a)編譯和執(zhí)行 OOP 程序那樣,AOP 工具為構(gòu)建和執(zhí)行方面提供了不同的工具。方面編織器(aspect weaver) 提供了按照方面中切入點(diǎn)指定的方式自動(dòng)調(diào)用通知的搭配方式。編織器可以接受源代碼或二進(jìn)制形式 AOP 代碼作為輸入。方面的編織對(duì)于性能和可伸縮性有影響,其中大部分取決于編織發(fā)生在應(yīng)用程序生命周期的哪一部分。方面的編織可以在以下時(shí)間發(fā)生:
- 構(gòu)建時(shí) —— 如果 OOP 編譯器已經(jīng)擴(kuò)展到 AOP,那么方面編織就是標(biāo)準(zhǔn)編譯的一部分,否則就是編譯后的步驟。
- 裝入時(shí) —— 與方面字節(jié)碼的編譯時(shí)編織相同,但是,是在類裝入的時(shí)候進(jìn)行編織。
- 運(yùn)行時(shí) —— 攔截和基于代理的機(jī)制提供了切入點(diǎn)匹配的手段,可以決定什么時(shí)候應(yīng)當(dāng)調(diào)用通知。
AspectJ 和 AspectWerkz 都支持構(gòu)建時(shí)和裝入時(shí)編織,但是 AspectJ 更側(cè)重于前者,而 AspectWerkz 更側(cè)重于后者。JBoss AOP 和 Spring AOP 則側(cè)重于在運(yùn)行時(shí)使用動(dòng)態(tài)代理和攔截器調(diào)用方面。注意,也能將 Java VM 技術(shù)擴(kuò)展到支持運(yùn)行時(shí)編織,但目前這仍然處在研究階段。使用運(yùn)行時(shí)攔截框架的關(guān)鍵好處是:它很自然地?cái)U(kuò)展到了方面的熱部署(hot deployment)。這意味著可以在運(yùn)行時(shí)激活或禁用所應(yīng)用的通知。
熱部署是 JBoss AOP 的核心特性,它提供了一個(gè)應(yīng)用服務(wù)器管理控制臺(tái),可以激活和禁止某些方面。在 Spring AOP 中也有熱部署。加入 AspectWerkz 構(gòu)建和裝入時(shí)編織模型的類似擴(kuò)展也支持熱部署。在 AspectJ 中,用這種方式激活和禁止方面需要用通知中的 “ if” 測(cè)試或用 “if” 切入點(diǎn)進(jìn)行。有時(shí)用術(shù)語(yǔ)“動(dòng)態(tài) AOP”來描述熱部署,但是請(qǐng)注意,這個(gè)術(shù)語(yǔ)可能會(huì)造成誤導(dǎo),因?yàn)樗械?AOP 工具都支持動(dòng)態(tài)連接點(diǎn)模型。而且 Spring AOP 完全基于代理機(jī)制。因此,這種工具很適合粗粒度的橫切,但是純粹基于代理的 AOP 不能用來通知精細(xì)的連接點(diǎn)(例如方法調(diào)用或字段設(shè)置)。另一方面,可以在沒有構(gòu)建時(shí)或裝入時(shí)編織的情況下使用 Spring AOP 的代理,這對(duì)于某些應(yīng)用服務(wù)器的部署會(huì)非常有用。
性能考慮 在 AOP 和性能的討論中,需要重點(diǎn)關(guān)注的是關(guān)于 AOP 實(shí)現(xiàn)的性能的爭(zhēng)論,它們與若干年前關(guān)于對(duì)象性能問題的爭(zhēng)論類似。一般來說,使用方面的代碼執(zhí)行起來與純粹面向?qū)ο蟮慕鉀Q方案類似(這類方案中橫切代碼散落在整個(gè)系統(tǒng)中)。在大多數(shù)企業(yè)應(yīng)用程序中,執(zhí)行時(shí)間由遠(yuǎn)程調(diào)用和數(shù)據(jù)庫(kù)調(diào)用決定,所以通常沒有必要擔(dān)心使用任何一種 AOP 工具時(shí)的開銷。
也就是說,考慮一下AWBench 最新發(fā)布的 AOP 工具基準(zhǔn)會(huì)很有價(jià)值(請(qǐng)參閱參考資料)。要理解這些基準(zhǔn),需要考慮 AOP 工具進(jìn)行方面編織和編譯的不同技術(shù)對(duì)性能的影響方式。
AspectJ 在編譯時(shí)會(huì)帶來開銷,主要是內(nèi)存和時(shí)間的使用,因?yàn)樗窃诰幾g時(shí)執(zhí)行大部分通知。在大型項(xiàng)目中,這些開銷有可能是很可觀的,而且可能帶來一些問題,特別是面向方面編程的橫切特性通常意味著,在切入點(diǎn)發(fā)生變化時(shí),大部分系統(tǒng)都需要重新編譯。但它也意味著在運(yùn)行的時(shí)候,幾乎不需要為了匹配切入點(diǎn)做額外的工作。另外一個(gè)運(yùn)行時(shí)的性能優(yōu)勢(shì)來自 AspectJ 和 AspectWerkz 中連接點(diǎn)參數(shù)的靜態(tài)類型檢查。這會(huì)帶來性能飛躍,因?yàn)椴恍枰苑瓷涞男问皆L問連接點(diǎn)上下文了。對(duì)比之下,JBoss AOP 和 Spring AOP 基于攔截的技術(shù)在運(yùn)行時(shí)有更多的工作要做。因此,在 AWBench 基準(zhǔn)評(píng)定中可以看到一個(gè)趨勢(shì):AspectJ 的通知調(diào)用最快,然后是 AspectWerkz、JBoss AOP,最后是 Spring AOP。通過比較,AspectJ 的構(gòu)建時(shí)開銷最多,AspectWerkz 次之,JBoss AOP 再次,Spring AOP 沒有構(gòu)建時(shí)開銷。
攔截的性能利弊
JBoss AOP 和 Spring AOP 使用的攔截和基于代理的 AOP 實(shí)現(xiàn)主要的性能利弊是什么?
+ 構(gòu)建時(shí)間的內(nèi)存和時(shí)間開銷可以忽略不計(jì)。
- 運(yùn)行時(shí)的通知調(diào)用開銷,需要決定切入點(diǎn)匹配。
與任何性能度量標(biāo)準(zhǔn)一樣,只能把這些準(zhǔn)則當(dāng)作參考,應(yīng)當(dāng)結(jié)合應(yīng)用程序和使用情況來考慮這些準(zhǔn)則。例如,與 Spring AOP 一起使用的典型粗粒度方面一般不會(huì)產(chǎn)生顯著的開銷。這里介紹的工具沒有任何一個(gè)有讓人無(wú)法接受的硬傷。與以前的一些 AspectJ 和 AspectWerkz 相比,這兩種工具進(jìn)行了更多的優(yōu)化,其他工具正在緊緊追趕。AOP 編譯器相對(duì)來說也是一種新發(fā)明,目前從研究社區(qū)到諸如 AspectJ 之類的實(shí)現(xiàn)的優(yōu)化速度也在加快。當(dāng)發(fā)生這些改進(jìn)的時(shí)候,正如我們期望看到的那樣,構(gòu)建時(shí)間會(huì)在不斷地改進(jìn)。
IDE 集成 IDE 集成的目標(biāo)是在熟悉的 IDE 中方便地編寫和構(gòu)建面向方面的程序。要達(dá)到這個(gè)目標(biāo),必須能夠在 IDE 中調(diào)用 AOP 編譯器或編織器。IDE 支持的另外一個(gè)主要職責(zé)是讓系統(tǒng)的橫切結(jié)構(gòu)易于導(dǎo)航和理解。
在編輯切入點(diǎn)時(shí),不得不運(yùn)行系統(tǒng)才能查看結(jié)果,尋找受影響的連接點(diǎn)是非常耗時(shí)的。與此類似的問題是,開發(fā)人員在初次學(xué)習(xí) AOP 時(shí)經(jīng)常會(huì)問:“怎樣才能知道方面在系統(tǒng)上的效果呢?如果其他人簽入的方面會(huì)影響正在處理的方面又會(huì)怎樣呢?”通過指出什么時(shí)候連接點(diǎn)受通知影響,AOP 工具回答了這些問題。這意味著在處理某個(gè)方法的時(shí)候,可以看到影響該方法的所有通知。反過來,在編寫方面的時(shí)候,可以立即看到這個(gè)方面影響了哪個(gè)連接點(diǎn)。可以想像一下現(xiàn)代 Java IDE 是怎樣提供方便的導(dǎo)航方式的,可以從一個(gè)方法導(dǎo)航到所有重寫它的方法。這種面向?qū)ο蠊ぞ咧С质沟孟到y(tǒng)的繼承結(jié)構(gòu)清晰可見。而 AOP IDE 支持使得橫切結(jié)構(gòu)的效果清晰可見,從而使處理某些方面就像處理對(duì)象一樣容易。
插件比較 每種工具都提供了不同程度的 IDE 支持,在幫助項(xiàng)目選擇合適工具的時(shí)候,這點(diǎn)可能很重要。研究實(shí)際使用 AspectJ 和 JBoss AOP IDE 插件可以讓人對(duì)它支持的特性范圍有個(gè)概念。下一節(jié)將進(jìn)一步研究工具的 IDE 插件。
圖 2 演示了用于 Eclipse 的 AspectJ 開發(fā)工具(AJDT)如何在編輯器中呈現(xiàn)出橫切結(jié)構(gòu),以及如何呈現(xiàn)為了顯示方面聲明及其效果而擴(kuò)展的視圖。關(guān)于這些特性的詳細(xì)描述以及更多截屏,請(qǐng)參閱參考資料中的 AJDT 文章。
圖 2. 用于 Eclipse 的 AspectJ 開發(fā)工具(AJDT)插件 V1.2.0

下面將重點(diǎn)介紹一些 AJDT 插件的特性;列表編號(hào)與圖中的標(biāo)簽對(duì)應(yīng):
- 包瀏覽器顯示了一些方面和方面聲明。切入點(diǎn)和聲明出現(xiàn)時(shí)有它們自己的圖標(biāo),這些圖標(biāo)指出了通知的種類(例如:before、after 等)。
- 編輯器支持顯示了結(jié)構(gòu)化的注釋,允許從某個(gè)方面導(dǎo)航到被通知成員。內(nèi)容輔助彈出對(duì)話框則顯示了通知體中所有可以使用的連接點(diǎn)上下文。
- 文檔大綱(Document Outline)表示活動(dòng)編輯器的橫切結(jié)構(gòu),代表影響對(duì)應(yīng)連接點(diǎn)的通知和類型間聲明。方面成形器(Aspect Visualiser)(在大綱下面,在這個(gè)壓縮的截屏中勉強(qiáng)可以見到)顯示了整個(gè)包中或項(xiàng)目中橫切的整體效果,并突出了受通知影響的源代碼行。
- 受通知影響的方法顯示了可以用來導(dǎo)航到相應(yīng)方面聲明的引導(dǎo)注釋。所有其他受影響的連接點(diǎn)都顯示了相同的結(jié)構(gòu)(例如,受類型間聲明影響的類型,以及受通知影響的調(diào)用站點(diǎn)。)
像 AJDT 插件一樣,JBoss AOP 插件也支持用視圖在橫切結(jié)構(gòu)中導(dǎo)航。在圖 3 中可以看到,Eclipse 的 JBoss AOP 插件提供了一些與 AJDT 插件相同的功能。它還有兩個(gè)顯著的額外特性:方面管理器視圖,用于查看切入點(diǎn)綁定;還有一個(gè) GUI,用于創(chuàng)建基于枚舉的切入點(diǎn)。表 2 提供了這些插件特性的完整比較。
圖 3. JBoss Eclipse 插件 V1.0.1

下面將重點(diǎn)介紹一些 JBoss AOP 插件的特性;列表編號(hào)與圖 3 中的標(biāo)簽對(duì)應(yīng):
- 在包瀏覽器中,通知顯得和普通 Java 成員一樣。
- 方面管理器是 jboss-aop.xml 文件的圖形化顯示,可以減少由于缺乏靜態(tài)檢查而帶來的問題(例如手工編輯 XML 的需要)。它還對(duì)程序的橫切結(jié)構(gòu)提供了方便的完整系統(tǒng)顯示。
- Java 元素上的一個(gè)附加上下文菜單允許直接選取它們,將它們放入一個(gè)切入點(diǎn)中,無(wú)需編輯切入點(diǎn)表達(dá)式。
特性比較 表 2 總結(jié)了 4 種工具 IDE 特性當(dāng)前的情況。它還提供了每種工具現(xiàn)有的庫(kù)和文檔情況的總結(jié)。然后是詳細(xì)討論。
表 2. IDE 支持、庫(kù)和文檔

下面的說明介紹了每種工具的 IDE 支持的關(guān)鍵特性:
- AspectJ —— AspectJ 主要的 IDE 支持是針對(duì) Eclipse 的。Oracle JDeveloper、Borland JBuilder 和 Sun NetBeans 插件也提供了不同程度的 AspectJ 支持。但是,目前 JBuilder 和 NetBeans 版本的開發(fā)不是很活躍,因此大大落后于 AspectJ 語(yǔ)言的發(fā)行進(jìn)度。隨 AspectJ 提供的一個(gè)重要工具是
ajdoc ,它可以為 AspectJ 程序生成 Javadoc 風(fēng)格的文檔。對(duì)于圖 3 中看到的文檔大綱中導(dǎo)航的橫切結(jié)構(gòu),ajdoc 支持用 HTML 文檔中的鏈接對(duì)這些結(jié)構(gòu)進(jìn)行導(dǎo)航。編輯器中的內(nèi)容助手是一項(xiàng)新特性,對(duì)編寫方面很有幫助,對(duì)那些對(duì)語(yǔ)言和各種原生切入點(diǎn)還不太熟悉的人也特別有用。
- AspectWerkz —— AspectWerkz 提供了初級(jí)的 Eclipse 插件。插件的成熟度落后于核心 AspectWerkz 實(shí)現(xiàn)的成熟度,至于真正的 IDE 支持,不要指望從 AspectWerkz 中可以得到(雖然這是聯(lián)合 @AspectJ 時(shí)預(yù)期獲得的一個(gè)好處)。
- JBoss AOP —— JBoss AOP 也側(cè)重于 Eclipse 支持。JBoss 的 AOP 插件提供了方面管理器,它方便了 XML 配置文件的編輯。Advised Members 視圖使得導(dǎo)航橫切成為可能。JBoss 還有一個(gè)新的動(dòng)態(tài)方面部署 UI,它為 JBoss AOP 提供了在運(yùn)行時(shí)修改應(yīng)用通知的方便。請(qǐng)注意,JBoss 的 AOP 插件是最近才發(fā)布的。它的成熟度還比不上 JBoss AOP 框架的其余部分。
- Spring AOP —— 在編譯 XML 文件中的方面規(guī)范說明書時(shí),Spring 的 Eclipse 插件會(huì)很有幫助,但它沒有提供任何特定于 AOP 的功能。
所有的工具都依賴現(xiàn)有的 Java 調(diào)試器進(jìn)行啟動(dòng)和調(diào)試。在所有的工具中,包括那些沒有成熟 IDE 支持的工具(AspectWerkz 和 Spring AOP),方面程序的調(diào)試都工作得不錯(cuò)。這意味著在通知中和單步執(zhí)行(single stepping)中設(shè)置斷點(diǎn)與在普通 Java 類中是一樣的。
有可能錯(cuò)過的特性 目前,所有的 IDE 插件中都還缺乏對(duì)重構(gòu)的支持。所以,如果方法名改變,那么本來應(yīng)當(dāng)仍然匹配這個(gè)方法的切入點(diǎn)可能不再匹配。這是語(yǔ)言擴(kuò)展不擅長(zhǎng)的領(lǐng)域之一。在 AspectJ 不得不為重命名提供自己的重構(gòu)支持的時(shí)候,在某種程度上,其他技術(shù)可以利用現(xiàn)有的重構(gòu)支持。因?yàn)榛谧⑨尯?XML 風(fēng)格的工具必須把完全限定 Java 切入點(diǎn)當(dāng)作字符串,所以它們也可以借助重構(gòu)工具,重新命名內(nèi)嵌在 XML 文件和注釋中的完全限定 Java 引用。
支持在 IDE 中使用 UML 視圖的工具越來越多,盡管對(duì)這類視圖的應(yīng)用目前仍然存在爭(zhēng)議。目前,還沒有與 AspectJ 或其他 AOP 工具兼容的 UML 查看器。如果對(duì) AspectJ 程序使用 UML 查看器,查看器可能會(huì)崩潰,因?yàn)樗蟮氖瞧胀?Java 代碼。相比之下,普通的 Java 技術(shù)會(huì)把方面作為普通的 Java 類顯示。這樣做的好處是有限的,因?yàn)樗鼰o(wú)法顯示在通知與受影響的連接點(diǎn)之間,或者通知與通過類型間聲明添加的附加成員之間的所有有意義的關(guān)系。
文檔和庫(kù) 除了 IDE 支持,工具的文檔和庫(kù)支持也是評(píng)估的重要因素。每種工具都提供了在線文檔,但是 Spring 框架為其 AOP 功能提供的是有點(diǎn)分散的、以實(shí)現(xiàn)為中心的文檔。無(wú)需 EJB 的 J2EE 和其他關(guān)于 Spring 框架的書籍會(huì)很快填補(bǔ)這個(gè)空白。AspectJ 是 AOP 工具的最好證明,目前有六本這方面的書正在印刷。注意,可使用文檔的狀態(tài)僅僅反映了每個(gè)項(xiàng)目已經(jīng)進(jìn)行的時(shí)間長(zhǎng)短。
Spring AOP 提供了優(yōu)秀的庫(kù)支持。與 Spring 框架的集成意味著它利用了依賴注入的(dependency-injecting)方面,提供了復(fù)雜成熟的事務(wù)攔截器庫(kù),而且支持一些有趣的第三方方面(例如 Acegi 安全性框架)。Spring 的 AOP 庫(kù)擁有在應(yīng)用服務(wù)器之間移植的優(yōu)點(diǎn),而且精心挑選的框架組件方式使它很容易接納模塊中其他利用 AOP 支持的部分。JBoss AOP 提供了與 JBoss 框架和 JEMS 堆棧的其他部分的良好集成,而且擁有目前能夠得到的最豐富的方面庫(kù)。這些庫(kù)包括對(duì) JBoss Cache、J2EE 按需使用、JBoss remoting、異步方面和 JMX 方面的支持。目前,雖然已經(jīng)用這些工具創(chuàng)建了一些第三方庫(kù),但 AspectJ 和 AspectWerkz 不包括任何庫(kù)。未來的發(fā)行版承諾將提供庫(kù)支持。
下一步是什么 評(píng)估 AOP 工具時(shí)要考慮的最后一個(gè)因素就是它們的下一步是什么。所有這些工具都在快速走向成熟,目前的實(shí)現(xiàn)工作正在解決這里討論的許多問題。更有趣的是某些技術(shù)的優(yōu)勢(shì)正在滲透到其他技術(shù)中。例如,橫切視圖曾經(jīng)是 AspectJ 所特有的,但現(xiàn)在 JBoss AOP 也提供了橫切視圖,而且很快其他工具也會(huì)提供。合并后的 @AspectJ 會(huì)把 AspectJ 工具支持的許多優(yōu)點(diǎn)帶到 AspectWerkz 的注釋風(fēng)格中。@AspectJ 還提供了語(yǔ)言擴(kuò)展風(fēng)格與注釋風(fēng)格之間的互操作性,這樣,語(yǔ)言的語(yǔ)法也將成為開發(fā)人員的一個(gè)選擇。
沿著這條路,對(duì) AOP 重構(gòu)的研究將會(huì)提供所有技術(shù)都能使用的結(jié)果。用于圖形選擇和切入點(diǎn)操作的 UI 將從一些常見的直觀推斷中受益,這些直觀推斷能夠?qū)⑦x擇和搜索結(jié)果轉(zhuǎn)換成切入點(diǎn)。UML 視圖也會(huì)開始顯示 AOP 聲明和聯(lián)合。全面支持這些新特性是有可能的,這要感謝一些領(lǐng)先的 AOP 工具在語(yǔ)義上的匯集。
長(zhǎng)遠(yuǎn)來看,性能應(yīng)該是一個(gè)不是問題的問題。就像開發(fā)人員不該擔(dān)心虛擬方法分派的開銷一樣,他們也不用擔(dān)心通知的調(diào)用開銷。目前在很大程度上這是事實(shí),而且隨著編織器的改進(jìn),以及與 JIT 和 VM 的集成越來越緊密,情況還會(huì)變得更好。
還有另外兩個(gè)趨勢(shì)正在出現(xiàn),但是還不確定。首先,AOP 的連接點(diǎn)模型和切入點(diǎn)機(jī)制的適用性超越了編程語(yǔ)言,對(duì)于能夠從描述運(yùn)行時(shí)事件的簡(jiǎn)潔語(yǔ)言中受益的其他工具來說,AOP 的連接點(diǎn)模型和切入點(diǎn)機(jī)制也很適用。隨著越來越多的人采用 AOP 工具,切入點(diǎn)的應(yīng)用在調(diào)試器、profiler 這類工具中的應(yīng)用可能越來越普遍。例如,可以在特定的控制流程中設(shè)置斷點(diǎn)。另一個(gè)正在出現(xiàn)的趨勢(shì)與模型驅(qū)動(dòng)的開發(fā)(model-driven development MDD)有關(guān)。由于橫切的問題在系統(tǒng)中是如此基本的一個(gè)問題,所以 MDD 工具會(huì)從模型化的橫切結(jié)構(gòu)以及生成的方面中獲益。
以下是期望從這些工具即將發(fā)布版本中得到的一些具體特性的列表:
- AspectJ 和 AspectWerkz —— AspectJ 5 會(huì)提供對(duì)切入點(diǎn)泛型的支持特性。@AspectJ 語(yǔ)法會(huì)支持 AspectWerkz 注釋風(fēng)格。
- JBoss AOP —— 參數(shù)的靜態(tài)類型化、性能提高、庫(kù)和更多的 IDE 支持特性。
- Spring AOP —— 性能提高、與 AspectJ 切入點(diǎn)的互操作性,以及把某些 Spring AOP 服務(wù)打包成 AspectJ 方面。
底線 如果存在這里給出的優(yōu)勢(shì)和不足,如何判斷為特定項(xiàng)目選擇哪個(gè)工具?在采用某項(xiàng)技術(shù)時(shí)可能遇到的主要問題是什么?這里是每種工具的強(qiáng)項(xiàng)與弱點(diǎn)的一個(gè)概括,可以幫助您制定最終決策。下面將開始介紹手工編寫橫切問題與使用 AOP 工具進(jìn)行處理的優(yōu)劣對(duì)比。
所有工具 VS 手工編碼的橫切
- 目前還不支持高級(jí) IDE 特性(例如重構(gòu))。
+ 一些方面天生就處于復(fù)雜系統(tǒng)中,如果沒有 AOP 工具,實(shí)現(xiàn)會(huì)變得非常脆弱,難以發(fā)展。
+ 橫切變得很明確,易于推理和修改。
AspectJ
- 語(yǔ)言擴(kuò)展要求使用已擴(kuò)展的編譯器和相關(guān)工具。
- 缺少庫(kù)。
+ 簡(jiǎn)潔的方面聲明和切入點(diǎn)的靜態(tài)檢查。
+ 成熟的 IDE 集成。
+ 豐富的文檔。
AspectWerkz
- 不太簡(jiǎn)潔的方面和切入點(diǎn)聲明。
- 缺少切入點(diǎn)的靜態(tài)檢查。
- 缺少庫(kù)。
+ 與 AspectJ 類似的機(jī)制,沒有語(yǔ)言擴(kuò)展。
+ 支持方面的熱部署。
JBoss AOP
- 缺少切入點(diǎn)的靜態(tài)檢查。
- 缺少到其他應(yīng)用服務(wù)器的移植性。
+ 有豐富的企業(yè)方面庫(kù)集合可用,與豐富的 JBoss 和 JEMS 庫(kù)集成在一起。
+ IDE 支持降低了采用難度,減少了手工編寫 XML 代碼的需要。
+ 支持方面的動(dòng)態(tài)部署。
Spring AOP
- 只能通知那些通過框架的代理機(jī)制實(shí)例化的對(duì)象。
- 不適合細(xì)致的方面。
- 缺少處理方面的 IDE 支持。
+ 簡(jiǎn)單的連接點(diǎn)模型很適于粗粒度的方面,更容易學(xué)習(xí)。
+ Spring 框架集成,易于現(xiàn)有 Spring 用戶采用。
+ 跨應(yīng)用服務(wù)器的方面庫(kù)可移植性。
結(jié)束語(yǔ) AOP 工具目前的成就讓人對(duì)它的發(fā)展前景感到興奮,之所以特別有興趣在這里研究這 4 種工具,是因?yàn)樗鼈兡壳暗某墒於龋约皩?duì)它們未來開發(fā)的展望。這里選擇進(jìn)行比較的 4 種工具都足夠成熟,均適用于商業(yè)開發(fā),并且會(huì)在將來的某個(gè)時(shí)候獲得成功。
仔細(xì)分析這篇由兩部分構(gòu)成 AOP 工具比較系列文章中討論的該工具的利弊,這些有助于判斷哪種工具最適合您的項(xiàng)目。文中指出了工具處理方面聲明、編織以及構(gòu)建集成的主要區(qū)別,概述了關(guān)鍵的性能問題;還強(qiáng)調(diào)了 IDE 集成的好處。本文概述了 Java 語(yǔ)言擴(kuò)展的優(yōu)勢(shì)與不足,這個(gè)主題對(duì) Java 開發(fā)人員有深遠(yuǎn)的意義,文章還指出了 AOP 工具的一些未來發(fā)展方向。
在閱讀本文時(shí),讀者可能會(huì)很驚訝地發(fā)現(xiàn)這些工具的相同點(diǎn)要多于它們的不同點(diǎn)。這意味著不管選擇哪項(xiàng)技術(shù),學(xué)習(xí)曲線可以從一個(gè) AOP 工具轉(zhuǎn)移到另一個(gè)。每種工具的新發(fā)展會(huì)繼續(xù)相互滲透。AOP 工具目前正在迅速發(fā)展,可以滿足不斷增長(zhǎng)的用戶社區(qū)的需求;而且它還在不斷發(fā)布新版本。不管您最后采用什么樣的 AOP 工具,都鼓勵(lì)您加入它的用戶討論列表。您的反饋會(huì)幫助這項(xiàng)重要的技術(shù)指明未來的發(fā)展方向。
記著下個(gè)月繼續(xù)關(guān)注 AOP@Work 系列的下一期文章:Ramnivas Laddad 的 “元數(shù)據(jù)和 AOP:天生絕配”。
參考資料
關(guān)于作者 Mik Kersten 是一流的面向方面的編程專家,也是 AspectJ 和 AJDT eclipse.org 項(xiàng)目的參與者。作為 Xerox PARC 的研究科學(xué)家,他為 AspectJ 構(gòu)建了 IDE 支持。他正在不列顛哥倫比亞大學(xué)攻讀博士學(xué)位,他的主要工作是使 IDE 更加面向方面。他也向構(gòu)建開發(fā)工具的公司提供咨詢,幫助公司利用、支持面向方面的編程技術(shù)。 |

|