比較Spring AOP與AspectJ

本文翻譯自博客Comparing Spring AOP and AspectJ程序員

介紹

現在有多個可用的AOP庫,這些組件須要回答一系列的問題:web

  • 是否與我現有的應用兼容?
  • 我在哪實現AOP?
  • 集成到個人應用是否很快?
  • 性能開銷是多少?

本文中,咱們將會着重回答這些問題,並介紹兩款Java最流行的AOP框架:Spring AOP 和 AspectJ。正則表達式

AOP概念

在咱們開始以前,讓咱們對術語和核心概念作一個快速,高水平的回顧:spring

  • Aspect切面:一個分佈在應用程序中多個位置的標準代碼/功能,一般與實際的業務邏輯(例如事務管理)不一樣。 每一個切面都側重於一個特定的橫切功能。
  • Joinpoint鏈接點:這是程序執行中的特定點,如方法執行,構調用造函數或字段賦值等。
  • Advice通知:在一個鏈接點中,切面採起的行動
  • Pointcut切點:一個匹配鏈接點的正則表達式。 每當任何鏈接點匹配一個切入點時,就執行與該切入點相關聯的指定通知。
  • Weaving織入:連接切面和目標對象來建立一個通知對象的過程。

Spring AOP and AspectJ

如今,一塊兒來討論Spring AOP and AspectJ,跨越多指標,如能力和目標、織入方式、內部結構、鏈接點和簡單性。設計模式

Capabilities and Goals

簡而言之,Spring AOP和AspectJ有不一樣的目標。
Spring AOP旨在經過Spring IoC提供一個簡單的AOP實現,以解決編碼人員面臨的最常出現的問題。這並非完整的AOP解決方案,它只能用於Spring容器管理的beans。瀏覽器

另外一方面,AspectJ是最原始的AOP實現技術,提供了玩這個的AOP解決方案。AspectJ更爲健壯,相對於Spring AOP也顯得更爲複雜。值得注意的是,AspectJ可以被應用於全部的領域對象。微信

Weaving

AspectJ and Spring AOP使用了不一樣的織入方式,這影響了他們在性能和易用性方面的行爲。
AspectJ使用了三種不一樣類型的織入:框架

  1. 編譯時織入:AspectJ編譯器同時加載咱們切面的源代碼和咱們的應用程序,並生成一個織入後的類文件做爲輸出。
  2. 編譯後織入:這就是所熟悉的二進制織入。它被用來編織現有的類文件和JAR文件與咱們的切面。
  3. 加載時織入:這和以前的二進制編織徹底同樣,所不一樣的是織入會被延後,直到類加載器將類加載到JVM。

更多關於AspectJ的信息,請見head on over to this article函數

AspectJ使用的是編譯期和類加載時進行織入,Spring AOP利用的是運行時織入。工具

運行時織入,在使用目標對象的代理執行應用程序時,編譯這些切面(使用JDK動態代理或者CGLIB代理)。

springaop-process
springaop-process

Internal Structure and Application

Spring AOP 是一個基於代理的AOP框架。這意味着,要實現目標對象的切面,將會建立目標對象的代理類。這能夠經過下面兩種方式實現:

  • JDK動態代理:Spring AOP的首選方法。 每當目標對象實現一個接口時,就會使用JDK動態代理。
  • CGLIB代理:若是目標對象沒有實現接口,則可使用CGLIB代理。

關於Spring AOP能夠經過官網瞭解更多。
另外一方面,AspectJ在運行時不作任何事情,類和切面是直接編譯的。所以,不一樣於Spring AOP,他不須要任何設計模式。織入切面到代碼中,它引入了本身的編譯期,稱爲AspectJ compiler (ajc)。經過它,咱們編譯應用程序,而後經過提供一個小的(<100K)運行時庫運行它。

Joinpoints

在上一小節,咱們介紹了Spring AOP基於代理模式。所以,它須要目標類的子類,並相應的應用橫切關注點。可是也伴隨着侷限性,咱們不能跨越「final」的類來應用橫切關注點(或切面),由於它們不能被覆蓋,從而致使運行時異常。

一樣地,也不能應用於靜態和final的方法。因爲不能覆寫,Spring的切面不能應用於他們。所以,Spring AOP因爲這些限制,只支持執行方法的鏈接點。
然而,AspectJ在運行前將橫切關注點直接織入實際的代碼中。 與Spring AOP不一樣,它不須要繼承目標對象,所以也支持其餘許多鏈接點。AspectJ支持以下的鏈接點:

joinpoint
鏈接點支持

一樣值得注意的是,在Spring AOP中,切面不適用於同一個類中調用的方法。這很顯然,當咱們在同一個類中調用一個方法時,咱們並無調用Spring AOP提供的代理的方法。若是咱們須要這個功能,能夠在不一樣的beans中定義一個獨立的方法,或者使用AspectJ。

Simplicity

Spring AOP顯然更加簡單,由於它沒有引入任何額外的編譯期或在編譯期織入。它使用了運行期織入的方式,所以是無縫集成咱們一般的構建過程。儘管看起來很簡單,Spring AOP只做用於Spring管理的beans 。

然而,使用AspectJ,咱們須要引入AJC編譯器,從新打包全部庫(除非咱們切換到編譯後或加載時織入)。這種方式相對於前一種,更加複雜,由於它引入了咱們須要與IDE或構建工具集成的AspectJ Java工具(包括編譯器(ajc),調試器(ajdb),文檔生成器(ajdoc),程序結構瀏覽器(ajbrowser))。

Performance

考慮到性能問題,編譯時織入比運行時織入快不少。Spring AOP是基於代理的框架,所以應用運行時會有目標類的代理對象生成。另外,每一個切面還有一些方法調用,這會對性能形成影響。

AspectJ不一樣於Spring AOP,是在應用執行前織入切面到代碼中,沒有額外的運行時開銷。

因爲以上緣由,AspectJ通過測試大概8到35倍快於Spring AOP。benchmarks

對比

這個快速表總結了Spring AOP和AspectJ之間的主要區別:

com
對比

選擇合適的框架

若是咱們分析本節全部的論點,咱們就會開始明白,沒有絕對的一個框架比另外一個框架更好。
簡而言之,選擇很大程度上取決咱們的需求:

  • 框架:若是應用程序不使用Spring框架,那麼咱們別無選擇,只能放棄使用Spring AOP的想法,由於它沒法管理任何超出spring容器範圍的東西。 可是,若是咱們的應用程序徹底是使用Spring框架建立的,那麼咱們可使用Spring AOP,由於它很直接便於學習和應用。
  • 靈活性:鑑於有限的鏈接點支持,Spring AOP並非一個完整的AOP解決方案,但它解決了程序員面臨的最多見的問題。 若是咱們想要深刻挖掘並利用AOP達到其最大能力,並但願得到來自各類可用鏈接點的支持,那麼AspectJ是最佳選擇。
  • 性能:若是咱們使用有限的切面,那麼性能差別很小。 可是,有時候應用程序有數萬個切面的狀況。 在這種狀況下,咱們不但願使用運行時織入,因此最好選擇AspectJ。 已知AspectJ比Spring AOP快8到35倍。
  • 共同優勢:這兩個框架是徹底兼容的。 咱們能夠隨時利用Spring AOP,而且仍然使用AspectJ來得到前者不支持的鏈接點。

總結

在這篇文章中,咱們分析了Spring AOP和AspectJ比較關鍵的幾個方面。咱們比較了AOP和AOP兩種方法的靈活性,以及它們與咱們的應用程序的匹配程度。

訂閱最新文章,歡迎關注個人公衆號

微信公衆號
相關文章
相關標籤/搜索