Spring AOP 在我们日常开发中扮演了一个非常重要的角色,对于如何使用 AOP 相信很多人已经不陌生,但其中有一些点却容易被我们忽视,本节我们结合一些“不为常知”的问题展开讨论。

同一个 AOP 类中几个切面注解的执行顺序

先给出结论:@Around [joinPoint.proceed()前] —> @Before —> @Around [joinPoint.proceed()以及之后] —> @After —> @AfterReturning(如果有异常则@AfterThrowing)

话不多说,我这们直接上代码:

@Aspect
public class AopClass { @Pointcut(value = "execution(* io.alan.*.Klass.*dong(..))")
public void point() { } @Before(value = "point()")
public void before() {
System.out.println("========>begin klass dong... //2");
} @Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("========>around begin klass dong //1");
joinPoint.proceed();
System.out.println("========>around after klass dong //3");
} @After(value = "point()")
public void after() {
System.out.println("========>after klass dong... //4");
} @AfterReturning(value = "point()")
public void afterReturning() {
System.out.println("========>after klass dong... //5");
} }

查看应用打印的日志,如下:

不同 AOP 类切面的执行顺序

如果我们对同一个方法定义多个 AOP,它的执行顺序是什么样的呢?

配置 AOP 执行顺序的三种方式

方式1:实现 org.springframework.core.Ordered 接口
@Aspect
public class AopClass implements Ordered { @Override
public int getOrder() {
return 2;
} }
方式2:使用注解 @Order
@Aspect
@Order(2)
public class AopClass { }
方式3:使用配置文件
<aop:config expose-proxy="true">
<aop:aspect ref="aopBean" order="2">
<aop:pointcut id="testPointcut" expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>
<aop:around pointcut-ref="testPointcut" method="doAround" />
</aop:aspect>
</aop:config>

代码测试

下面我们演示在同一份代码上加上两个 AOP,然后观察日志。

@Aspect
@Order(2)
public class Aop2 { @Pointcut(value = "execution(* io.kimmking.*.Klass.*dong(..))")
public void point() { } @Before(value = "point()")
public void before() {
System.out.println(" Aop2========>before klass dong... //2");
} @AfterReturning(value = "point()")
public void afterReturning() {
System.out.println(" Aop2========>afterReturning klass dong... //5");
} @After(value = "point()")
public void after() {
System.out.println(" Aop2========>after klass dong... //4");
} @Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(" Aop2========>around before klass dong //1");
joinPoint.proceed();
System.out.println(" Aop2========>around after klass dong //3"); } }
@Aspect
@Order(3)
public class Aop3 { @Pointcut(value = "execution(* io.kimmking.*.Klass.*dong(..))")
public void point() { } @Before(value = "point()")
public void before() {
System.out.println(" Aop3========>before klass dong... //2");
} @AfterReturning(value = "point()")
public void afterReturning() {
System.out.println(" Aop3========>afterReturning klass dong... //5");
} @After(value = "point()")
public void after() {
System.out.println(" Aop3========>after klass dong... //4");
} @Around("point()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println(" Aop3========>around before klass dong //1");
joinPoint.proceed();
System.out.println(" Aop3========>around after klass dong //3"); } }

打印的日志如下:

从日志中我们可以看到,order 越小的 AOP 类越先执行,但还有一点需要我们注意:就是最先执行的 AOP 最后才执行结束(如上图中的 AOP2)。

我们通过下面的这张示意图就可以理解了。

小结一下:我们可以将 Spring AOP 当作一个同心圆,要执行的方法为圆心,最外层的 order 最小。从最外层按照 AOP1、AOP2 的顺序依次执行 Around 方法,Before 方法。然后执行 method 方法,最后按照 AOP2、AOP1 (顺序反过来了)的顺序依次执行 After、AfterReturn 方法。

所以对多个AOP来说,先执行 before 的,一定后执行 after。

例如,如果我们要在同一个方法事务提交后执行自己的 AOP ,那么可以把事务的 AOP order 设置为2,自己的 AOP order 设置为1,然后在 AfterReturn 里边处理自己的业务逻辑。

参考链接


END

聊聊 Spring AOP 的不为常知的“秘事”的更多相关文章

  1. Spring -- aop(面向切面编程),前置&后置&环绕&抛异常通知,引入通知,自动代理

    1.概要 aop:面向方面编程.不改变源代码,还为类增加新的功能.(代理) 切面:实现的交叉功能. 通知:切面的实际实现(通知要做什么,怎么做). 连接点:应用程序执行过程期间,可以插入切面的地点. ...

  2. 从源码层面聊聊面试问烂了的 Spring AOP与SpringMVC

    Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以.但今天笔者带大家一起深入浅出源码,看看他的原理.以期让印象更加深刻,面试的时候游刃有余. Sp ...

  3. Spring AOP常见面试题

    一.AOP是什么? 与OOP对比,面向切面,传统的OOP开发中的代码逻辑是至上而下的过程中会长生一些横切性问题,这些横切性的问题和我们的主业务逻辑关系不会散落在代码的各个地方,造成难以维护,AOP的编 ...

  4. 死磕Spring之AOP篇 - Spring AOP常见面试题

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  5. 学习Spring5必知必会(5)~Spring AOP

    一.学习 AOP 思想的准备工作: 1.横切面关注点 在开发中,为了给业务方法中增加日志记录,权限检查,事务控制等功能,此时我们需要在修改业务方法内添加这些零散的功能代码(横切面关注点). 这些零散存 ...

  6. 比较 Spring AOP 与 AspectJ

    本文翻译自博客Comparing Spring AOP and AspectJ(转载:https://juejin.im/post/5a695b3cf265da3e47449471) 介绍 如今有多个 ...

  7. 关于 Spring AOP (AspectJ) 该知晓的一切

    关联文章: 关于Spring IOC (DI-依赖注入)你需要知道的一切 关于 Spring AOP (AspectJ) 你该知晓的一切 本篇是年后第一篇博文,由于博主用了不少时间在构思这篇博文,加上 ...

  8. 关于 Spring AOP (AspectJ) 你该知晓的一切

    版权声明:本文为CSDN博主「zejian_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/javazej ...

  9. Spring AOP源码分析--代理方式的选择

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 年前写了一个面试突击系列的文章,目前只有redis相关的.在这个系列里,我整理了一些面试题与大家 ...

随机推荐

  1. NNVM AI框架编译器

    NNVM AI框架编译器 深度学习已变得无处不在且不可或缺.看到对在多种平台(例如手机,GPU,IoT设备和专用加速器)上部署深度学习工作负载的需求不断增长.TVM堆栈弥合深度学习框架与面向性能或效率 ...

  2. 从7nm到5nm,半导体制程

    从7nm到5nm,半导体制程 芯片的制造工艺常常用XXnm来表示,比如Intel最新的六代酷睿系列CPU就采用Intel自家的14nm++制造工艺.所谓的XXnm指的是集成电路的MOSFET晶体管栅极 ...

  3. Geo-CNN的三维点云

    Geo-CNN的三维点云 Modeling Local Geometric Structure of 3D Point Clouds using Geo-CNN 摘要 深度卷积神经网络(CNNs)的最 ...

  4. java接口类

    是什么:类似于java中的继承,但是继承只可以继承一个人父类,接口类可以继承多个 作用:解决java继承解决不了的问题 关键字:interface(定义) implements(使用) 注意事项:1. ...

  5. Spring Aop的执行顺序

    Spring Aop的执行顺序 首先回忆一下 AOP 的常用注解 @Before:前置通知:目标方法之前执行 @After:后置通知:目标方法之后执行 @AfterReturning:返回后通知:执行 ...

  6. 从1+1=2来理解Java字节码从1+1=2来理解Java字节码

    编译"1+1"代码 首先我们需要写个简单的小程序,1+1的程序,学习就要从最简单的1+1开始,代码如下: 写好java类文件后,首先执行命令javac TestJava.java ...

  7. Mybatis数据连接池的配置---增删改查(以及遇见的问题)

    1.首先创建项目和各个文件,如图所示: 2.配置相关数据库连接 在jdbc.properties中加入 1 db.driver=com.mysql.jdbc.Driver 2 db.url=jdbc: ...

  8. 【题解】滑雪 luogu1434 记忆化搜索

    记忆化搜索入门题 题目 Michael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在 ...

  9. VBS脚本编程(3)——常用函数

    数据类型转换函数 1.Hex 函数 返回表示十六进制数字值的字符串. Hex(number) number 参数是任意有效的表达式. 说明 如果 number 参数不是整数,则在进行运算前将其四舍五入 ...

  10. HTTP首部字段详解

    HTTP首部字段详解 在HTTP/1.1规范中定义了47种首部字段,总共分为四大类: 通用首部字段 -- 请求报文和响应报文两方都会使用的首部 请求首部字段 -- 从客户端向服务器端发送请求报文时使用 ...