Spring Boot AOP(三) 通知执行链源码解析
博主社群介绍: ① 群内初中生、高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。 ② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。 ③ 群内也有职场精英,大厂大佬,跨国企业主管,可交流技术、面试、找工作的经验。 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬,进群赠送ZEEKLOG评论防封脚本,送真活跃粉丝,助你提升文章热度。 群公告里还有全网大赛约稿汇总/博客提效工具集/ZEEKLOG自动化运营脚本 有兴趣的加文末联系方式,备注自己的ZEEKLOG昵称,拉你进群,互相学习共同进步。 文章目录
Spring Boot AOP(三) 通知执行链源码解析
1. 执行链概述
在 Spring AOP 中,一个方法可能对应 多个切面(Aspect) 和 多个通知(Advice)。Spring 使用 Advisor 链 + MethodInterceptor 链 来统一管理这些通知,使方法执行时按顺序执行各类通知。
核心概念
| 概念 | 说明 |
|---|---|
| Advisor | 切面 + 切入点 + 通知的组合对象 |
| Advice | 切面中具体执行的操作,例如 @Before、@After、@Around |
| MethodInterceptor | AOP 的统一调用接口,所有 Advice 最终都转换为 MethodInterceptor |
| ReflectiveMethodInvocation | 方法调用封装类,负责顺序调用 Advisor 链 |
Spring AOP 的通知最终都会被封装为 MethodInterceptor,执行链由 ReflectiveMethodInvocation 管理。
2. Advisor 链与通知统一处理
在 Spring 中,多个切面可能作用于同一个方法。Spring 会将所有切面对应的通知 排序后加入 Advisor 链:
- 收集匹配的切面
- 将切面中的 Advice 转换为 MethodInterceptor
- 按 @Order 或实现 Ordered 接口排序
- 构建 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 执行逻辑说明
currentInterceptorIndex控制当前执行的通知- 如果到达链尾,则调用目标方法
- 否则,将当前通知强转为 MethodInterceptor 并调用
- 每个环绕通知内部可以调用
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 | 执行顺序 |
|---|---|---|
| 前置通知 @Before | MethodBeforeAdviceInterceptor | 最先执行 |
| 环绕通知 @Around | AroundAdviceInterceptor | 可环绕目标方法 |
| 返回通知 @AfterReturning | AfterReturningAdviceInterceptor | 目标方法成功返回后执行 |
| 异常通知 @AfterThrowing | AfterThrowingAdviceInterceptor | 目标方法异常时执行 |
| 后置通知 @After | AfterAdviceInterceptor | 最后执行,无论成功/异常 |
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 链顺序执行
- 多切面组合执行顺序由
@Order或Ordered接口控制 - Mermaid 图直观展示了 Advisor 链、方法调用链和环绕通知执行顺序
这一篇是 源码级、流程图丰富、示例全面 的第三篇,紧接第二篇的代理机制,完整衔接整个系列。
下一步可以写 第四篇:Spring Boot /error 与 BasicErrorController 源码解析 或你希望继续写 异常与 AOP 结合的执行顺序 这一主题,你希望我直接写哪一个?
结束语

👨💻 关于我
持续学习 | 追求真我
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
感谢订阅专栏 三连文章

掘金点击访问QiunerZEEKLOG点击访问QiunerGitHub点击访问QiunerGitee点击访问Qiuner
| 专栏 | 简介 |
|---|---|
| 📊 一图读懂系列 | 图文并茂,轻松理解复杂概念 |
| 📝 一文读懂系列 | 深入浅出,全面解析技术要点 |
| 🌟持续更新 | 保持学习,不断进步 |
| 🎯 人生经验 | 经验分享,共同成长 |
你好,我是Qiuner. 为帮助别人少走弯路而写博客
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注吧 我会尽力带来有趣的内容 😎。
代码都在Github或Gitee上,如有需要可以去上面自行下载。记得给我点星星哦😍
如果你遇到了问题,自己没法解决,可以去我掘金评论区问。ZEEKLOG评论区和私信消息看不完 掘金消息少一点.
| 上一篇推荐 | 链接 |
|---|---|
| Java程序员快又扎实的学习路线 | 点击该处自动跳转查看哦 |
| 一文读懂 AI | 点击该处自动跳转查看哦 |
| 一文读懂 服务器 | 点击该处自动跳转查看哦 |
| 2024年创作回顾 | 点击该处自动跳转查看哦 |
| 一文读懂 ESLint配置 | 点击该处自动跳转查看哦 |
| 老鸟如何追求快捷操作电脑 | 点击该处自动跳转查看哦 |
| 未来会写什么文章? | 预告链接 |
|---|---|
| 一文读懂 XX? | 点击该处自动跳转查看哦 |
| 2025年终总结 | 点击该处自动跳转查看哦 |
| 一图读懂 XX? | 点击该处自动跳转查看哦 |