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?点击该处自动跳转查看哦