Spring AOP基礎

結繩記事,總結,思考,方有成長~

AOP是什麼

AOP是Aspect Oriented Programing的簡稱,即面向切面編程。它爲程序開發提供了一個嶄新的思考角度,可以將重複性的橫切邏輯抽取到統一的模塊中。通過OOP的縱向抽象和AOP的橫向抽取,程序纔可以真正解決重複性代碼問題。

AOP術語

  • 連接點(Joinpoint):類中具有邊界性質的特定點,比如類中某個方法調用前、調用後、方法拋出異常後,這都是被稱爲“連接點”。
  • 切點(Pointcut):在爲數衆多的“連接點”中,AOP通過“切點”定位到具體的“連接點”。藉助數據庫查詢概念來理解再好不過:連接點相當於數據庫中的記錄,而切點相當於查詢條件。切點和連接點不是一對一的關係,一個切點可以匹配多個連接點。
  • 增強(Advice):織入目標類連接點上的程序代碼,同時也包含方位信息,比如方法執行前、執行後、拋出異常後。
  • 織入(Weaving):將增強添加到目標類的具體連接點上的過程,AOP有3種織入方式:
    • 編譯期織入,要求使用特殊的Java編譯器。
    • 類裝載期織入,要求使用特殊的類裝載器。
    • 動態代理織入,在運行期爲目標類添加增強生成子類的方式。
      Spring採用動態代理織入,使用純Java實現,不需要專門的編譯過程,也不需要特殊的類裝載器,它在運行期通過代理方式向目標類織入增強代碼。
      AspectJ採用編譯期織入和類裝載期織入,是語言級的AOP實現,有一個專門的編譯器來生成遵守Java字節碼規範的Class文件。
  • 代理(Proxy):一個類被AOP織入增強後,就產生一個結果類,它是融合了原類和增強邏輯的代理類。
    Spring AOP使用動態代理技術在運行期織入增強的代碼,分爲JDK動態代理 和 CGLib動態代理。使用JDK動態代理,目標類必須實現接口,而CGLib不對目標類做任何限制,它通過動態生成目標類子類的方式提供代理。JDK在創建代理對象時性能高於CGLib,而生成的代理對象的運行性能卻比CGLib低。如果是singleton的代理,則推薦使用CGLib動態代理。
  • 切面(Aspect):切面由切點和增強組成。即包括了橫切代碼的邏輯,又包括了連接點的定義。

AOP無法增強

例如在一個service類中有2個方法bus1()和bus2()都使用了@Cacheable緩存註解也就是希望2個方法都啓用緩存。如果業務處理過程中,bus1()調用了bus2(),則bus2()方法永遠無法啓用緩存。
原因爲:方法內部之間調用的時候,不會使用被增強的代理類,而是直接調用未被增強原類的方法,這也就是bus2()無法被織入增強的原因。

@AspectJ

Spring AOP中定義一個切面是比較繁瑣的,需要實現專門的接口,並進行一些較爲複雜的配置,推薦使用@AspectJ註解,可以非常容易的定義一個切面,而不需要實現任何接口。
注意:Spring在處理@AspecJ註解表達式時,需要將Spring的asm模塊添加到類路徑中。asm是輕量級的字節碼處理框架,因爲Java的反射機制無法獲取入參名,Spring就利用asm處理@AspectJ中所描述的方法入參名。
此外,Spring採用AspectJ提供的@AspectJ註解類庫及相應的解析類庫,需要再pom.xml文件中添加aspect.weaver和aspectj.tools類包的依賴。
在使用@AspectJ切面時,需要基於Schema的aop命名空間進行配置,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="……"
			xmlns:aop="http://www.……">
			<!-- 基於@AspectJ切面的驅動器>
			<aop:aspectj-autoproxy />
</beans>

@AspectJ定義切面的切點表達式,最合適的方式推薦註解,自定義註解,然後在需要增強的方法上使用該註解即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章