日常開發中經常會使用到 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
順序依次執行,從上面日誌可以看出
- 本文完,希望對你有幫助