Javaweb之SpringBootWeb案例之AOP通知顺序的详细解析

3.2 通知顺序

讲解完了Spring中AOP所支持的5种通知类型之后,接下来我们再来研究通知的执行顺序。

当在项目开发当中,我们定义了多个切面类,而多个切面类中多个切入点都匹配到了同一个目标方法。此时当目标方法在运行的时候,这多个切面类当中的这些通知方法都会运行。

此时我们就有一个疑问,这多个通知方法到底哪个先运行,哪个后运行? 下面我们通过程序来验证(这里呢,我们就定义两种类型的通知进行测试,一种是前置通知@Before,一种是后置通知@After)

定义多个切面类:

java 复制代码
@Slf4j
@Component
@Aspect
public class MyAspect2 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect2 -> before ...");
    }
​
    //后置通知
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect2 -> after ...");
    }
}
​
java 复制代码
@Slf4j
@Component
@Aspect
public class MyAspect3 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect3 -> before ...");
    }
​
    //后置通知
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect3 ->  after ...");
    }
}
java 复制代码
@Slf4j
@Component
@Aspect
public class MyAspect4 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect4 -> before ...");
    }
​
    //后置通知
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect4 -> after ...");
    }
}
复制代码

重新启动SpringBoot服务,测试通知的执行顺序:

备注:

  1. 把DeptServiceImpl实现类中模拟异常的代码删除或注释掉。

  2. 注释掉其他切面类(把@Aspect注释即可),仅保留MyAspect2、MyAspect3、MyAspect4 ,这样就可以清晰看到执行的结果,而不被其他切面类干扰。

  • 使用postman测试查询所有部门数据

  • 查看idea中控制台日志输出

通过以上程序运行可以看出在不同切面类中,默认按照切面类的类名字母排序:

  • 目标方法前的通知方法:字母排名靠前的先执行

  • 目标方法后的通知方法:字母排名靠前的后执行

如果我们想控制通知的执行顺序有两种方式:

  1. 修改切面类的类名(这种方式非常繁琐、而且不便管理)

  2. 使用Spring提供的@Order注解

使用@Order注解,控制通知的执行顺序:

java 复制代码
@Slf4j
@Component
@Aspect
@Order(2)  //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect2 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect2 -> before ...");
    }
​
    //后置通知 
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect2 -> after ...");
    }
}
java 复制代码
@Slf4j
@Component
@Aspect
@Order(3)  //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect3 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect3 -> before ...");
    }
​
    //后置通知
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect3 ->  after ...");
    }
}
java 复制代码
@Slf4j
@Component
@Aspect
@Order(1) //切面类的执行顺序(前置通知:数字越小先执行; 后置通知:数字越小越后执行)
public class MyAspect4 {
    //前置通知
    @Before("execution(* com.itheima.service.*.*(..))")
    public void before(){
        log.info("MyAspect4 -> before ...");
    }
​
    //后置通知
    @After("execution(* com.itheima.service.*.*(..))")
    public void after(){
        log.info("MyAspect4 -> after ...");
    }
}

重新启动SpringBoot服务,测试通知执行顺序:

通知的执行顺序大家主要知道两点即可:

  1. 不同的切面类当中,默认情况下通知的执行顺序是与切面类的类名字母排序是有关系的

  2. 可以在切面类上面加上@Order注解,来控制不同的切面类通知的执行顺序

相关推荐
m0_3801138436 分钟前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
Gofarlic_OMS1 小时前
SolidEdge专业许可证管理工具选型关键评估标准
java·大数据·运维·服务器·人工智能
风树种子1 小时前
深入理解 Spring TaskDecorator:异步线程上下文传递的优雅之道
spring·taskdecorator·异步线程上下文
清华都得不到的好学生1 小时前
数据结构->1.稀疏数组,2.数组队列(没有取模),3.环形队列
java·开发语言·数据结构
weyyhdke1 小时前
基于SpringBoot和PostGIS的省域“地理难抵点(最纵深处)”检索及可视化实践
java·spring boot·spring
ILYT NCTR1 小时前
【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
java·spring boot·spring
weixin_425023001 小时前
PG JSONB 对应 Java 字段 + MyBatis-Plus 完整实战
java·开发语言·mybatis
不早睡不改名@2 小时前
Netty源码分析---Reactor线程模型深度解析(二)
java·网络·笔记·学习·netty
子非鱼@Itfuture2 小时前
`<T> T execute(...)` 泛型方法 VS `TaskExecutor<T>` 泛型接口对比分析
java·开发语言
2601_949816162 小时前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring