Spring AOP `MethodInvocation` 工作原理

?? 一、通知到 MethodInterceptor 的轉換機制

Spring AOP 通過適配器模式將開發者定義的注解型通知(如 @Before)統一轉換為 MethodInterceptor 接口實現,確保所有通知類型能接入同一調用鏈。以下是轉換細節:

1. 適配器實現原理

  • 核心接口:MethodInterceptor是所有通知的最終形態,其invoke(MethodInvocation mi)方法封裝了通知邏輯與鏈式調用邏輯。
  • 適配器作用:將不同通知類型(如AspectJMethodBeforeAdvice)包裝為MethodInterceptor子類,實現邏輯轉換。

2. 各通知類型的轉換細節

下表總結了五種通知的轉換邏輯與執行順序:

通知類型原始接口轉換后實現invoke() 核心邏輯
@BeforeAspectJMethodBeforeAdviceMethodBeforeAdviceInterceptor1. 執行 advice.before()
2. 調用 mi.proceed() 觸發后續鏈
@AfterAspectJAfterAdviceAfterAdviceInterceptor1. try { mi.proceed() }
2. finally { advice.after() }(確保最終執行)
@AfterReturningAspectJAfterReturningAdviceAfterReturningAdviceInterceptor1. 調用 mi.proceed()
2. 若正常返回,執行 advice.afterReturning()
@AfterThrowingAspectJAfterThrowingAdviceThrowsAdviceInterceptor1. try { mi.proceed() }
2. catch(ex) { advice.afterThrowing(ex) }
@AroundAspectJAroundAdvice1. 自定義前后邏輯
2. 通過 mi.proceed() 觸發后續鏈(需主動調用)

關鍵設計:除 @Around 外,所有通知均被轉換為環繞通知形式,通過統一的 invoke() 接口接入調用鏈。


🔄 二、MethodInvocation 與攔截器鏈的協同流程

1. 調用鏈構建過程

  1. 代理對象創建:Spring 容器啟動時,掃描所有Advisor(包含通知與切點)。
  2. 適配器轉換:通過AdvisorAdapterRegistryAdvisor中的通知轉換為MethodInterceptor
  3. 鏈式存儲:生成List<MethodInterceptor>并注入ReflectiveMethodInvocation

2. 調用鏈執行邏輯(ReflectiveMethodInvocation.proceed()

public class ReflectiveMethodInvocation implements MethodInvocation {private final List<MethodInterceptor> interceptors;private int currentInterceptorIndex = -1;  // 當前執行位置索引public Object proceed() throws Throwable {// 1. 所有攔截器執行完畢 → 反射調用目標方法if (this.currentInterceptorIndex == interceptors.size() - 1) {return invokeJoinpoint(); }// 2. 獲取下一個攔截器并推進索引MethodInterceptor interceptor = interceptors.get(++currentInterceptorIndex);// 3. 執行當前攔截器(觸發統一的invoke接口)return interceptor.invoke(this);  // 將自身(MethodInvocation)傳入}
}

索引機制currentInterceptorIndex 記錄當前執行位置,每次 proceed() 調用時遞增,實現攔截器的順序觸發。

3. 各通知在調用鏈中的協作順序

以下序列圖展示了典型調用流程(含多個通知類型):

ReflectiveMethodInvocationBefore攔截器Around攔截器After攔截器目標方法interceptor.invoke(this)1執行@Before邏輯2調用proceed()3interceptor.invoke(this)4環繞前邏輯5調用proceed()6interceptor.invoke(this)7調用proceed()8反射調用目標方法9返回結果10執行@After邏輯11返回12環繞后邏輯13返回14返回最終結果15ReflectiveMethodInvocationBefore攔截器Around攔截器After攔截器目標方法

協作關鍵

  • 嵌套執行:每個攔截器通過調用mi.proceed()觸發后續攔截器或目標方法,形成嵌套調用棧。
  • 邏輯控制權:攔截器可決定是否調用proceed()。例如權限校驗失敗時,Before攔截器可不調用proceed(),直接中斷鏈。

🧩 三、統一 MethodInterceptor 的設計價值

1. 外部易用性

開發者通過直觀注解(如 @Before)聲明切面,無需理解底層調用鏈。適配器模式隱藏了復雜性,例如:

@Before("execution(* com.dwl.*.*(..))")
public void logBefore(JoinPoint jp) {System.out.println("Before: " + jp.getSignature());
}

2. 內部統一性

  • 單一執行邏輯:ReflectiveMethodInvocation.proceed()只需遍歷List<MethodInterceptor>,無需區分通知類型。
  • 擴展性:新增通知類型時,只需實現適配器并注冊到AdvisorAdapterRegistry,無需修改調用鏈核心邏輯。

3. 異常處理優勢

  • 統一異常傳播:異常沿調用鏈反向傳遞,由最近的@AfterThrowing@Around攔截器捕獲。
  • 資源清理保證:@After邏輯在finally塊執行,確保即使目標方法異常也能運行(如關閉數據庫連接)。

? 四、完整流程案例:日志切面執行

假設切面包含 @Before@Around@After 通知,調用鏈構建與執行如下:

  1. 轉換階段

    • @BeforeMethodBeforeAdviceInterceptor
    • @AroundAspectJAroundAdvice
    • @AfterAfterAdviceInterceptor
  2. 調用鏈執行順序

    調用proceed
    調用proceed
    調用proceed
    返回
    執行finally邏輯
    執行環繞后邏輯
    Before攔截器
    Around攔截器
    After攔截器
    目標方法
  3. 異常場景:若目標方法拋出異常:

    • After 攔截器在 finally 中執行日志清理。
    • 異常傳遞給Around攔截器,由其捕獲并記錄。

💎 總結

  1. 轉換必然性:適配器模式是 Spring AOP 的基石,將注解通知統一轉為MethodInterceptor,實現調用鏈標準化。
  2. 協同核心:ReflectiveMethodInvocation通過索引控制與嵌套調用(proceed())協調攔截器執行,形成責任鏈模式。
  3. 設計價值:
    • 對外:簡化開發,通過注解屏蔽底層復雜度。
    • 對內:通過統一接口減少冗余代碼,提升擴展性。
    • 健壯性:異常處理與資源清理機制保障業務邏輯安全。

此設計完美體現了 “開閉原則”:新增通知類型無需修改調用鏈核心,僅需擴展適配器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92888.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PPO原論文閱讀

一、Introduction1.目前存在的問題&#xff1a;(deep)Q-learning:在一些簡單問題上表現不佳&#xff0c;可理解性差基礎的policy gradient算法&#xff1a;&#xff08;如REINFORCE&#xff09;魯棒性差&#xff0c;需要大量數據TRPO&#xff1a;復雜&#xff0c;在包含噪音&am…

零基礎也能創作專屬歌曲:文心一言+蘑兔AI協同教程

在AI技術飛速發展的今天&#xff0c;音樂創作已不再是專業音樂人的專屬領域。通過文心一言與蘑兔AI的協同使用&#xff0c;即使沒有音樂基礎&#xff0c;也能輕松完成從歌詞創作到作曲編曲的全流程。本文將詳細拆解操作步驟&#xff0c;助你快速上手&#xff0c;實現音樂創作夢…

圖論:搜索問題

提到圖論中的搜索問題&#xff0c;首先想到的也就是DFS和BFS了&#xff0c;而提到這兩種搜索&#xff0c;那么最典型的題目就是島嶼問題了&#xff0c;下面就練習幾道相關的題目&#xff0c;為之后的更深奧的圖論學習打下基礎&#xff01; 孤島的總面積 題目鏈接&#xff1a;…

AI驅動攻防升級,API安全走到關鍵檔口

在數字化轉型與AI技術快速發展的雙重驅動下&#xff0c;API已成為企業業務與外部世界連接的神經中樞。然而&#xff0c;隨著API的深度應用&#xff0c;針對API的攻擊規模與復雜性也在持續升級。 API為何頻頻成為黑客重點盯防的突破口&#xff1f;企業常見的API防護手段是否還能…

網絡基礎DAY18-動態路由協議基礎

動態路由協議基礎知識回顧&#xff1a;1.什么是路由&#xff1f; 答&#xff1a;是三層設備轉發IP報文的路徑信息。 2.路由有哪些來源&#xff1f; 答&#xff1a;1.直連路由2.靜態路由3.動態路由 3.有直連路由的條件&#xff1f; 答&#xff1a;1.二層和三層物理接口狀態為UP …

axios統一封裝規范管理

新建/api/ 1.新建統一處理文件/api/axios.ts import axios from "axios"const http axios.create({baseURL: import.meta.env.VITE_API_BASE_URL, // 從環境變量讀取timeout: 10000, });// 請求攔截器&#xff08;如添加 Token&#xff09; http.interceptors.reque…

Java學習第七十四部分——Elasticsearch(ES)

目錄 一、前言提要 二、核心特性 三、應用場景 四、主要優勢 五、集成方式 六、基礎操作 七、高級特性 八、概念類比——與關系型數據庫 九、簡單示例——實現存儲與搜索 十、生態集成——基于Spring Data Elasticsearch 十一、性能優化建議 十二、總結歸納概述 一…

TDengine 轉化函數 TO_UNIXTIMESTAMP 用戶手冊

TDengine TO_UNIXTIMESTAMP 函數用戶使用手冊 函數概述 TO_UNIXTIMESTAMP 是 TDengine 中的標量函數&#xff0c;用于將符合 ISO8601/RFC3339 標準的日期時間字符串轉換為 Unix 時間戳。與 TO_TIMESTAMP 不同&#xff0c;該函數專門處理標準格式的時間字符串&#xff0c;無需指…

Java 中的排序算法詳解

目錄 一、冒泡排序&#xff08;Bubble Sort&#xff09; 原理? 二、選擇排序&#xff08;Selection Sort&#xff09; 原理? 三、插入排序&#xff08;Insertion Sort&#xff09; 原理? 四、快速排序&#xff08;Quick Sort&#xff09; 原理? 五、歸并排序&…

Gitee如何成為國內企業DevOps轉型的首選平臺?

Gitee如何成為國內企業DevOps轉型的首選平臺&#xff1f; 在數字化轉型浪潮中&#xff0c;DevOps已成為提升企業研發效能的關鍵引擎。作為國內領先的代碼托管與協作平臺&#xff0c;Gitee憑借本土化優勢與全流程支持能力&#xff0c;正成為越來越多企業DevOps實踐的核心載體。本…

?Excel——SUMPRODUCT 函數

SUMPRODUCT 是 Excel 中最強大的函數之一&#xff0c;可以用于 ?多條件求和、加權計算、數組運算? 等復雜場景。下面通過 ?基礎語法 實用案例? 徹底講透它的用法&#xff01;?一、基礎語法?SUMPRODUCT(數組1, [數組2], [數組3], ...)?功能?&#xff1a;將多個數組的對…

告別虛函數性能焦慮:深入剖析C++多態的現代設計模式

?? 引言:當多態遇上性能瓶頸 我經常被問到這樣一個問題:“既然virtual函數這么方便,為什么在一些高性能場景下,大家卻避之不及?” 答案很簡單:性能。 在我參與的多個HPC項目和游戲引擎開發中,virtual函數調用往往成為性能分析工具中最顯眼的那個紅點。一個看似無害…

k8s-MongoDB 副本集部署

前提準備一套 k8s 集群worker 節點上的 /nfs/data 目錄掛載到磁盤一、NFS 高可用方案&#xff08;NFSkeepalivedSersync&#xff09;本方案 NFS 的高可用方案&#xff0c;應用服務器為 Client &#xff0c;兩臺文件服務器分別 Master 和 Slave&#xff0c;使用 keepalived 生成…

BI 系統數據看板全解析:讓數據可視化驅動業務決策

BI 系統數據看板全解析&#xff1a;讓數據可視化驅動業務決策在 BI 系統中&#xff0c;數據看板是連接原始數據與業務洞察的 “橋梁”。它將零散的業務指標轉化為直觀的可視化圖表&#xff0c;讓產品經理、運營人員等角色能快速把握業務動態。一個設計精良的數據看板&#xff0…

圖機器學習(14)——社交網絡分析

圖機器學習&#xff08;14&#xff09;——社交網絡分析0. 前言1. 數據集分析1.1 數據集介紹1.2 使用 networkx 加載數據集2. 網絡拓撲和社區檢測2.1 網絡拓撲2.2 社區檢測0. 前言 社交網站的崛起是近年來數字媒體領域最活躍的發展趨勢之一&#xff0c;數字社交互動已經融入人…

深入解析Hadoop MapReduce中Reduce階段排序的必要性

MapReduce概述與Reduce階段簡介MapReduce作為Hadoop生態系統的核心計算框架&#xff0c;其設計思想源自Google論文&#xff0c;通過"分而治之"的理念實現海量數據的并行處理。該模型將計算過程抽象為兩個關鍵階段&#xff1a;Map階段負責數據分解和初步處理&#xff…

7月23日華為機考真題第二題-200分

?? 點擊直達筆試專欄 ??《大廠筆試突圍》 ?? 春秋招筆試突圍在線OJ ?? 筆試突圍OJ bishipass.com 02. 圖書館資源分配系統 問題描述 A先生是一位圖書館管理員,負責管理圖書采購和分配工作。圖書館收到了來自不同出版社的圖書批次,同時有多位讀者代表排隊申請圖書…

基于深度學習的圖像分類:使用ResNet實現高效分類

最近研學過程中發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊鏈接跳轉到網站人工智能及編程語言學習教程。讀者們可以通過里面的文章詳細了解一下人工智能及其編程等教程和學習方法。下面開始對正文內容的…

JVM:工具

JVMjpsjstatjmapjhatjstackjconsolejvisualvmjps jps&#xff08; Java Virtual Machine Process Status Tool &#xff09;&#xff0c;是 JDK 中的一個命令行工具&#xff0c;用于列出當前正在運行的 JVM 實例的信息。其對于監控和管理運行在多個 JVM 上的 Java 應用程序特別…

Elasticsearch Circuit Breaker 全面解析與最佳實踐

一、Circuit Breaker 簡介 Elasticsearch 是基于 JVM 的搜索引擎&#xff0c;其內存管理十分重要。為了避免單個操作或查詢耗費過多內存導致節點不可用&#xff0c;Elasticsearch 引入了 Circuit Breaker&#xff08;熔斷器&#xff09;機制。當內存使用達到熔斷器預設閾值時&a…