Spring AOP 知識點 & 實現機制
一、關於AOP
1. 什麼是 AOP?
-
Aspect Orentied Programming:面向切面程式設計
-
Object Orentied Programming:面向物件程式設計
-
AOP 程式設計是以 OOP 為基礎,OOP 側重點是物件抽象和封裝,AOP 側重點時共通處理部分的封裝和使用,用於改善共通元件。是對 OOP 的補充和完善
2. AOP 的作用
-
分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。舉個例子:開發中為了除錯,或在生產環境後為了對系統進行監控,需要為業務需求的實現物件新增日誌記錄功能,或者,業務方法的執行需要一定的許可權限制。如果以面向物件的方式實現,就需要把系統中的每個業務物件都加入日誌記錄,加入相應的安全檢查,那麼,這些實現程式碼就會遍及所有的業務物件中。如果對這些程式碼進行模組化的組織,簡化系統需求與實現之間的對比關係,通過某種方式在適當的時候呼叫這些程式碼,那麼就不用每個業務方法裡都寫著相同的程式碼了
3. 什麼時候用AOP
-
日誌功能
-
安全檢查
-
事務管理
-
快取
二、AOP 相關概念
1.Joinpoint
-
Joinpoint 就是進行織入操作的系統執行點
2.Pointcut
-
是 Joinpoint的表述方式,指定了系統中符合條件的一組 Joinpoint
3.Advice
-
Advice 代表的是織入到 Joinpoint 的橫切邏輯
-
分類:
-
Before Advice:在指定位置之前執行,可以做一些初始化工作,比如設定系統初始值,獲取必要系統資源
-
After Advice
-
After returning Advice :當 當前 Joinpoint 正常執行完後,比如方法正常返回而沒有丟擲異常
-
After throwing Advice:當 當前 Joinpoint 執行過程中丟擲異常的情況下,才會執行
-
After Advice:不管是否正常返回,都會執行,相當於 finally 塊一樣
-
-
Around Advice:可以在 Joinpoint 之前 或者 之後都能執行相應的邏輯,Filter功能就是其中的一種實現。可以用來系統安全驗證及檢查,簡單的日誌記錄以及系統附加行為的新增
-
4.Aspect
-
是對系統中的橫切關注點邏輯進行模組化封裝的 AOP 概念實體,其可以包含多個 Pointcut 以及相關 Advice定義。
-
如果將 Aspect 比作 OOP 中的Class,那麼 Advice 就相當於 CLass 中的 Method
5.織入和織入器
-
AspectJ 有專門的編譯器來完成織入操作,ProxyFactory 是 Spring AOP 中最通用的織入器
6.目標物件
-
符合 Pointcut 所指定的條件,在織入過程中被織入橫切邏輯的物件
三、Spring AOP 的實現機制
1. 實現機制
-
spring AOP 屬於第二代AOP(動態AOP),採用動態代理機制和位元組碼生成技術實現,與最初的 AspectJ採用編譯器將橫切邏輯織入目標物件不同,動態代理機制和位元組碼生成都是在執行期間為目標物件生成一個代理物件,而將橫切邏輯織入到這個代理物件中,系統最終使用的是織入了橫切邏輯的代理物件,而不是真正的目標物件
2.動態代理
-
一般的代理模式是有多少需要代理的物件就要寫多少代理類,但是jdk 1.3 之後引入了一種稱之為動態代理的機制,使用該機制,可以為指定的介面在系統執行期間動態的生成代理物件
-
實現:
-
java.lang.reflect.Proxy 類 和 java.lang.reflect.InvocatingHandler 介面。當 Proxy動態生成的代理物件上的相應的介面方法被呼叫時,對應的InvocationHandler就會攔截相應的方法呼叫,並進行相應的處理。InvocationHandler 就是實現橫切邏輯的地方,是橫切邏輯的載體
-
-
適用:
-
只能對實現了相應 Interface 的類使用。如果目標物件沒有實現任何 Interface,spring AOP 會嘗試使用一個稱為 CGLIB 的開源的動態位元組碼生成類庫,為目標物件生成動態的代理物件例項
-
3.動態位元組碼生成
-
原理:對目標物件進行繼承擴充套件,為其生成相應的子類,而子類可以通過重寫類擴充套件父類的行為,只要將橫切邏輯的實現放到子類中,然後讓系統使用擴充套件後的目標物件的子類,就OK了。(在系統執行期間動態為目標物件生成相應的擴充套件子類)
四、靜態 AOP
1. 靜態 AOP 的優缺點
-
優點:直接以 Java位元組碼的形式編譯到 Java 類中,java虛擬機器可以像通常一樣載入 java類執行
-
缺點:不夠靈活,如果需要進行修改,就需要重新編譯
2.spring AOP中的 Joinpoint
-
在spring AOP中,只支援方法級別的 Joinpoint
3.spring AOP中的Pointcut
-
public interface Pointcut {
Pointcut TRUE;
ClassFilter getClassFilter();//匹配物件
MethodMatcher getMethodMatcher();//匹配方法
static default {
TRUE = TruePointcut.INSTANCE;
}
}
//ClassFilter 介面的作用是對Joinpoint所處的物件進行Class級別的型別匹配
public interface ClassFilter{
boolean maches(Class clazz);//當織入的目標物件的Class型別與Pointcut所規定的型別相符時,將返回true
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
//方法級別的攔截
public interface MethodMatcher {
MethodMatcher TRUE;
boolean matches(Method var1, Class<?> var2);
boolean isRuntime();// 當不用檢查引數時,返回false
boolean matches(Method var1, Class<?> var2, Object... var3);
static default {
TRUE = TrueMethodMatcher.INSTANCE;
}
}
1.Pointcut的族譜
StaticMethodmacher :isRuntime 返回false,可以進行快取提高效能
DynamicMethodMacher:isRuntime 返回true,因為每次都要對方法引數進行檢查,無法對匹配結果進行快取
4. spring AOP 中的 Advise
1.Advice類圖
per-class 型別的advice就是以下中的advice,這種advice例項可以在目標物件類的所有實現之間共享,通常只是提供方法級別的攔截功能,不會為目標物件類儲存任何狀態或者新增新的特性
5. spring AOP 中的 Aspect
1.Advisor
在Spring中,Advisor 代表的是Aspect,理論上,Aspect可以有多個 Pointcut 和 多個 Advice,但是,Advisor 通常支援有一個Pointcut 和 一個 Advice
2.PointcutAdvisor 族譜
任何型別的 Pointcut、Advice 都可以通過DefaultPointcutAdvisor來使用
NameMatchMethodPointcutAdvisor 限定了自身可以使用的 Pointcut 型別為 NameMatchMethodPointcut,當通過 Advisor 的 setMappedName 方法設定將被攔截的方法名稱的時候,實際上是在操作 NameMatchMethodPointcutAdvisor 所持有的 NameMatchMethodPointcut例項
RegexpmethodPointcutAdvisor 通過正則表示式為其設定相應的Pointcut
DefaultBeanFactoryPointcutAdvisor:其作用是可以通過容器中的Advice註冊的beanName來關聯對應的Advice,只有當對應的Pointcut匹配成功之後,才去例項化對應的Advice,減少了容器啟動初期Advisor 和 Advice之間的耦合性
6.spring AOP 的織入
1. ProxyFactory織入器
根據AdvisedSupport 建立AOPProxy
2.AdvisedSupport:生成代理物件所需要資訊的載體
ProxyConfig:定義了生成代理物件應該才去的行為措施
Advised:針對哪些類生成哪種橫切邏輯
3.ProxyFactory
ProxyFactory 集AopProxy 和 AdvisedSupport於一身,可以通過ProxyFactory設定生成代理物件所需要的相關資訊,也可以通過ProxyFactory 取得最終生成的代理物件。前者是AdvisedSupport的職責,後者是AopProxy的職責
為了重用相關邏輯,Spring Aop 框架在實現的時候,將一些共用的邏輯抽取到了ProxyCreatorSupport 中,它自身就繼承了 AdvisorSupport ,所以生成的代理物件的必要資訊從其自身就可以拿到。為了簡化子類生成不同型別 AopProxy ,ProxyCreatorSupport 內部持有一個 AopProxyFactory 例項。
五、動態AOP
1. 動態AOP 的優缺點
優點:AOP的織入過程在系統執行開始之後進行,而不是預先編譯到系統類中,而織入資訊大都採用外部 xml 檔案格式儲存
缺點:因為動態 AOP 的實現大都在類載入或者系統執行期間,採用對系統位元組碼進行操作的方式來完成織入,難免會造成一定的效能損失
2. 使用
在 Aspect 類上加上 @Aspect 註解
用 @Pointcut 定義切入點
@Before、@AfterThrowing、@AfterReturning、@After、@Around: 用value 指定 Pointcut,指定Aspect
配置檔案中要新增 <aop:aspectj-autoproxy/>
3. 基於Aop 名稱空間
<aop:config >
<aop:pointcut>
<aop:advisor pointcut advise order>
</aop:config>