专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

# Spring实战系列 - Aspect 五种通知切面通知执行顺序

日常开发中经常会使用到 Spring AOP,通知类型有:Around、Before、After、AfterReturning、AfterThrowing ,本文主要讲解五种通知都有时,正常和异常情况下的执行顺序,以及多个切面存在时,执行顺序如何

正常逻辑代码

  • 接口定义如下
public interface UserService {

    void saveUser();

    void deleteUser();
}

  • 接口实现代码如下
@Slf4j
@Component
public class UserServiceImpl implements UserService {

    @Override
    public void saveUser() {
        log.info("save user");
    }

    @Override
    public void deleteUser() {
        log.info("delete user");
        System.out.println(1 / 0);
    }
}

针对正常接口 UserService 定义两个切面逻辑

  • 切面一
@Slf4j
@Order(99)// 注意顺序
@Aspect
@Component
public class UserServiceAspect {

    @Before("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void before() {
        log.info("before");
    }

    @Around("execution(* com.lushwe.aspect.service.impl..*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around开始");
        Object proceed = proceedingJoinPoint.proceed();
        log.info("around结束");
        return proceed;
    }

    @After("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void after() {
        log.info("after");
    }

    @AfterReturning("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void afterReturning() {
        log.info("afterReturning");
    }

    @AfterThrowing("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void afterThrowing() {
        log.info("afterThrowing");
    }
}

  • 切面二
@Slf4j
@Order(100)// 注意顺序
@Aspect
@Component
public class UserServiceAspectTwo {

    @Before("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void before() {
        log.info("before");
    }

    @Around("execution(* com.lushwe.aspect.service.impl..*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("around开始");
        Object proceed = proceedingJoinPoint.proceed();
        log.info("around结束");
        return proceed;
    }

    @After("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void after() {
        log.info("after");
    }

    @AfterReturning("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void afterReturning() {
        log.info("afterReturning");
    }

    @AfterThrowing("execution(* com.lushwe.aspect.service.impl..*(..))")
    public void afterThrowing() {
        log.info("afterThrowing");
    }
}

正常情况下执行顺序,打印日志如下

2020-04-17 15:27:55.500  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspect      : around开始
2020-04-17 15:27:55.501  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspect      : before
2020-04-17 15:27:55.501  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : around开始
2020-04-17 15:27:55.501  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : before
2020-04-17 15:27:55.501  INFO 4329 --- [           main] c.l.aspect.service.impl.UserServiceImpl  : save user
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : around结束
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : after
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : afterReturning
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspect      : around结束
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspect      : after
2020-04-17 15:27:55.503  INFO 4329 --- [           main] com.lushwe.aspect.UserServiceAspect      : afterReturning

有异常情况下执行顺序,打印日志如下

2020-04-17 15:20:55.403  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspect      : around开始
2020-04-17 15:20:55.403  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspect      : before
2020-04-17 15:20:55.403  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : around开始
2020-04-17 15:20:55.403  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : before
2020-04-17 15:20:55.403  INFO 4227 --- [           main] c.l.aspect.service.impl.UserServiceImpl  : delete user
2020-04-17 15:20:55.403  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : after
2020-04-17 15:20:55.405  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspectTwo   : afterThrowing
2020-04-17 15:20:55.405  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspect      : after
2020-04-17 15:20:55.406  INFO 4227 --- [           main] com.lushwe.aspect.UserServiceAspect      : afterThrowing
Exception in thread "main" java.lang.ArithmeticException: / by zero
...(详细异常信息省略)...

总结

  • 正常情况下执行顺序:Around start -> Before -> Around end -> After -> AfterReturning
  • 有异常情况下执行顺序:Around start -> Before -> After -> AfterThrowing ,有异常时,Around end 逻辑不会执行
  • 当有多有切面时,按照 @Order 顺序依次执行,从上面日志可以看出

  • 本文完,希望对你有帮助

文章永久链接:https://tech.souyunku.com/47518

未经允许不得转载:搜云库技术团队 » # Spring实战系列 - Aspect 五种通知切面通知执行顺序

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们