郁闷了半天,我通过AOP切面打印的日志顺序怪怪的,网上查了好几篇文章都说没问题,最后发现是springboot版本升级后@Before @Around @After等执行顺序发生了变化。
1.切面类
@Aspect// 这是一个切面
@Component// 这是一个需要被装配的spring bean
@Slf4j
public class AopOrderAspecct {@Pointcut("execution(public void com.example.temp.aopOrder.*.*())")public void point() {}@Before("point()")public void before(JoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String methodName = methodSignature.getName();log.info("{}-执行before。。。", methodName);}@Around("point()")public void around(ProceedingJoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String methodName = methodSignature.getName();log.info("{}-进入around。。。", methodName);try {joinPoint.proceed();} catch (Throwable throwable) {log.error("{}-around内部方法执行失败:{}", methodName, throwable.getMessage());}log.info("{}-around执行完毕!", methodName);}@After("point()")public void after(JoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String methodName = methodSignature.getName();log.info("{}-执行after。。。", methodName);}@AfterReturning("point()")public void afterReturning(JoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String methodName = methodSignature.getName();log.info("{}-执行afterReturning。。。", methodName);}@AfterThrowing("point()")public void afterThrowing(JoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String methodName = methodSignature.getName();log.info("{}-执行afterThrowing。。。", methodName);}
}
2.测试Service
@Component
@Slf4j
public class AopOrderServiceA {@ResourceAopOrderServiceB serviceB;public void aopOrderA() {log.info("aopOrderA-进入方法。。。");int x = 0/0;serviceB.aopOrderB();log.info("aopOrderA-方法执行完毕!");}}@Component
@Slf4j
public class AopOrderServiceB {public void aopOrderB() {log.info("aopOrderB-进入方法。。。");
// int x = 0/0;log.info("aopOrderB-方法执行完毕!");}
}
3.单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class OrderServiceTest {@ResourceAopOrderService aopOrderService;@Testpublic void testOrder() {String springVersion = SpringVersion.getVersion();String bootVersion = SpringBootVersion.getVersion();log.info("spring:{},springBoot:{}", springVersion, bootVersion);aopOrderService.aopOrder();}
}
4.springboot不同版本的结果
springboot版本 2.3.1.RELEASE 之前,after在around之后执行, 2.3.1.RELEASE 及之后,around包裹整个切面执行周期。
spring boot 版本为 2.0.0.RELEASE
spring:5.0.4.RELEASE,springBoot:2.0.0.RELEASE
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-方法执行完毕!
aopOrderA-around执行完毕!
aopOrderA-执行after。。。
aopOrderA-执行afterReturning。。。
spring boot 版本为 2.1.0.RELEASE
spring:5.1.2.RELEASE,springBoot:2.1.0.RELEASE
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-方法执行完毕!
aopOrderA-around执行完毕!
aopOrderA-执行after。。。
aopOrderA-执行afterReturning。。。
spring boot 版本为 2.2.0.RELEASE
spring:5.2.0.RELEASE,springBoot:2.2.0.RELEASE
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-方法执行完毕!
aopOrderA-around执行完毕!
aopOrderA-执行after。。。
aopOrderA-执行afterReturning。。。
spring boot 版本为 2.3.0.RELEASE
spring:5.2.6.RELEASE,springBoot:2.3.0.RELEASE
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-方法执行完毕!
aopOrderA-around执行完毕!
aopOrderA-执行after。。。
aopOrderA-执行afterReturning。。。
spring boot 版本为 2.3.1.RELEASE(从这里开始不一样)
spring:5.2.7.RELEASE,springBoot:2.3.1.RELEASE
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-方法执行完毕!
aopOrderA-执行afterReturning。。。
aopOrderA-执行after。。。
aopOrderA-around执行完毕!// 注意,这里不同
spring boot 版本为2.7.0(目标方法执行抛出异常时)
spring:5.3.20,springBoot:2.7.0
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderA-执行afterThrowing。。。// 注意,这里不同
aopOrderA-执行after。。。
aopOrderA-around内部方法执行失败:/ by zero
aopOrderA-around执行完毕!
当目标方法切面嵌套时
spring:5.3.20,springBoot:2.7.0
aopOrderA-进入around。。。
aopOrderA-执行before。。。
aopOrderA-进入方法。。。
aopOrderB-进入around。。。
aopOrderB-执行before。。。
aopOrderB-进入方法。。。
aopOrderB-方法执行完毕!
aopOrderB-执行afterReturning。。。
aopOrderB-执行after。。。
aopOrderB-around执行完毕!
aopOrderA-方法执行完毕!
aopOrderA-执行afterReturning。。。
aopOrderA-执行after。。。
aopOrderA-around执行完毕!
aopOrderA-方法执行完毕!
aopOrderA-执行afterReturning。。。
aopOrderA-执行after。。。
aopOrderA-around执行完毕!
流程图
参考连接:
https://blog.csdn.net/weixin_44005802/article/details/127014570
https://blog.csdn.net/lgxzzz/article/details/100026524