# 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 順序依次執行,從上面日誌可以看出

  • 本文完,希望對你有幫助
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章