spring boot 单个切面内,多个通知处理一个切点执行的顺序是怎样的?多个切面,多个通知处理一个切点的执行顺序又是怎样的?请看下文:
大体逻辑依然是:1.around > 2.before > 切点方法 > 3.around > 4.after > 5.afterReturning(or afterThrowing)
相同类型的通知根据通知方法名称的字典序执行
注: @Order 放在相同类型的通知根据方法上并不会改变同类通知的执行顺序
注: 多个切面默认按照切面类名称的字典序执行,@Order注解放在切面类上可以改变切面的执行顺序,值越小,切面越先执行
整体类似于同心圆,局部与单个切面执行逻辑一致
整体执行顺序如下:
详细执行顺序如下:
注: 同一个切面内,相同类型的通知根据通知方法名称的字典序执行
切面1(示例):
package com.imooc.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Slf4j
//@Order(6)
public class Aspect1 {
@Pointcut("execution(* com.imooc.controller.HelloController.*(..))")
private void pointCutMethod() {
}
//声明前置通知
// @Before("pointCutMethod()")
// public void doBefore2(JoinPoint point) {
// log.info("Aspect1:doBefore2");
// }
//声明前置通知
@Before("pointCutMethod()")
public void doBefore1(JoinPoint point) {
log.info("Aspect1:doBefore1");
}
//声明前置通知
// @Before("pointCutMethod()")
// public void aBefore(JoinPoint point) {
// log.info("Aspect1:aBefore");
// }
//声明后置通知
@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
log.info("Aspect1:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
log.info("Aspect1:doAfterThrowing");
}
//声明最终通知
@After("pointCutMethod()")
public void doAfter() {
log.info("Aspect1:doAfter");
}
//声明环绕通知
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
log.info("Aspect1:doAround-1");
Object obj = pjp.proceed();
log.info("Aspect1:doAround-2");
return obj;
}
}
切面2(示例):
package com.imooc.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Slf4j
//@Order(1)
public class Aspect2 {
@Pointcut("execution(* com.imooc.controller.HelloController.*(..))")
private void pointCutMethod() {
}
//声明前置通知
@Before("pointCutMethod()")
public void doBefore(JoinPoint point) {
log.info("Aspect2:doBefore");
}
//声明后置通知
@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
log.info("Aspect2:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
log.info("Aspect2:doAfterThrowing");
}
//声明最终通知
@After("pointCutMethod()")
public void doAfter() {
log.info("Aspect2:doAfter");
}
//声明环绕通知
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
log.info("Aspect2:doAround-1");
Object obj = pjp.proceed();
log.info("Aspect2:doAround-2");
return obj;
}
}
切点(示例):
package com.imooc.controller;
import com.imooc.config.SelfRefreshScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import java.util.ArrayList;
import java.util.List;
@ApiIgnore
@RestController
@SelfRefreshScope
public class HelloController {
final static Logger logger = LoggerFactory.getLogger(HelloController.class);
@GetMapping("/hello")
public Object hello() {
logger.info("info: hello~");
List<String> list = new ArrayList<>();
return list;
}
}
spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。