iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >Spring AOP的执行顺序是怎样的
  • 902
分享到

Spring AOP的执行顺序是怎样的

2024-04-02 19:04:59 902人浏览 八月长安
摘要

本篇内容介绍了“spring aop的执行顺序是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!问题描

本篇内容介绍了“spring aop的执行顺序是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

问题描述

公司新项目需要搭建一个新的前后分离Http服务,我选择了目前比较熟悉的SpringBoot WEB来快速搭建一个可用的系统。

鲁迅说过,不要随便升级已经稳定使用的版本。我偏不信这个邪,仗着自己用了这么久Spring,怎么能不冲呢。不说了,直接引入了最新的SprinBoot  2.3.4.RELEASE版本,开始给项目搭架子。

起初,大多数的组件引入都一切顺利,本以为就要大功告成了,没想到在搭建日志切面时栽了跟头。

作为一个接口服务,为了方便查询接口调用情况和定位问题,一般都会将请求日志打印出来,而Spring的AOP作为切面支持,完美的切合了日志记录的需求。

之前的项目中,运行正确的切面日志记录效果如下图:

Spring AOP的执行顺序是怎样的

可以看到图内的一次方法调用,会输出请求url,出入参,以及请求IP等等,之前为了好看,还加入了分割线。

我把这个实现类放入新项目中,执行出来却是这样的:

Spring AOP的执行顺序是怎样的

我揉了揉眼睛,仔细看了看复制过来的老代码,精简版如下:

 @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable {     // 开始打印请求日志     ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();     httpservletRequest request = attributes.getRequest();      // 初始化traceId     initTraceId(request);      // 打印请求相关参数     LOGGER.info("========================================== Start ==========================================");     // 打印请求 url     LOGGER.info("URL            : {}", request.getRequestURL().toString());     // 打印 Http method     LOGGER.info("HTTP Method    : {}", request.getMethod());     // 打印调用 controller 的全路径以及执行方法     LOGGER.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());     // 打印请求的 IP     LOGGER.info("IP             : {}", IPAddressUtil.getIpAdrress(request));     // 打印请求入参     LOGGER.info("Request Args   : {}", joinPoint.getArgs()); }   @After("webLog()") public void doAfter() throws Throwable {     LOGGER.info("=========================================== End ==========================================="); }   @Around("webLog()") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {     long startTime = System.currentTimeMillis();     Object result = proceedingJoinPoint.proceed();     // 打印出参     LOGGER.info("Response Args  : {}", result);     // 执行耗时     LOGGER.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);     return result; }

代码感觉完全没有问题,难道新版本的SpringBoot出Bug了。

显然,成熟的框架不会在这种大方向上犯错误,那会不会是新版本的SpringBoot把@After和@Around的顺序反过来了?

其实事情也没有那么简单。

Spring AOP执行顺序

我们先来回顾下Spring AOP执行顺序。

我们在网上查找关于SpringAop执行顺序的的资料,大多数时候,你会查到如下的答案:

正常情况

Spring AOP的执行顺序是怎样的

异常情况

Spring AOP的执行顺序是怎样的

多个切面的情况

Spring AOP的执行顺序是怎样的

所以@Around理应在@After之前,但是在SprinBoot  2.3.4.RELEASE版本中,@Around切切实实执行在了@After之后。

当我尝试切换回2.2.5.RELEASE版本后,执行顺序又回到了@Around-->@After

探究顺序错误的真相

既然知道了是SpringBoot版本升级导致的问题(或者说顺序变化),那么就要来看看究竟是哪个库对AOP执行的顺序进行了变动,毕竟,SpringBoot只是“形”,真正的内核在Spring。

我们打开pom.xml文件,使用插件查看spring-aop的版本,发现SpringBoot 2.3.4.RELEASE  版本使用的AOP是spring-aop-5.2.9.RELEASE。

而2.2.5.RELEASE对应的是spring-aop-5.2.4.RELEASE

于是我去官网搜索文档,不得不说Spring由于过于庞大,官网的文档已经到了冗杂的地步,不过最终还是找到了:

https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-framework-reference/core.html#aop-ataspectj-advice-ordering

Spring AOP的执行顺序是怎样的

As of Spring Framework 5.2.7, advice methods defined in the same @Aspect  class that need to run at the same join point are assigned precedence based on  their advice type in the following order, from highest to lowest precedence:  @Around, @Before, @After, @AfterReturning, @AfterThrowing.

我粗浅的翻译一下重点:

从Spring5.2.7开始,在相同@Aspect类中,通知方法将根据其类型按照从高到低的优先级进行执行:@Around,@Before  ,@After,@AfterReturning,@AfterThrowing。

这样看其实对比不明显,我们再回到老版本,也就是2.2.5.RELEASE对应的spring-aop-5.2.4.RELEASE,当时的文档是这么写的:

What happens when multiple pieces of advice all want to run at the same join  point? Spring AOP follows the same precedence rules as AspectJ to determine the  order of advice execution. The highest precedence advice runs first "on the way  in" (so, given two pieces of before advice, the one with highest precedence runs  first). "On the way out" from a join point, the highest precedence advice runs  last (so, given two pieces of after advice, the one with the highest precedence  will run second).

简单翻译:在相同@Aspect类中Spring AOP遵循与AspectJ相同的优先级规则来确定advice执行的顺序。

再挖深一点,那么AspectJ的优先级规则是什么样的?

我找了AspectJ的文档:

https://www.eclipse.org/aspectj/doc/next/progguide/semantics-advice.html

Spring AOP的执行顺序是怎样的

At a particular join point, advice is ordered by precedence.

A piece of around advice controls whether advice of lower precedence will run  by calling proceed. The call to proceed will run the advice with next  precedence, or the computation under the join point if there is no further  advice.

A piece of before advice can prevent advice of lower precedence from running  by throwing an exception. If it returns nORMally, however, then the advice of  the next precedence, or the computation under the join pint if there is no  further advice, will run.

Running after returning advice will run the advice of next precedence, or the  computation under the join point if there is no further advice. Then, if that  computation returned normally, the body of the advice will run.

Running after throwing advice will run the advice of next precedence, or the  computation under the join point if there is no further advice. Then, if that  computation threw an exception of an appropriate type, the body of the advice  will run.

Running after advice will run the advice of next precedence, or the  computation under the join point if there is no further advice. Then the body of  the advice will run.

大伙又要说了,哎呀太长不看!简短地说,Aspectj的规则就是上面我们能够在网上查阅到的顺序图展示的那样,依旧是老的顺序。

代码验证

我把业务逻辑从代码中删除,只验证下这几个advice的执行顺序:

 @Aspect @Component public class WebLogAspect {      private final static Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);           @Pointcut("execution(public * com.xx.xxx.xxx.controller..*.*(..))")     public void webLog() {}           @Before("webLog()")     public void doBefore(JoinPoint joinPoint) throws Throwable {         LOGGER.info("-------------doBefore-------------");     }      @AfterReturning("webLog()")     public void afterReturning() {         LOGGER.info("-------------afterReturning-------------");     }     @AfterThrowing("webLog()")     public void afterThrowing() {         LOGGER.info("-------------afterThrowing-------------");     }           @After("webLog()")     public void doAfter() throws Throwable {         LOGGER.info("-------------doAfter-------------");     }           @Around("webLog()")     public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {         long startTime = System.currentTimeMillis();         LOGGER.info("-------------doAround before proceed-------------");         Object result = proceedingJoinPoint.proceed();         LOGGER.info("-------------doAround after proceed-------------");         return result;     }

我们将版本改为2.2.5.RELEASE,结果如图:

Spring AOP的执行顺序是怎样的

我们将版本改为2.3.4.RELEASE,结果如图:

Spring AOP的执行顺序是怎样的

“Spring AOP的执行顺序是怎样的”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Spring AOP的执行顺序是怎样的

本文链接: https://www.lsjlt.com/news/84469.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring AOP的执行顺序是怎样的
    本篇内容介绍了“Spring AOP的执行顺序是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!问题描...
    99+
    2024-04-02
  • 深入理解Spring Aop的执行顺序
    首先回忆一下 AOP 的常用注解 @Before:前置通知:目标方法之前执行 @After:后置通知:目标方法之后执行 @AfterReturning:返回...
    99+
    2024-04-02
  • Spring AOP与代理类的执行顺序是什么
    本篇内容介绍了“Spring AOP与代理类的执行顺序是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!关于 Spring AO...
    99+
    2023-07-05
  • javascript顺序执行是怎样的
    这篇文章主要讲解了“javascript顺序执行是怎样的”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“javascript顺序执行是怎样的”吧! ...
    99+
    2024-04-02
  • sql语句执行顺序是怎样的
    这篇文章主要介绍了sql语句执行顺序是怎样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。sql语句执行顺序:1、最先执行from tab;...
    99+
    2024-04-02
  • Sql中执行的顺序是怎么样的
    小编给大家分享一下Sql中执行的顺序是怎么样的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!学过 Sql,或了解过 Sql 的人...
    99+
    2024-04-02
  • SQL查询的执行顺序是怎样的
    本篇内容介绍了“SQL查询的执行顺序是怎样的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!SQL 查询的执...
    99+
    2024-04-02
  • Spring Aop常见注解与执行顺序详解
    目录Spring Aop 的常用注解常见问题示例代码配置文件接口类实现类aop 拦截器测试类执行结论多切面的情况代理失效场景总结Spring 一开始最强大的就是 IOC / AOP ...
    99+
    2024-04-02
  • java代码块执行顺序是怎样的
    本文小编为大家详细介绍“java代码块执行顺序是怎样的”,内容详细,步骤清晰,细节处理妥当,希望这篇“java代码块执行顺序是怎样的”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、类的静态代码块、结构代码块、结...
    99+
    2023-06-30
  • 关于Spring BeanPostProcessor的执行顺序
    目录Spring BeanPostProcessor执行顺序Spring-BeanPostProcessor接口总结定义BeanPostProcessorBeanPostProces...
    99+
    2024-04-02
  • SQL查询语句的执行顺序是怎样的
    这篇文章主要介绍“SQL查询语句的执行顺序是怎样的”,在日常操作中,相信很多人在SQL查询语句的执行顺序是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SQL查询语句的...
    99+
    2024-04-02
  • Oracle Form触发器执行顺序是怎样的
    这篇文章主要讲解了“Oracle Form触发器执行顺序是怎样的”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Oracle Form触发器执行顺序是怎样的”...
    99+
    2024-04-02
  • sql语句执行顺序优先级是怎样的
    小编给大家分享一下sql语句执行顺序优先级是怎样的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!sql执行顺序优先级由高到低依次...
    99+
    2024-04-02
  • Spring AOP中多切面运行顺序是什么
    这篇文章将为大家详细讲解有关Spring AOP中多切面运行顺序是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Spring AOP多切面运行顺序多切面运行顺序当一个方法的执行被多个切面共同...
    99+
    2023-06-29
  • spring中aop的执行原理是什么
    在Spring中,AOP(面向切面编程)的执行原理主要涉及以下几个方面:1. 切面的定义:通过注解或配置文件等方式,定义切面(Asp...
    99+
    2023-08-09
    spring aop
  • Java中try-catch-finally语法块的执行顺序是怎样的
    这篇文章主要讲解了“Java中try-catch-finally语法块的执行顺序是怎样的”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中try-catch-finally语法块的执行...
    99+
    2023-06-03
  • mysql的执行顺序是什么
    mysql的执行顺序是什么?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、执行顺序根据查询指定的表格,from计算笛卡尔积。on根据join_condition过滤数据。...
    99+
    2023-06-14
  • MySql的执行顺序
    mysql执行顺序如下: from 阶段 where 阶段 group by 阶段 having 阶段 select 阶段 order by 阶段 limit 阶段 按照以上书写顺序,完整的执行顺...
    99+
    2023-08-31
    mysql 数据库 java
  • Spring初始化与销毁的执行顺序是什么
    这篇文章主要介绍了Spring初始化与销毁的执行顺序是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring初始化与销毁的执行顺序是什么文章都会有所收获,下面我们一起来看看吧。演示 - 初始化销毁顺序@...
    99+
    2023-07-05
  • golang init的执行顺序是什么
    在Go语言中,init()函数是一个特殊的函数,它会在程序运行时自动被调用,而不需要显式调用。 init()函数的执行顺序如下: ...
    99+
    2024-02-29
    golang
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作