在前文中我們已經分析了 Spring AOP 如何生成 Proxy 代理對象,今天我們將深入探討攔截器鏈是如何被調用的——這正是 Proxy 模式發揮作用的核心環節,也是 Spring 為我們提供 AOP 功能的關鍵實現路徑。
在 JdkDynamicAopProxy 中生成 Proxy 實例時,核心代碼如下:
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
這裡的 this 參數對應的是 InvocationHandler 實例,而 JdkDynamicAopProxy 正好實現了該接口。因此,當代理對象的任何方法被調用時,都會回調到 invoke(Object proxy, Method method, Object[] args) 方法。這就是整個 AOP 攔截鏈啟動的起點。
該方法的主要職責包括:處理特殊方法(equals/hashCode)、管理 Proxy 上下文、獲取目標對象、構建攔截器鏈、決定是直接反射調用還是走攔截器鏈、處理返回值、最後釋放資源。以下是關鍵步驟解讀:
對於 equals()、hashCode() 以及 Advised 接口定義的方法,Spring 提供了直接處理邏輯,避免進入攔截器鏈,提升性能。
若 exposeProxy 為 true,則通過 AopContext.setCurrentProxy(proxy) 將當前代理綁定到線程局部變量,方便目標方法內部獲取代理引用(例如自我調用場景)。
TargetSource targetSource = this.advised.targetSource;
Object target = targetSource.getTarget(); // 可能來自對象池
Class targetClass = (target != null) ? target.getClass() : null;
// 核心:獲取針對當前方法的攔截器鏈
List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this.advised, proxy, method, targetClass);
這裡的 chain 包含了所有匹配當前方法的攔截器(包括動態方法匹配的 Advisor)。
AopUtils.invokeJoinpointUsingReflection(target, method, args)。ReflectiveMethodInvocation 並調用其 proceed() 方法,正式進入攔截器鏈執行流程。若目標方法返回 this 且返回類型兼容代理類型,則將返回值替換為代理對象,保證調用端拿到的是代理而非裸目標對象。最後在 finally 塊中釋放目標對象(若來自池)並恢復舊的 Proxy 上下文。
這是一個純反射調用封裝,核心邏輯:
setAccessible(true) 破壞封裝。InvocationTargetException 並拋出真實異常 ex.getTargetException(),保證異常棧不被攔截器污染。AopInvocationException。這是整個 AOP 執行流程的「心臟」。它維護一個 currentInterceptorIndex 指針,每次 proceed() 都會:
index == size),調用 invokeJoinpoint() 執行真實目標方法。InterceptorAndDynamicMethodMatcher,執行動態匹配,匹配成功則調用 dm.interceptor.invoke(nextInvocation()),失敗則 index++ 遞歸 proceed()。MethodInterceptor,直接調用 interceptor.invoke(nextInvocation())。private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {
ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();
invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;
invocation.parent = this;
return invocation;
}
每次進入下一個攔截器時,都會 克隆當前調用上下文 並遞增索引。這種不可變鏈式設計保證了:
invocation.proceed() 時,實際執行的是克隆對象的 proceed(),從而自然串聯起整條鏈。TransactionInterceptor 中多次 proceed())。在 TransactionInterceptor.invoke() 中可以看到典型模式:
try {
retVal = invocation.proceed(); // 執行後續攔截器 + 目標方法
} catch (Throwable ex) {
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
若事務管理器實現了 CallbackPreferringPlatformTransactionManager,則改用模板回調風格,但本質仍是通過 invocation.proceed() 驅動鏈條向前流動。
Spring AOP 的攔截器調用機制展示了經典的 責任鏈模式 + 命令模式 + 原型模式(Clone) 的組合應用:
JdkDynamicAopProxy.invoke() 是入口,負責上下文準備與分發決策。ReflectiveMethodInvocation 封裝了「調用上下文 + 鏈狀結構 + 索引指針」,是鏈條執行的核心載體。nextInvocation() 通過淺拷貝實現狀態遞進,巧妙解決了遞歸調用時的狀態隔離問題。MethodInvocation.proceed(),無感知鏈條其餘細節,實現了極佳的解耦。理解這套機制,不僅有助於排查 AOP 不生效、執行順序錯誤等疑難雜症,更能啟發我們在設計插件系統、中間件鏈路時的架構思維。