深入理解 SpringAOP(一):AOP 組件概述

概述

spring-aop 模塊是 Spring 框架中最重要的組件之一,它爲我們提供了強大的 AOP 功能,併爲其他擴展功能(如聲明式事務、聲明式異步處理等)提供了支持。在本文中,我們將深入探討 SpringAOP 的源碼,從代理對象的創建開始,揭示 SpringAOP 的運行機制。

首先,在閱讀這篇文章前,請先確保對 Spring 中 Bean 創建流程有基本的瞭解,因爲實際上這個流程也是 SpringAOP 生效的關鍵。在這個基礎上,我們將聚焦於 SpringAOP 中的後處理器,以及與 AOP 功能密切相關的通知器、通知和切點等組件或概念,通過對這些組件的代碼結構深入認知,我們將更好地理解 SpringAOP 的內部工作原理。

當我們描述 AOP 的時候,它通常包含下述概念/組件:

  • 通知 Advice :是切面邏輯的具體實現,它決定了在切點處執行什麼操作;
  • 切點 Pointcut:程序執行過程中的一個特定點,例如方法的調用或異常的拋出,它是通知的觸發點;
  • 通知器 Advisor :它代表了要對哪些對象、在哪裏、應用哪些通知,它通常是且不限於是通知和切點的組合體;
  • 連接點 Joinpoint :它代表了程序中的某一處位置,通常包含切點切入位置的一些信息,比如 MethodInvocationConstructorInvocation
  • 切面 Aspect:它是 AspectJ 的概念,在 Spring 中可以認爲是一個同時包含多種 Advisor 的聚合體,實際使用時,我們通過 @Aspect 註解聲明的切面中的方法會被轉爲多個 Advisor

接下來,我們將圍繞着上述內容,展開研究。

本專題共三篇文章,這是第一篇:

  • 深入理解 SpringAOP(一):AOP 組件概述;
  • 深入理解 SpringAOP(二):AOP的執行流程;
  • 深入理解 SpringAOP(三):AspectJ支持;

一、通知器

因此,某種程度上來說,Advisor 就是某個具體切入規則的最小單位。

1、實現體系

image.png
通知器 Advisor 本身的方法異常簡單,它只規定“要在哪裏應用哪些通知”,而“對哪些類使用”則交由子類來實現:

public interface Advisor {
	
	// 獲取通知操作,即具體的操作邏輯
	Advice getAdvice();

	// 每個切入目標是否都需要一個新的通知器
	boolean isPerInstance();

}

因此一般 Advisor 不會直接使用,而是轉爲具體的 PointcutAdvisorIntroductionAdvisor 使用。

2、切點通知器

PointcutAdvisor ,直譯即切點通知器,允許通知器提供一個切點類 Pointcut ,用於匹配特定的方法或者類:

public interface PointcutAdvisor extends Advisor {

	// 獲取切點,即類或方法匹配器
	Pointcut getPointcut();

}

它也是最常見的通知器,Spring 中大部分我們熟知的功能都基於它實現,比如用於處理 @Async 註解的 AsyncAnnotationAdvisor ,與用於處理 @Transcational 註解的 TransactionAttributeSourceAdvisor (嚴格來說這麼說並不準確,因爲實際上註解是由 TransactionAnnotationParser 處理的,不過這裏我們認爲它們相關)。

3、引介入通知器

IntroductionAdvisor ,直譯即爲引介通知器,比較少用到的通知器,用於實現接口引入——即讓一個 bean 無中生有的獲得特定某些接口的方法,有點類似於 kotlin 的擴展函數:

public interface IntroductionInfo {

	// 需要引入的接口,即被切入的類等於變相的實現了這些接口
	Class<?>[] getInterfaces();

}

它比較常用的實現應該是 DeclareParentsAdvisor ,用於配合 AspectJ@DeclareParents 做接口引入,不過確實不太常見,因此我們瞭解即可。

二、通知

image.png
Advice 即 “通知”,它表示切入對象後,需要“在什麼地方做什麼事”。它的子接口非常多,但是按切入位置可以簡單分爲三類:

  • 執行前通知:BeforeAdvice
  • 環繞通知:InterceptorAdvice
  • 後置通知:AfterAdvice ,這裏又分爲返回後通知 AfterReturningAdvice 和異常通知 ThrowsAdvice

比較有趣的是,除了 DynamicIntroductionAdvice 外,AdviceInterceptorBeforeAdviceAfterAdvice  這幾個頂級接口都是沒有抽象方法的標記接口,因此我們可以一般只關注具體的實現接口即可。
方法攔截器與切點
方法攔截器 MethodInterceptor 最常見的 Advice ,我們熟知的絕大部分基於 SpringAOP 提供的功能都依賴它實現——實際上,就算是其他的實現,到最後執行代理方法的時候依然要適配爲 MethodInterceptor 去執行。

public interface MethodInterceptor extends Interceptor {

	// 攔截方法調用
	@Nullable
	Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;

}

在這裏,我們就會接觸到 Joinpoint ,也就是切點的概念,MethodInvocation就是方法切點:
它包含了一次方法調用中的一些已知信息,包括調用的方法、調用的參數等等,最常見的實現是 ReflectiveInvocation ,我們在 AspectJ 中接觸的 JoinPoint 跟它基本一樣。
image.png

三、切點

切面 Pointcut 是屬於 PointcutAdvisor 的一個組件,它用於匹配類或者方法:

public interface PointcutAdvisor extends Advisor {

	/**
	 * Get the Pointcut that drives this advisor.
	 */
	Pointcut getPointcut();
}

切點由類型過濾器 ClassFilter 和方法匹配器 MethodMatcher 兩個組件共同組成:

public interface Pointcut {

	/**
	 * Return the ClassFilter for this pointcut.
	 * @return the ClassFilter (never {@code null})
	 */
	ClassFilter getClassFilter();

	/**
	 * Return the MethodMatcher for this pointcut.
	 * @return the MethodMatcher (never {@code null})
	 */
	MethodMatcher getMethodMatcher();

}

當使用時,將僅會攔截 ClassFilter  不過濾的類中與 MethodMatcher 匹配的方法。
比較常用的實現類爲支持對類和方法名進行表達式匹配的 NameMatchMethodPointcut ,與支持 Spring 元註解機制,能夠按照類和方法上註解進行匹配的 AnnotationMatchingPointcut

四、後處理器

image.png
AOP 發生在 Bean 的創建過程中,它基於特定的後處理器 AbstractAutoProxyCreator 完成,當然,實際上它的背後是一個大家族:
兩個關鍵的抽象類

  • AbstractAutoProxyCreatorAbstractAutoProxyCreator是一個抽象類,實現了BeanPostProcessor接口,用於自動創建代理對象。它的作用是在Spring容器中自動檢測符合條件的bean,並對其進行代理。它可以根據一些配置條件(例如bean的名稱、類型、註解等)決定是否對目標bean進行代理,並提供了一些鉤子方法供子類實現自定義的代理邏輯;
  • AbstractAdvisorAutoProxyCreatorAbstractAdvisorAutoProxyCreatorAbstractAutoProxyCreator 的子類,它進一步擴展了自動代理的功能。除了 AbstractAutoProxyCreator 的功能外,AbstractAdvisorAutoProxyCreator 還能夠通過配置Advisor(通知器)來決定代理的行爲;

兩個關鍵的實現類

  • AspectJAwareAdvisorAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator 繼承自 AbstractAdvisorAutoProxyCreator,它是Spring AOP的一個關鍵組件之一,用於實現基於AspectJ註解的自動代理。它支持使用AspectJ註解(如 @Aspect@Pointcut@Before@After 等)來定義切面,然後根據這些切面的定義,在目標 bean 上應用相應的通知;
  • AnnotationAwareAspectJAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreatorAspectJAwareAdvisorAutoProxyCreator 的子類,它進一步擴展了 AspectJ 註解的自動代理功能。與 AspectJAwareAdvisorAutoProxyCreator 相比,AnnotationAwareAspectJAutoProxyCreator 提供了更加靈活的註解驅動的 AOP 配置方式。它支持使用 @Aspect 註解定義切面,並且還支持其他註解如 @Before@After@Around 等,用於在目標 bean 的方法上應用切面邏輯;

默認情況下,我們的項目都是基於 AnnotationAwareAspectJAutoProxyCreator 實現的 AOP 功能。
在後文,我們會深入後處理器的源碼,從而跟蹤 AOP 的運行流程。

總結

image.png

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