前言
??本文首先介紹了責任鏈的基本原理,并附帶一個例子說明責任鏈模式,確保能夠理解責任鏈的前提下,在進行Spring AOP執行責任鏈的源碼分析。責任鏈模式允許將多個處理對象連接成鏈,請求沿著鏈傳遞,直到被處理或結束。每個處理者可以選擇處理請求或傳遞給下一個。
??Spring AOP的攔截器鏈,攔截器或者過濾器鏈,都是典型的責任鏈應用。比如,當一個方法被調用時,多個攔截器按順序執行,每個攔截器可以決定是否繼續執行鏈中的下一個。
??深入Spring AOP的源碼部分,特別是攔截器鏈的執行過程。比如,在Spring AOP中,當調用一個被增強的方法時,會創建一個MethodInvocation對象,其中包含攔截器鏈。每個攔截器都是一個Advice,比如MethodInterceptor。這時候,責任鏈模式的應用可能體現在攔截器的依次調用上,每個攔截器處理完后調用下一個,直到最后一個攔截器執行實際的方法。
??具體分析Spring的源碼,比如ReflectiveMethodInvocation類的proceed方法。這個方法可能負責按順序調用攔截器鏈中的每個攔截器,直到所有攔截器處理完畢,最后調用目標方法。這個流程是否符合責任鏈模式的結構?是的,每個攔截器處理請求,并決定是否傳遞下去。
??可能還需要比較責任鏈模式的不同變體,比如純的責任鏈(每個處理者必須處理請求)和不純的(可以傳遞)。Spring AOP的攔截器鏈屬于后者,每個攔截器都可以選擇是否繼續傳遞,或者在處理前后執行某些操作,然后繼續傳遞。
??另外,Spring AOP的基本原理不在本文中介紹了,詳情請看以往文章,有更加詳細的表述,有理論和源碼的解析。文章:Spring AOP源碼解析
??實際應用場景本文也涉及到,如何自定義攔截器,如何調整攔截器鏈的順序,或者如何利用責任鏈模式實現類似的功能。這些實際應用案例可以增強回答的實用性。
??最后,確保回答結構清晰,先解釋責任鏈模式,再結合Spring源碼詳細說明,最后總結其優勢和應用場景。需要避免過于冗長的代碼分析,而是突出重點部分,比如關鍵類和方法的調用流程。
責任鏈模式原理詳解與源碼實例
一、責任鏈模式(Chain of Responsibility Pattern)原理
核心思想:將多個處理對象連成一條鏈,請求沿鏈傳遞,直到有一個處理對象處理它或鏈結束。每個處理對象可選擇處理請求或傳遞給下一個對象。
1. 模式結構
角色 | 職責 |
---|---|
Handler(抽象處理者) | 定義處理請求的接口,通常包含指向下一個處理者的引用(nextHandler )。 |
ConcreteHandler | 具體處理者,實現處理邏輯,或決定是否將請求傳遞到下一個處理者。 |
Request | 請求對象,封裝請求的上下文數據。 |
2. 類圖
+----------------+ +-------------------+
| Handler | <|-------| ConcreteHandlerA |
+----------------+ +-------------------+
| +nextHandler | | +handleRequest() |
| +handleRequest()| +-------------------+
+----------------+ ^| || |
+-------------------+
| ConcreteHandlerB |
+-------------------+
| +handleRequest() |
+-------------------+
3. 執行流程
- 客戶端將請求發送到責任鏈的第一個處理者。
- 每個處理者決定是否處理該請求:
- 若處理,則終止傳遞。
- 若不處理,則調用
nextHandler.handleRequest()
。
- 請求沿鏈傳遞,直到被處理或鏈結束。
二、責任鏈模式源碼實例
1. 抽象處理者(Handler)
public abstract class Handler {protected Handler nextHandler; // 指向下一個處理者public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(Request request);
}
2. 具體處理者(ConcreteHandler)
public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(Request request) {if (canHandle(request)) {System.out.println("ConcreteHandlerA 處理請求: " + request.getData());} else if (nextHandler != null) {nextHandler.handleRequest(request); // 傳遞給下一個處理者}}private boolean canHandle(Request request) {return request.getType().equals("A");}
}public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(Request request) {if (canHandle(request)) {System.out.println("ConcreteHandlerB 處理請求: " + request.getData());} else if (nextHandler != null) {nextHandler.handleRequest(request); // 傳遞給下一個處理者}}private boolean canHandle(Request request) {return request.getType().equals("B");}
}
3. 請求對象(Request)
public class Request {private String type; // 請求類型private String data; // 請求數據public Request(String type, String data) {this.type = type;this.data = data;}public String getType() { return type; }public String getData() { return data; }
}
4. 客戶端調用
public class Client {public static void main(String[] args) {// 創建責任鏈Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);// 發送請求Request request1 = new Request("A", "請求1");Request request2 = new Request("B", "請求2");handlerA.handleRequest(request1); // 由 ConcreteHandlerA 處理handlerA.handleRequest(request2); // 由 ConcreteHandlerB 處理}
}
輸出結果:
ConcreteHandlerA 處理請求: 請求1
ConcreteHandlerB 處理請求: 請求2
三、Spring AOP 攔截器鏈中的責任鏈模式
Spring AOP 通過 攔截器鏈(Interceptor Chain) 實現方法增強(如事務、日志),其核心設計正是基于責任鏈模式。
1. 核心組件
組件 | 職責 |
---|---|
MethodInvocation | 封裝被代理方法的調用上下文(類似 Request )。 |
MethodInterceptor | 攔截器接口(類似 Handler ),定義增強邏輯。 |
ReflectiveMethodInvocation | 具體責任鏈實現,管理攔截器鏈的調用順序。 |
2. 源碼解析
(1)攔截器鏈的創建
在生成代理對象時,Spring 會將所有匹配的攔截器(如 MethodInterceptor
)按順序組合成鏈。
入口:AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {// 獲取所有攔截器(包括事務、日志等)List<Object> interceptorList = new ArrayList<>();for (Advisor advisor : this.advisors) {if (advisor instanceof PointcutAdvisor) {// 匹配攔截器是否適用于當前方法if (((PointcutAdvisor) advisor).getPointcut().getMethodMatcher().matches(method, targetClass)) {interceptorList.add(advisor.getAdvice());}}}return interceptorList;
}
(2)責任鏈的觸發
代理對象調用方法時,觸發 ReflectiveMethodInvocation#proceed()
,按順序執行攔截器鏈。該方法類似于遞歸執行,遞歸方法也是有終止條件的,請注意區分。
源碼:ReflectiveMethodInvocation
public class ReflectiveMethodInvocation implements ProxyMethodInvocation {private final Object target; // 目標對象private final Method method; // 目標方法private final Object[] arguments; // 方法參數private final List<Object> interceptorsAndDynamicMethodMatchers; // 攔截器鏈private int currentInterceptorIndex = -1; // 當前攔截器索引public Object proceed() throws Throwable {// 1. 所有攔截器執行完畢,調用原始方法if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// 2. 獲取下一個攔截器Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);// 3. 執行攔截器邏輯if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice;return mi.invoke(this); // 將當前 MethodInvocation 傳遞給攔截器} else {// 動態匹配器處理(略)}}// 調用原始方法protected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);}
}
(3)攔截器的執行邏輯
每個 MethodInterceptor
攔截器決定是否繼續傳遞鏈(調用 proceed()
)或終止。
示例:Spring 事務攔截器 TransactionInterceptor
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor {public Object invoke(MethodInvocation invocation) throws Throwable {// 1. 開啟事務TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);try {// 2. 繼續執行攔截器鏈(責任鏈傳遞)Object retVal = invocation.proceed();// 3. 提交事務commitTransactionAfterReturning(txInfo);return retVal;} catch (Throwable ex) {// 4. 回滾事務completeTransactionAfterThrowing(txInfo, ex);throw ex;}}
}
四、責任鏈模式在 Spring AOP 中的設計優勢
-
靈活擴展
新增攔截器只需實現MethodInterceptor
并注冊到鏈中,無需修改現有代碼。 -
邏輯解耦
每個攔截器專注單一職責(如事務、日志),通過鏈式調用組合功能。 -
動態控制流程
攔截器可決定是否繼續調用鏈(如權限校驗失敗時直接拋出異常終止流程)。 -
執行順序可控
攔截器鏈的順序可通過@Order
注解或實現Ordered
接口調整。
五、實際應用場景與自定義攔截器
1. 自定義攔截器示例
public class LoggingInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("方法調用前: " + invocation.getMethod().getName());Object result = invocation.proceed(); // 繼續鏈System.out.println("方法調用后: " + invocation.getMethod().getName());return result;}
}
2. 配置攔截器鏈
在 Spring 配置中注冊攔截器:
<bean id="loggingInterceptor" class="com.example.LoggingInterceptor"/>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"/><aop:config><aop:advisor advice-ref="loggingInterceptor" order="1"/><aop:advisor advice-ref="transactionInterceptor" order="2"/>
</aop:config>
3. 執行順序
攔截器按 order
值從小到大依次執行:
LoggingInterceptor(前置日志) → TransactionInterceptor(事務管理) → 目標方法
六、總結
- 責任鏈模式核心:解耦請求發送者與處理者,允許多個對象按鏈式處理請求。
- Spring AOP 實現:通過
ReflectiveMethodInvocation
管理攔截器鏈,每個MethodInterceptor
按責任鏈模式依次執行。 - 優勢:靈活擴展、職責分離、動態流程控制。
- 應用場景:事務管理、日志記錄、權限校驗、性能監控等切面功能。