Aspectj與Spring AOP的對比分析
今天有多個可用的 AOP 庫, 它們需要能夠回答許多問題:
1、是否與用戶現(xiàn)有的或新的應(yīng)用程序兼容?
2、在哪里可以實(shí)現(xiàn) AOP?
3、與自己的應(yīng)用程序集成多快?
4、性能開銷是多少?
在本文中, 我們將研究如何回答這些問題, 并介紹 Spring aop 和 AspectJ, 這是 Java 的兩個最受歡迎的 aop 框架。
2、AOP概念在開始之前, 讓我們對術(shù)語和核心概念進(jìn)行快速、高層次的審查:
Aspect —— 一種標(biāo)準(zhǔn)代碼/功能, 分散在應(yīng)用程序中的多個位置, 通常與實(shí)際的業(yè)務(wù)邏輯不同 (例如, 事務(wù)管理)。每個方面都側(cè)重于特定的跨裁剪功能
Joinpoint —— 它是執(zhí)行程序 (如方法執(zhí)行、構(gòu)造函數(shù)調(diào)用或字段分配) 期間的特定點(diǎn)
Advice —— 特定 joinpoint 中的方面所采取的行動
Pointcut —— 與 joinpoint 匹配的正則表達(dá)式。每次連接點(diǎn)與切入點(diǎn)匹配時, 都將執(zhí)行與該切入點(diǎn)關(guān)聯(lián)的指定建議。
Weaving —— 將各方面與目標(biāo)對象鏈接起來以創(chuàng)建建議對象的過程
3、Spring AOP 和 AspectJ現(xiàn)在, 讓我們在一些維度上討論 Spring AOP 和 AspectJ —— 例如功能、目標(biāo)、Weaving(織入)、內(nèi)部結(jié)構(gòu)、joinpoints 和簡單性。
3.1、能力和目標(biāo)簡單地說, Spring AOP 和 AspectJ 有不同的目標(biāo)。
Spring aop 旨在提供一個跨 Spring IoC 的簡單的 aop 實(shí)現(xiàn), 以解決程序員面臨的最常見問題。它不打算作為一個完整的 AOP 解決方案 —— 它只能應(yīng)用于由 Spring 容器管理的 bean。
另一方面, AspectJ 是原始的 aop 技術(shù), 目的是提供完整的 aop 解決方案。它更健壯, 但也比 Spring AOP 復(fù)雜得多。還值得注意的是, AspectJ 可以在所有域?qū)ο笾袘?yīng)用。
3.2、Weaving(織入)AspectJ 和 Spring AOP 都使用不同類型的編織, 這會影響它們在性能和易用性方面的行為。
AspectJ 使用三種不同類型的Weaving:
編譯時 Weaving: AspectJ 編譯器作為輸入我們的方面的源代碼和我們的應(yīng)用, 并產(chǎn)生一個織入類文件作為輸出;
編譯后 Weaving: 這也稱為二進(jìn)制織入。它是用來織入現(xiàn)有的類文件和 JAR 文件與我們的方面;
加載時間 Weaving: 這就像前二進(jìn)制織入, 不同的是織入被推遲, 直到類加載程序加載類文件到 JVM。
要了解更多關(guān)于 AspectJ 本身的詳細(xì)信息, 請 閱讀此文。
當(dāng) AspectJ 使用編譯時和class文件加載時織入時,Spring AOP 利用運(yùn)行時織入。
使用運(yùn)行時編織, 這些方面在使用目標(biāo)對象的代理執(zhí)行應(yīng)用程序時被編織-使用 JDK 動態(tài)代理或 CGLIB 代理 (在下一點(diǎn)討論):
Spring aop 是基于代理的 aop 框架。這意味著, 要實(shí)現(xiàn)目標(biāo)對象的各個方面, 它將創(chuàng)建該對象的代理。使用以下兩種方法之一實(shí)現(xiàn):
1、JDK 動態(tài)代理 —— Spring AOP 的首選方式。只要目標(biāo)對象實(shí)現(xiàn)甚至一個接口, 就會使用 JDK 動態(tài)代理;
2、CGLIB 代理 —— 如果目標(biāo)對象沒有實(shí)現(xiàn)接口, 則可以使用 CGLIB 代理。
我們可以從 官方文檔 中了解有關(guān) Spring AOP 代理機(jī)制的更多信息。
另一方面, AspectJ 在運(yùn)行時不做任何事情, 因?yàn)轭愂侵苯佑梅矫孢M(jìn)行編譯的。
與 Spring AOP 不同, 它不需要任何設(shè)計(jì)模式。為了編織代碼的各個方面, 它引入了稱為 AspectJ 編譯器 (ajc) 的編譯器, 通過它編譯我們的程序, 然后通過提供一個小型 (100K) 運(yùn)行時庫來運(yùn)行它。
3.4、Joinpoints在3.3 節(jié)中, 我們顯示了 Spring AOP 是基于代理模式的。因此, 它需要將目標(biāo) Java 類分類, 并相應(yīng)地應(yīng)用交叉問題。
但這是有限制的。我們不能在 '最終' 類中應(yīng)用交叉問題 (或方面), 因?yàn)樗鼈儾荒鼙恢貙? 因此會導(dǎo)致運(yùn)行時異常。
同樣適用于靜態(tài)和最終方法。不能將 Spring 方面應(yīng)用于它們, 因?yàn)樗鼈儾荒鼙桓采w。因此, 由于這些限制, Spring AOP 只支持方法執(zhí)行連接點(diǎn)。
然而, AspectJ 在運(yùn)行前直接將橫切關(guān)注點(diǎn)編織到實(shí)際代碼中。與 Spring AOP 不同, 它不需要對目標(biāo)對象進(jìn)行子類, 因此也支持許多其他 joinpoints。
以下是支持的 joinpoints 的摘要:
Joinpoint Spring AOP Supported AspectJ Supported Method Call No Yes Method Execution Yes Yes Constructor Call No Yes Constructor Execution No Yes Static initializer execution No Yes Object initialization No Yes Field reference No Yes Field assignment No Yes Handler execution No Yes Advice execution No Yes還值得注意的是, 在 Spring AOP 中, aspects不應(yīng)用于在同一個類中相互調(diào)用的方法。
這顯然是因?yàn)楫?dāng)我們調(diào)用同一類中的方法時, 我們就不會調(diào)用 Spring AOP 提供的代理的方法。如果我們需要這個功能, 那么我們必須在不同的 bean 中定義一個單獨(dú)的方法, 或者使用 AspectJ。
3.5、簡單性Spring AOP 顯然更簡單, 因?yàn)樗粫谖覀兊臉?gòu)建過程中引入任何額外的編譯器或織入。它使用運(yùn)行時編織, 因此它與我們通常的構(gòu)建過程無縫集成。雖然它看起來很簡單, 但它只適用于由 Spring 管理的 bean。
但是, 要使用 AspectJ, 我們需要引入 AspectJ 編譯器 (ajc) 并重新打包所有的庫 (除非我們切換到編譯后或加載時間的織入)。
當(dāng)然, 這比前者更復(fù)雜, 因?yàn)樗肓?AspectJ Java 工具 (包括編譯器 (ajc)、調(diào)試器 (ajdb)、文檔生成器 (ajdoc)、程序結(jié)構(gòu)瀏覽器 (ajbrowser)), 我們需要將它們與我們的 IDE 或生成工具。
3.6、性能就性能而言, 編譯時織入比運(yùn)行時織入快得多。Spring AOP 是基于代理的框架, 因此在應(yīng)用程序啟動時會創(chuàng)建代理。另外, 每個方面還有一些方法調(diào)用, 這會對性能產(chǎn)生負(fù)面影響。
另一方面, AspectJ 在應(yīng)用程序執(zhí)行之前將這些方面編織到主代碼中, 因此沒有額外的運(yùn)行時開銷, 與 Spring AOP 不同。
基于這些原因, 基準(zhǔn)表明 AspectJ 的速度幾乎比 Spring AOP 快8到35倍。
4、總結(jié)此快速表總結(jié)了 Spring AOP 和 AspectJ 之間的關(guān)鍵區(qū)別:
Spring AOP AspectJ 在純 Java 中實(shí)現(xiàn) 使用 Java 編程語言的擴(kuò)展實(shí)現(xiàn) 不需要單獨(dú)的編譯過程 除非設(shè)置 LTW,否則需要 AspectJ 編譯器 (ajc) 只能使用運(yùn)行時織入 運(yùn)行時織入不可用。支持編譯時、編譯后和加載時織入 功能不強(qiáng)-僅支持方法級編織 更強(qiáng)大 - 可以編織字段、方法、構(gòu)造函數(shù)、靜態(tài)初始值設(shè)定項(xiàng)、最終類/方法等......。 只能在由 Spring 容器管理的 bean 上實(shí)現(xiàn) 可以在所有域?qū)ο笊蠈?shí)現(xiàn) 僅支持方法執(zhí)行切入點(diǎn) 支持所有切入點(diǎn) 代理是由目標(biāo)對象創(chuàng)建的, 并且切面應(yīng)用在這些代理上 在執(zhí)行應(yīng)用程序之前 (在運(yùn)行時) 前, 各方面直接在代碼中進(jìn)行織入 比 AspectJ 慢多了 更好的性能 易于學(xué)習(xí)和應(yīng)用 相對于 Spring AOP 來說更復(fù)雜 5、選擇正確的框架如果我們分析了本節(jié)中提出的所有論點(diǎn), 我們就會開始理解, 一個框架比另一個架構(gòu)更好。
簡單地說, 選擇很大程度上取決于我們的要求:
框架: 如果應(yīng)用程序沒有使用 spring 框架, 那么我們就別無選擇, 只能放棄使用 spring AOP 的想法, 因?yàn)樗鼰o法管理任何超出 spring 容器范圍的東西。但是, 如果我們的應(yīng)用程序是完全使用 spring 框架創(chuàng)建的, 那么我們可以使用 spring AOP, 因?yàn)樗呛唵蔚膶W(xué)習(xí)和應(yīng)用
靈活性: 由于有限的 joinpoint 支持, Spring aop 不是一個完整的 aop 解決方案, 但它解決了程序員面臨的最常見的問題。盡管如果我們想深入挖掘和開發(fā) AOP 以達(dá)到其最大能力, 并希望得到廣泛的可用 joinpoints 的支持, 那么最好選擇 AspectJ
性能: 如果我們使用的是有限的切面, 那么就會有細(xì)微的性能差異。但有時, 應(yīng)用程序有成千上萬個切面的情況。我們不想在這樣的情況下使用運(yùn)行時編織, 所以最好選擇 AspectJ。AspectJ 已知的速度比 Spring AOP 快8到35倍
兩者的最佳之處: 這兩個框架都是完全兼容的。我們總是可以利用 Spring AOP; 只要有可能, 仍然可以在不支持前者的地方使用 AspectJ 獲得支持
6、結(jié)論在本文中, 我們分析了 Spring AOP 和 AspectJ 的幾個關(guān)鍵領(lǐng)域。
我們比較了兩種 AOP 方法的靈活性, 以及它們將如何輕松地適應(yīng)我們的應(yīng)用程序。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. WML語言的基本情況2. 淺談python多線程和多線程變量共享問題介紹3. python利用platform模塊獲取系統(tǒng)信息4. Python 多線程之threading 模塊的使用5. CSS代碼檢查工具stylelint的使用方法詳解6. Python如何批量獲取文件夾的大小并保存7. Java WindowBuilder 安裝及基本使用的教程8. react axios 跨域訪問一個或多個域名問題9. Python的Tqdm模塊實(shí)現(xiàn)進(jìn)度條配置10. python 實(shí)現(xiàn)rolling和apply函數(shù)的向下取值操作
