Spring--AOP、通知的执行顺序

多个切面的执行顺序

如果我们在同一个方法使用多个AOP注解,我们如何指定他们的执行顺序呢?

可以通过指定切面的order,order越小越是最先执行

配置切面执行顺序的三种方式:

一.通过实现Ordered接口

@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect1 implements Ordered{@Override 
  public int getOrder() { 
    // TODO Auto-generated method stub 
    return 2; 
  } 
   
}

二.配置文件配置

<aop:config expose-proxy="true"> 
  <aop:aspect ref="aopBean" order="0">  
    <aop:pointcut id="testPointcut" expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>  
    <aop:around pointcut-ref="testPointcut" method="doAround" />  
  </aop:aspect>  
</aop:config>

三.@Order注解指定

@Component
@Aspect
@Slf4j
@Order(1) 
public class MessageQueueAopAspect1{  
  ... 
}

通知的执行顺序

Advice :通知(建言),在切面的某个特定的连接点(增强方法)(Join point)上执行的操作。

分为:

 测试示例

创建两个自定义注解

自定义注解1

 1 /**
 2  * 自定义注解1
 3  * @author JustJavaIt
 4  * @date 2022/3/20 21:09
 5  */
 6 @Target(ElementType.METHOD)
 7 @Retention(RetentionPolicy.RUNTIME)
 8 @Documented
 9 public @interface Annotation1 {
10 }

 自定义注解2

 1 /**
 2  * 自定义注解2
 3  * @author JustJavaIt
 4  * @date 2022/3/20 21:09
 5  */
 6 @Target(ElementType.METHOD)
 7 @Retention(RetentionPolicy.RUNTIME)
 8 @Documented
 9 public @interface Annotation2 {
10 
11 }

 定义两个切面

切面1

 1 /**
 2  * 切面1 order比较小 先执行
 3  * @author JustJavaIt
 4  * @date 2022/3/20 21:13
 5  */
 6 @Component
 7 @Aspect
 8 @Slf4j
 9 @Order(1)
10 public class AopAspect1 {
11 
12     @Pointcut("@annotation(com.study.frame.aopTest.Annotation1)")
13     private void pointCutMethod() {
14     }
15 
16     /**
17      * 前置通知: 在一个方法执行之前,执行通知。
18      * 模拟执行权限检查
19      * @param point
20      */
21     @Before("pointCutMethod()")
22     public void doBefore(JoinPoint point) {
23         log.info("AopAspect1:@Before,目标方法为:{},参数为{}",
24                 point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName(),
25                 Arrays.toString(point.getArgs()));
26     }
27 
28     /**
29      * 返回后通知: 在一个方法执行之后,只有在方法成功完成时,才能执行通知。如果抛异常了,那么不会执行通知(可打开测试Controller注释)。
30      * @param point
31      * @param returnValue
32      */
33     @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
34     public void doAfterReturning(JoinPoint point,Object returnValue) {
35         log.info("AopAspect1:@AfterReturning,方法返回值为:{}", returnValue);
36     }
37 
38     /**
39      * 抛出异常后通知: 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
40      * @param e
41      */
42     @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
43     public void doAfterThrowing(Exception e) {
44         log.info("AopAspect1:@AfterThrowing");
45     }
46 
47     /**
48      * 后置通知:在一个方法执行之后,不考虑其结果,执行通知。
49      */
50     @After("pointCutMethod()")
51     public void doAfter() {
52         log.info("AopAspect1:@After");
53     }
54 
55     /**
56      * 环绕通知: 在建议方法调用之前和之后,执行通知。
57      * @param pjp
58      * @return
59      * @throws Throwable
60      */
61     @Around("pointCutMethod()")
62     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
63         log.info("AopAspect1:@Around-1");
64         Object obj = pjp.proceed();
65         log.info("AopAspect1:@Around-2");
66         return obj;
67     }
68 }
View Code

切面2

 1 /**
 2  * 切面2 order比较大 后执行
 3  * @author JustJavaIt
 4  * @date 2022/3/20 21:15
 5  */
 6 @Component
 7 @Aspect
 8 @Slf4j
 9 @Order(2)
10 public class AopAspect2 {
11 
12     @Pointcut("@annotation(com.study.frame.aopTest.Annotation2)")
13     private void pointCutMethod() {
14     }
15 
16 
17     //声明前置通知
18     @Before("pointCutMethod()")
19     public void doBefore(JoinPoint point) {
20         log.info("AopAspect2:@Before,目标方法为:{},参数为{}",
21                 point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName(),
22                 Arrays.toString(point.getArgs()));
23     }
24 
25     //声明后置通知
26     @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
27     public void doAfterReturning(JoinPoint point, Object returnValue) {
28         log.info("AopAspect2:@AfterReturning,方法返回值为:{}", returnValue);
29     }
30 
31     //声明例外通知
32     @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
33     public void doAfterThrowing(Exception e) {
34         log.info("AopAspect2:@AfterThrowing");
35     }
36 
37     //声明最终通知
38     @After("pointCutMethod()")
39     public void doAfter() {
40         log.info("AopAspect2:@After");
41     }
42 
43     //声明环绕通知
44     @Around("pointCutMethod()")
45     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
46         log.info("AopAspect2:@Around-1");
47         Object obj = pjp.proceed();
48         log.info("AopAspect2:@Around-2");
49         return obj;
50     }
51 }
View Code

 测试单个切面(无异常)

@RestController
@Slf4j
@RequestMapping("/study")
public class TestAopController {

    @Annotation1
    @GetMapping("/testAop")
    public Boolean testAop(@RequestParam("user_id") Long userId) throws Exception {
        log.info("开始执行testAop()");
        return true;
    }
}

运行结果:

 

 测试单个切面(抛异常)

 1 @RestController
 2 @Slf4j
 3 @RequestMapping("/study")
 4 public class TestAopController {
 5 
 6     @Annotation1
 7     @GetMapping("/testAop")
 8     public Boolean testAop(@RequestParam("user_id") Long userId) throws Exception {
 9         log.info("开始执行testAop()");
10         throw new Exception("异常");
11     }
12 }

运行结果:

 

 测试多个切面(无异常)

 1 @RestController
 2 @Slf4j
 3 @RequestMapping("/study")
 4 public class TestAopController {
 5 
 6     @Annotation1
 7     @Annotation2
 8     @GetMapping("/testAop")
 9     public Boolean testAop(@RequestParam("user_id") Long userId) throws Exception {
10         log.info("开始执行testAop()");
11         //throw new Exception("异常");
12         return true;
13     }
14 }

运行结果:

 测试多个切面(抛异常)

 1 @RestController
 2 @Slf4j
 3 @RequestMapping("/study")
 4 public class TestAopController {
 5 
 6     @Annotation1
 7     @Annotation2
 8     @GetMapping("/testAop")
 9     public Boolean testAop(@RequestParam("user_id") Long userId) throws Exception {
10         log.info("开始执行testAop()");
11         throw new Exception("异常");
12     }
13 }

运行结果:

 总结

 

待补充 ......

 

希望本文章对您有帮助,您的转发、点赞是我的创作动力,十分感谢。

扫描下方二维码关注我,您会收到更多优质文章推送。

 

posted @ 2020-12-20 22:37  JustJavaIt  阅读(3351)  评论(2编辑  收藏  举报