3.2 通知顺序
讲解完了Spring中AOP所支持的5种通知类型之后,接下来我们再来研究通知的执行顺序。
当在项目开发当中,我们定义了多个切面类,而多个切面类中多个切入点都匹配到了同一个目标方法。此时当目标方法在运行的时候,这多个切面类当中的这些通知方法都会运行。
此时我们就有一个疑问,这多个通知方法到底哪个先运行,哪个后运行? 下面我们通过程序来验证(这里呢,我们就定义两种类型的通知进行测试,一种是前置通知@Before,一种是后置通知@After)
定义多个切面类:
@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 ..."); } }
@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 ..."); } }
@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服务,测试通知的执行顺序:
备注:
- 把DeptServiceImpl实现类中模拟异常的代码删除或注释掉。
- 注释掉其他切面类(把@Aspect注释即可),仅保留MyAspect2、MyAspect3、MyAspect4 ,这样就可以清晰看到执行的结果,而不被其他切面类干扰。
- 使用postman测试查询所有部门数据
-
- 查看idea中控制台日志输出
-
通过以上程序运行可以看出在不同切面类中,默认按照切面类的类名字母排序:
- 目标方法前的通知方法:字母排名靠前的先执行
- 目标方法后的通知方法:字母排名靠前的后执行
如果我们想控制通知的执行顺序有两种方式:
- 修改切面类的类名(这种方式非常繁琐、而且不便管理)
- 使用Spring提供的@Order注解
使用@Order注解,控制通知的执行顺序:
@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 ..."); } }
@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 ..."); } }
@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服务,测试通知执行顺序:
通知的执行顺序大家主要知道两点即可:
- 不同的切面类当中,默认情况下通知的执行顺序是与切面类的类名字母排序是有关系的
- 可以在切面类上面加上@Order注解,来控制不同的切面类通知的执行顺序