Spring Boot AOP(三) 通知执行链源码解析

Spring Boot AOP(三) 通知执行链源码解析
博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。 ② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。 ③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送ZEEKLOG评论防封脚本,送真活跃粉丝,助你提升文章热度。 群公告里还有全网大赛约稿汇总/博客提效工具集/ZEEKLOG自动化运营脚本 有兴趣的加文末联系方式,备注自己的ZEEKLOG昵称,拉你进群,互相学习共同进步。 

文章目录


Spring Boot AOP(三) 通知执行链源码解析

1. 执行链概述

在 Spring AOP 中,一个方法可能对应 多个切面(Aspect)多个通知(Advice)。Spring 使用 Advisor 链 + MethodInterceptor 链 来统一管理这些通知,使方法执行时按顺序执行各类通知。

核心概念

概念说明
Advisor切面 + 切入点 + 通知的组合对象
Advice切面中具体执行的操作,例如 @Before、@After、@Around
MethodInterceptorAOP 的统一调用接口,所有 Advice 最终都转换为 MethodInterceptor
ReflectiveMethodInvocation方法调用封装类,负责顺序调用 Advisor 链
Spring AOP 的通知最终都会被封装为 MethodInterceptor,执行链由 ReflectiveMethodInvocation 管理。

2. Advisor 链与通知统一处理

在 Spring 中,多个切面可能作用于同一个方法。Spring 会将所有切面对应的通知 排序后加入 Advisor 链

  1. 收集匹配的切面
  2. 将切面中的 Advice 转换为 MethodInterceptor
  3. 按 @Order 或实现 Ordered 接口排序
  4. 构建 ReflectiveMethodInvocation 执行链

Mermaid 流程图:Advisor 链构建

扫描 Bean 切面

匹配切入点

收集匹配的通知

Advice 转换为 MethodInterceptor

按顺序构建 ReflectiveMethodInvocation 链


3. MethodInterceptor 执行流程

3.1 ReflectiveMethodInvocation 核心源码

核心方法:proceed()

publicObjectproceed()throwsThrowable{if(this.currentInterceptorIndex ==this.interceptorsAndDynamicMethodMatchers.size()-1){returnthis.method.invoke(this.target,this.arguments);}Object interceptorOrAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if(interceptorOrAdvice instanceofMethodInterceptor){return((MethodInterceptor) interceptorOrAdvice).invoke(this);}else{returnproceed();}}

3.2 执行逻辑说明

  1. currentInterceptorIndex 控制当前执行的通知
  2. 如果到达链尾,则调用目标方法
  3. 否则,将当前通知强转为 MethodInterceptor 并调用
  4. 每个环绕通知内部可以调用 proceed() 执行下一环节

Mermaid 流程图:MethodInterceptor 调用链

渲染错误: Mermaid 渲染失败: Parse error on line 3: ...>proceed] B --> C[@Before 前置通知] ----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'


4. 不同通知类型执行链示意

通知类型转换为 MethodInterceptor执行顺序
前置通知 @BeforeMethodBeforeAdviceInterceptor最先执行
环绕通知 @AroundAroundAdviceInterceptor可环绕目标方法
返回通知 @AfterReturningAfterReturningAdviceInterceptor目标方法成功返回后执行
异常通知 @AfterThrowingAfterThrowingAdviceInterceptor目标方法异常时执行
后置通知 @AfterAfterAdviceInterceptor最后执行,无论成功/异常

5. 环绕通知执行链深入解析

环绕通知最灵活,可以完全控制方法执行:

@Around("execution(* com.example.service..*.*(..))")publicObjectaroundAdvice(ProceedingJoinPoint pjp)throwsThrowable{System.out.println("环绕通知前逻辑");Object result = pjp.proceed();System.out.println("环绕通知后逻辑");return result;}

Mermaid 流程图:环绕通知链执行

方法调用

环绕通知1前逻辑

环绕通知2前逻辑

目标方法执行

环绕通知2后逻辑

环绕通知1后逻辑

返回调用方


6. 多 Advisor 链组合示例

@Aspect@Component@Order(1)publicclassLoggingAspect{@Before("execution(* com.example.service..*.*(..))")publicvoidbefore(JoinPoint jp){System.out.println("日志前置: "+ jp.getSignature());}}@Aspect@Component@Order(2)publicclassTransactionAspect{@Around("execution(* com.example.service..*.*(..))")publicObjectaround(ProceedingJoinPoint pjp)throwsThrowable{System.out.println("事务开始");Object result = pjp.proceed();System.out.println("事务提交");return result;}}@Aspect@Component@Order(3)publicclassMetricsAspect{@AfterReturning(pointcut ="execution(* com.example.service..*.*(..))", returning ="result")publicvoidafterReturning(JoinPoint jp,Object result){System.out.println("性能监控: "+ jp.getSignature()+", 返回: "+ result);}}

多切面执行顺序示意

方法调用

LoggingAspect @Before

TransactionAspect @Around 前

目标方法执行

TransactionAspect @Around 后

MetricsAspect @AfterReturning

返回调用方


7. ReflectiveMethodInvocation 执行链源码示意

proceed 方法调用

获取当前索引的 MethodInterceptor

索引是否到达链尾?

执行目标方法 method.invoke

执行当前拦截器

interceptor.invoke this

拦截器内部调用 proceed

返回结果

逐层返回到调用方


8. 本文总结

  • Spring AOP 统一将所有通知封装为 MethodInterceptor
  • ReflectiveMethodInvocation 负责 链式执行所有通知
  • 环绕通知可以完全控制目标方法执行,其他通知按 Advisor 链顺序执行
  • 多切面组合执行顺序由 @OrderOrdered 接口控制
  • Mermaid 图直观展示了 Advisor 链、方法调用链和环绕通知执行顺序

这一篇是 源码级、流程图丰富、示例全面 的第三篇,紧接第二篇的代理机制,完整衔接整个系列。

下一步可以写 第四篇:Spring Boot /error 与 BasicErrorController 源码解析 或你希望继续写 异常与 AOP 结合的执行顺序 这一主题,你希望我直接写哪一个?

结束语

👨‍💻 关于我

持续学习 | 追求真我

如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

感谢订阅专栏 三连文章

image-20251011155556997

掘金点击访问QiunerZEEKLOG点击访问QiunerGitHub点击访问QiunerGitee点击访问Qiuner

专栏简介
📊 一图读懂系列图文并茂,轻松理解复杂概念
📝 一文读懂系列深入浅出,全面解析技术要点
🌟持续更新保持学习,不断进步
🎯 人生经验经验分享,共同成长
你好,我是Qiuner. 为帮助别人少走弯路而写博客

如果本篇文章帮到了你 不妨点个吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。

代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍

如果你遇到了问题,自己没法解决,可以去我掘金评论区问。ZEEKLOG评论区和私信消息看不完 掘金消息少一点.
上一篇推荐链接
Java程序员快又扎实的学习路线点击该处自动跳转查看哦
一文读懂 AI点击该处自动跳转查看哦
一文读懂 服务器点击该处自动跳转查看哦
2024年创作回顾点击该处自动跳转查看哦
一文读懂 ESLint配置点击该处自动跳转查看哦
老鸟如何追求快捷操作电脑点击该处自动跳转查看哦
未来会写什么文章?预告链接
一文读懂 XX?点击该处自动跳转查看哦
2025年终总结点击该处自动跳转查看哦
一图读懂 XX?点击该处自动跳转查看哦

Read more

Java 大视界 -- Java+Spark MLlib 构建智能推荐系统:协同过滤算法实战与优化(441)

Java 大视界 -- Java+Spark MLlib 构建智能推荐系统:协同过滤算法实战与优化(441)

Java 大视界 -- Java+Spark MLlib 构建智能推荐系统:协同过滤算法实战与优化(441) * 引言: * 正文: * 一、 推荐系统整体架构设计:从业务场景出发,搭建高可用架构 * 1.1 架构设计核心原则:贴合业务,兼顾性能与可扩展性 * 1.2 全链路架构图:纵向布局,清晰呈现核心模块 * 1.3 核心模块职责:分工明确,形成闭环 * 1.3.1 数据采集层 * 1.3.2 数据处理层 * 1.3.3 模型层 * 1.3.4 推荐生成层 * 1.3.5 存储层

By Ne0inhk
【Linux系统编程】(四十)线程控制终极指南:从资源共享到实战操控,带你吃透线程全生命周期

【Linux系统编程】(四十)线程控制终极指南:从资源共享到实战操控,带你吃透线程全生命周期

前言         在 Linux 多线程开发中,“线程控制” 是贯穿始终的核心技能 —— 从线程的创建、终止,到等待、分离,每一步操作都直接影响程序的性能、稳定性和资源利用率。而要熟练掌握线程控制,首先必须理清一个关键问题:进程和线程究竟哪些资源共享、哪些资源独占?这是理解线程控制逻辑的底层基石。         很多开发者在编写多线程程序时,常会陷入这样的困境:明明调用了pthread_create却创建失败,线程退出后出现资源泄漏,用pthread_join等待线程却始终阻塞,甚至因误操作导致整个进程崩溃。这些问题的根源,往往是对线程与进程的资源关系理解不深,或是对 POSIX 线程库的控制接口使用不当。         本文将从 “进程与线程的资源划分” 入手,层层递进讲解 Linux 线程的完整控制流程 —— 包括 POSIX 线程库的使用、线程创建、终止、等待、分离等核心操作,全程结合实战代码和底层原理,用通俗的语言拆解复杂概念,让你不仅 “会用” 线程控制接口,更能 “懂原理”

By Ne0inhk
内网安全部署:Java + OpenClaw 本地大模型私有化方案

内网安全部署:Java + OpenClaw 本地大模型私有化方案

文章目录 * 前言 * 一、开篇:你的数据正在裸奔吗? * 二、技术栈选型:为什么选这三兄弟? * 2.1 本地大模型:Ollama是傻瓜相机 * 2.2 OpenClaw:AI界的机械臂 * 2.3 Java:老当益壮的底盘 * 三、架构设计:三层铁桶怎么搭? * 3.1 数据流向图(脑补版) * 3.2 安全边界划分 * 四、环境搭建:从0到1手摸手 * 4.1 本地模型部署(Ollama) * 4.2 OpenClaw安装与配置 * 4.3 Java项目准备 * 五、Java集成实战:代码说话 * 5.1 基础对话接口 * 5.

By Ne0inhk
Java 手写 AI Agent:ZenoAgent 实战笔记

Java 手写 AI Agent:ZenoAgent 实战笔记

摘要:作为一个长期使用 Java 的后端开发者,我对 AI Agent 的内部运作机制充满了好奇。为了深入理解 Agent 的工作原理,我决定动手写一个简单的 Agent 系统 —— ZenoAgent。本文记录了我在这个过程中的学习心得与技术实践,包括如何手写 ReAct 循环、在分布式环境下实现 Human-in-the-loop、尝试复刻类 o1 的流式思考以及探索错误处理机制。希望这些踩坑经验能给同样想探索 AI 的 Java 开发者一些参考。 👀 在线体验:项目已部署上线,欢迎试玩:线上部署地址 (注:受限于服务器资源,线上本地部署了 Qwen3:8B 模型(参见另一篇博文华为云服务器本地部署大模型实战),虽不如商业模型聪明,但足以演示 Agent 的核心能力) 💡 写在前面:我的学习初衷 市面上已经有了像 LangChain 和 AutoGen

By Ne0inhk