Spring-Order注解

如果我们在同一个方法自定义多个AOP,如何执行执行顺序?

有一种答案是指定order,order越小越先执行。这种答案不算错,但是有些片面。

更改Aspect的Order有三中方式,1:通过实现org.springframework.core.Ordered接口;2:通过注解@Order(1) ;3:通过配置文件配置

我们实验采用注解的方式,定义两个Aspect:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Log {

 String description() default "";

}

order=1001

代码java

@Aspect

@Component

@Order(1001)

public class LogAspect {

 private final Logger logger /= LoggerFactory.getLogger(this.getClass());

​

​

 //日志注解

 @Pointcut(value /= "@annotation(com.meituan.pay.mapi.aspect.Log)")

 public void logAspect() {

 }

​

 //声明前置通知

 @Before("logAspect()")

 public void doBefore(JoinPoint point) {

 logger.info("logAspect:doBefore");

 return;

 }

​

 //声明后置通知

 @AfterReturning(pointcut /= "logAspect()", returning /= "returnValue")

 public void doAfterReturning(JoinPoint point, Object returnValue) {

 logger.info("logAspect:doAfterReturning");

 }

​

 //声明例外通知

 @AfterThrowing(pointcut /= "logAspect()", throwing /= "e")

 public void doAfterThrowing(Exception e) {

 logger.info("logAspect:doAfterThrowing");

 }

​

 //声明最终通知

 @After("logAspect()")

 public void doAfter() {

 logger.info("logAspect:doAfter");

 }

​

 //声明环绕通知

 @Around("logAspect()")

 public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

 logger.info("logAspect:doAround-start");

 Object obj /= pjp.proceed();

 logger.info("logAspect:doAround-end");

 return obj;

 }

​

}

**SignAspect:**

代码块

java

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Sign {

 String description() default "";

}

order=1002

代码块

java

@Aspect

@Component

@Order(1002)

public class SignAspect {

 private final Logger logger /= LoggerFactory.getLogger(this.getClass());

​

​

 //日志注解

 @Pointcut(value /= "@annotation(com.meituan.pay.mapi.aspect.Sign)")

 public void signAspect() {

 }

​

 //声明前置通知 

 @Before("signAspect()")

 public void doBefore(JoinPoint point) {

 logger.info("signAspect:doBefore");

 return;

 }

​

 //声明后置通知 

 @AfterReturning(pointcut /= "signAspect()", returning /= "returnValue")

 public void doAfterReturning(JoinPoint point, Object returnValue) {

 logger.info("signAspect:doAfterReturning");

 }

​

 //声明例外通知 

 @AfterThrowing(pointcut /= "signAspect()", throwing /= "e")

 public void doAfterThrowing(Exception e) {

 logger.info("signAspect:doAfterThrowing");

 }

​

 //声明最终通知 

 @After("signAspect()")

 public void doAfter() {

 logger.info("signAspect:doAfter");

 }

​

 //声明环绕通知 

 @Around("signAspect()")

 public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

 logger.info("signAspect:doAround-start");

 Object obj /= pjp.proceed();

 logger.info("signAspect:doAround-end");

 return obj;

 }

​

}
**测试:**

代码块

java

@Service

public class AspectTestService {

 private static final Logger LOGGER /= LoggerFactory.getLogger(AspectTestService.class);

​

 @Sign

 @Log

 public void testAspect() {

 LOGGER.info("执行方法");

 }

}
**最终输出:**

代码块

java

LogAspect (LogAspect.java:55) logAspect:doAround/-start

LogAspect (LogAspect.java:30) logAspect:doBefore

SignAspect (SignAspect.java:54) signAspect:doAround/-start

SignAspect (SignAspect.java:29) signAspect:doBefore

AspectTestService (AspectTestService.java:19) 执行方法

SignAspect (SignAspect.java:56) signAspect:doAround/-end

SignAspect (SignAspect.java:48) signAspect:doAfter

SignAspect (SignAspect.java:36) signAspect:doAfterReturning

LogAspect (LogAspect.java:57) logAspect:doAround/-end

LogAspect (LogAspect.java:49) logAspect:doAfter

LogAspect (LogAspect.java:37) logAspect:doAfterReturning

**结论:**

从上面的测试我们看到,确实是order越小越是最先执行,但更重要的是最先执行的最后结束。

AOP就是面向切面编程,什么是切面,画一个图来理解下:


Spring-Order注解

由此得出:

  1. spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小
  2. 从最外层按照LogAspect、SignAspect的顺序依次执行doAround方法,doBefore方法
  3. 然后执行method方法
  4. 最后按照SignAspect、LogAspect的顺序依次执行doAfter、doAfterReturn方法
  5. 也就是说对多个AOP来说,先before的,一定后after

应用举例:

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

原文 

https://segmentfault.com/a/1190000023246427

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring-Order注解

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址