AOP 概述及相關基礎知識

一、AOP 概述

AOP 是 Aspect Oriented Programing 的簡稱,面向切面的編碼;

AOP 的工作重心是如何將增強應用到目標對象的連接點上:

        第一,通過切點和增強定位到連接點上;

        第二,在增強中編寫切面的代碼;

 

1.1、連接點 - Joinpoint

Spring 僅支持方法的連接點;

連接點由兩個個信息確定:

       (1)一是用方法表示的程序 執行點

(2)二是用相對位置表示的 方位

如在 Test.foo() 方法執行前的連接點,執行點是 Test.foo(),方位是該方法執行前的位置;

 

1.2、切點 - Pointcut

切點可以用來定位連接點;

在 Spring 中,切點通過 org.springframework.aop.Pointcut 接口進行描述,使用類和方法作爲連接點的查詢條件,Spring AOP 的規則解析引擎負責解析切點所設定的查詢條件,找到連接點,準備的說是 執行點;

Spring 通過 org.springframework.aop.Pointcut 接口描述切點:

  • ClassFilter:定位到某些特定類上;
  • MethodMatcher:定位到某些特定的方法上;

 

1.3、增強 - Advice

增強是織入目標類連接點上的 一段程序代碼

在 Spring 中,增強還擁有一個和連接點有關的信息,就是 執行點的方位

如 BeforeAdvice、AfterReturningAdvice、ThrowsAdvice 等;

 

1.4、目標對象 - Target

增強邏輯的織入目標類;

 

1.5、引介 - Introduction

引介是一種特殊的增強,它可以爲類添加一些屬性和方法,比如間接的幫業務類實現某個接口;

 

1.6、織入 - Weaving

織入就是將增強或者引介添加到目標類的具體連接點上的過程;

(1)編譯期織入,要求使用特殊的 Java 編譯器;

(2)類裝載期織入,要求使用特殊的類裝載器;

(3)動態代理織入,在運行期爲目標類添加增強生成子類的方式;

Spring 採用的是 動態代理織入,而 AspectJ 採用 編譯期織入和類裝載期織入

 

1.7、代理 - Proxy

一個類被 AOP 織入增強後,會產生一個結果類,它是 融合了原類和增強邏輯的代理類;

 

1.8、切面 - Aspect

切面由 切點增強(引介)組成;

包含了 橫切代碼 和 連接點 信息;

 

二、基礎知識 - 動態代理技術

Spring AOP 使用動態代理技術在運行期織入增強的代碼,它使用了兩種代理機制:

(1)一種是基於 JDK 的動態代理;

(2)一種是基於 CGLib 的動態代理;

之所以需要兩種動態代理機制,是因爲 JDK 本身只提供接口的代理,而不支持類的代理;

二者的區別可以參考我之前的文章:Spring AOP 兩種動態代理機制

 

JDK 的動態代理主要涉及 java.lang.reflect 包中的兩個類:

(1)Proxy ;

(2)InvocationHandler(是一個接口);

 

原始的 AOP 有三個問題:

(1)目標類的所有方法都添加了性能監視橫切邏輯,但是我們只希望對業務類中的某些特定的方法添加橫切邏輯;

(2)通過硬編碼的方式指定了織入橫切邏輯的織入點,及在方法開始前還是結束前織入代碼;

(3)手工編寫代理實例的創建過程,爲不同的類創建代理時,需要分別編寫相應的創建代碼,無法做到通用;

Spring AOP 則是通過 Pointcut 指定哪些類的哪些方法需要織入橫切邏輯,通過 Advice 描述橫切邏輯和方法的具體織入方位;其通過 切面 Advisor 將 Pointcut 和 Advice 組裝起來,這樣就可以利用 JDK 和 CGLib 採用統一的方式爲目標對象創建織入切面的代理對象了;

 

 

三、問題

3.1、spring AOP無法攔截內部方法調用(方法 A 內部調用了本類的方法 B,B沒有得到增強)?

方法內部之間調用的時候,不會使用被增強的代理類,而是直接調用未被增強的原類方法;

解決方法有很多,將增強類寫入原類中屬性中,然後使用該屬性調用 B 方法,或者使用如下方法:

(1)配置文件添加 expose-proxy 屬性,值爲 true;

        <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true">

(2)內部調用的地方使用,使用前先判斷 AopContext.currentProxy() 是否存在;

        ((類名) AopContext.currentProxy()).方法名

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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