乐趣区

SpringOrder注解

如果咱们在同一个办法自定义多个 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 就是面向切面编程,什么是切面,画一个图来了解下:

由此得出:

  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 里边解决本人的业务逻辑

退出移动版