关于@Around、@Before、@After、@AfterReturning、@AfterThrowing执行顺序以及执行结果总结
spring4.x版本的执行结果顺序是:
@Around注解方法的前半部分业务逻辑
->@Before注解方法的业务逻辑
->目标方法的业务逻辑
->@Around注解方法的后半部分业务逻辑(@Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理,直接向上抛出异常,则不会执行Around注解方法的后半部分业务逻辑;若做了异常捕获处理,则会执行)。
->@After(不管目标方法有无异常,都会执行@After注解方法的业务逻辑)
->@AfterReturning(若目标方法无异常,执行@AfterReturning注解方法的业务逻辑)
->@AfterThrowing(若目标方法有异常,执行@AfterThrowing注解方法的业务逻辑)
我的spring源码版本是5.2.14,之前一直没搞明白五大通知的执行结果,特此记录。
前菜:切面类业务代码
要被增强的类及方法:
当执行MathCalculator.div方法时,会触发aop进而执行增强的业务,它的拦截器链数组如下,
[
ExposeInvocationInterceptor,
AspectJAroundAdvice,
MethodBeforeAdviceInterceptor,
AspectJAfterAdvice,
AfterReturningAdviceInterceptor,
AspectJAfterThrowingAdvice
]
按照这个链数组从角标0开始顺序执行invoke方法,invoke方法中递归执行ReflectiveMethodInvocation的proceed方法。
执行流程大致如下:
@Around前半部分(执行Around注解的方法内ProceedingJoinPoint.proceed()之前的代码逻辑并通过ProceedingJoinPoint.proceed()方法递归调用到Before拦截器)
->@Before
->@After(使用了try...finally结构,try代码块中继续递归调用AfterReturning,finally代码块中是执行after注解的方法逻辑)
->@AfterReturning
->@AfterThrowing
->目标方法执行(开始往回返数据,即return)
->@AfterThrowing(无异常return数据,有异常捕获异常执行AfterThrowing注解的方法逻辑并再次抛出异常)
->@AfterReturning(执行AfterReturning注解的方法逻辑并return目标方法执行结果)
->@After(执行After注解的方法逻辑并return目标方法执行结果)
->@Before(return目标方法执行结果)
->@Around后半部分(执行Around注解的方法内ProceedingJoinPoint.proceed()之后的代码逻辑并return目标方法执行结果)。
以上就是大致的执行流程。
总结:所以包含通知注解的执行结果如下,
@Around注解方法的前半部分业务逻辑
->@Before注解方法的业务逻辑
->目标方法的业务逻辑
->@AfterThrowing(若目标方法有异常,执行@AfterThrowing注解方法的业务逻辑)
->@AfterReturning(若目标方法无异常,执行@AfterReturning注解方法的业务逻辑)
->@After(不管目标方法有无异常,都会执行@After注解方法的业务逻辑)
->@Around注解方法的后半部分业务逻辑(@Around注解方法内的业务逻辑若对ProceedingJoinPoint.proceed()方法没做捕获异常处理,直接向上抛出异常,则不会执行Around注解方法的后半部分业务逻辑;若做了异常捕获处理,则会执行)。
正常执行结果如下:
抛异常结果如下:
如果我理解的内容有误,烦请评论区留言或者私聊,我好及时纠正,谢谢!
关于@Around、@Before、@After、@AfterReturning、@AfterThrowing执行顺序以及执行结果总结相关推荐
- java执行顺序_java执行顺序
本文讨论Java中(静态)变量.(静态)代码块的执行顺序 首先创建3个类: 1.Foo类,用于打印变量 public class Foo { public Foo(String word) { Sys ...
- Mysql 层级、执行顺序、执行计划分析
逻辑分层 下面是MySQL的逻辑分层图: 连接层:连接与线程处理,这一层并不是MySQL独有,一般的基于C/S架构的都有类似组件,比如连接处理.授权认证.安全等. 服务层:包括缓存查询.解析器.优化器 ...
- main线程 子线程 顺序_面试官:线程池如何按照core、max、queue的执行顺序去执行?详解...
前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...
- adguard没有核心 core no_面试官:线程池如何按照core、max、queue的执行顺序去执行?...
前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...
- 执行计划级别mysql 2ef,Mysql 层级、执行顺序、执行计划分析
逻辑分层 下面是MySQL的逻辑分层图: 连接层:连接与线程处理,这一层并不是MySQL独有,一般的基于C/S架构的都有类似组件,比如连接处理.授权认证.安全等. 服务层:包括缓存查询.解析器.优化器 ...
- 关于Java中try-catch-finally-return的执行顺序
1.try块中没有抛出异常,try.catch和finally块中都有return语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static int ...
- Java笔记——Java代码块的执行顺序
Java代码块的执行顺序 Java程序中代码块的执行顺序对于学习Java的人来说是必不可少需要掌握的. 代码块 在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为: 局 ...
- 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)
今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间的区别.所以花了点时间研究了下. 据msdn中介绍,它们最大的区别就是BeginInvoke属于异步执行的. Cont ...
- Unity脚本生命周期与执行顺序
目录 脚本生命周期 MonoBehavior生命周期图 脚本执行顺序 自定义执行顺序 @(文章目录) 在Unity中,脚本可以理解为附加在游戏对象上的用于定义游戏对象行为的指令代码.必须绑定在游戏对象 ...
最新文章
- 2013 年最不可思议的 10 个硬件开源项目
- java 泛型 get()_Java泛型,get类的泛型参数
- 前端每周清单半年盘点之 PWA 篇
- codeforces div3 D Circular Dance (链式向前星)
- Arduino--DS3231实时时钟模块
- 一个简单的数据库工具类
- RecyclerListView的使用
- iptables说明(转)
- php -l 检查文件是否语法错误
- RHEL6.3 NFS服务搭建过程详解
- php strictbool,PHP 7 Bool类型提示不起作用
- Python笔记:re模块详解
- Android 在导航栏上添加一个截屏按键,点击进行截屏
- 熟练的运用计算机英语怎么说,熟练的英文翻译,熟练英语怎么说
- linux docker启动指定字符集,【字符集】解决docker 容器中中文乱码问题
- Go语言基础教程:版本选择
- 李德毅:希望智能驾驶成为我国继高铁之后又一张新名片
- DMSP/OLS夜间灯光数据——应用
- 浏览器首页被2345、hao123锁定了,怎么办
- js中的includes用法