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注解,来控制不同的切面类通知的执行顺序

相关推荐
唐青枫13 小时前
Java SLF4J 实战指南:从日志门面到 Logback、MDC 和链路追踪
java
名字还没想好☜13 小时前
Go slice 的 append 陷阱:共享底层数组导致的数据串改
开发语言·后端·golang·go·slice
诸神缄默不语13 小时前
FastAPI后端配置CORS中间件支持浏览器跨域访问
后端·fastapi
Fanta丶13 小时前
14.Activiti7 网关 排他网关ExclusiveGateway、并行网关ParallelGateway
后端
明月_清风13 小时前
robots.txt 完全指南:从入门到精通
后端·爬虫
jvmind_dev13 小时前
Java GC 实战指南(番外篇):被忽视的隐形杀手 —— Class Unloading 如何拖垮 GC
java·后端
An_s13 小时前
机器学习python之识别图中物品信息
java·linux·开发语言
明月_清风13 小时前
从零写一个"像人"的爬虫:反爬攻防实战指南
后端·爬虫
贰先生13 小时前
Xiuno BBS 审计之问题13:管理员发帖 doctype=0 时存储型 XSS
后端
AIGS00114 小时前
跨越语义鸿沟:企业本体语义平台的构建与落地
java·人工智能·python·机器学习·人工智能ai大模型应用