设为首页 加入收藏

TOP

Spring AOP中增强Advice的执行顺序(一)
2023-07-25 21:33:13 】 浏览:47
Tags:Spring AOP Advice

Spring AOP中增强Advice的执行顺序

本文主要验证Spring AOP中Advice的执行顺序问题。(Spring版本: 5.3.23)

Spring AOP中Advice分类

Spring AOP中Advice可分为如下五类:

  1. @Around
  2. @Before
  3. @AfterReturning
  4. @AfterThrowing
  5. @After

Advice相关概念参考

同一Apsect中不同类型Advice执行顺序

配置基础环境

  1. 依赖版本
  • Spring 版本为: 5.3.23
  • Spring Boot 版本为: 2.6.12
  • aspectjweaver 版本: 1.9.9.1
  1. 定义Spring Boot启动类
package sakura.springinaction;

@SpringBootApplication
@EnableAspectJAutoProxy
public class MySpringApplication {
	public static void main(String[] args) {
		SpringApplication.run(MySpringApplication.class, args);
	}
}
  1. 定义一个用于测试的Controller类
package sakura.springinaction.controller;

@Controller
@Slf4j
public class IndexController {
	@GetMapping("/time")
	@ResponseBody
	public String time() {
		LocalDateTime now = LocalDateTime.now();
		String nowTime = now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
		log.info("Current time: " + nowTime);
		return nowTime;
	}
}
  1. 定义一个声明式切面 Apsect1
@Slf4j
@Component
@Aspect
public class Aspect1 {

   // 定义 Point Cut 切面
   @Pointcut("execution(public * sakura.springinaction.controller.*.*(..))")
   public void controllerLayer() {
   }

   // 定义Advice

   @Before("controllerLayer()")
   private void beforeAdvice2() {
   	log.info("Aspect_1 # @Before");
   }

   @After("controllerLayer() && @annotation(getMapping)")
   private void afterAdvice1(GetMapping getMapping) {
   	log.info("Aspect_1 # @afterAdvice" + " path: " + Arrays.toString(getMapping.value()));
   }

   @AfterReturning(pointcut = "controllerLayer()", returning = "val")
   private void afterReturningAdvice(Object val) {
   	log.info("Aspect_1 # @AfterReturning" + " returnValue: " + val);
   }

   @AfterThrowing(pointcut = "controllerLayer()", throwing = "thrower")
   private void afterThrowingAdvice(Throwable thrower) {
   	log.info("Aspect_1 # @AfterThrowing" + " thrower: " + thrower.getClass().getName());
   }

   @Around("controllerLayer() && @annotation(getMapping)")
   private Object aroundAdvice(ProceedingJoinPoint pjp, GetMapping getMapping) throws Throwable {
   	// Around 前置处理
   	Stopwatch stopwatch = Stopwatch.createStarted();
   	log.info("Aspect_1 # @Around-Before" + " methodName: " + pjp.getSignature().getName() + ", path: " + Arrays.toString(getMapping.value()));
   	Object result = pjp.proceed();
   	// Around 后置处理
   	log.info("Aspect_1 # @Around-After" + " methodName: " + pjp.getSignature().getName() + ", runTime: " + stopwatch.elapsed(TimeUnit.NANOSECONDS));
   	return result;
   }

}

实验结果

在 发起请求(http://localhost:8080/time) 后,日志输出如图:
日志记录

结论

在同一个切面(Apsect)定义中对于同一个Join Point而言,不同类型的Advice执行先后顺序依次是:

  1. @Around 前置处理
  2. @Before
  3. @AfterReturning/@AfterThrowing
  4. @After
  5. @Around 后置置处理

优先级说明:

  • 对于进入Join PointAdvice而言(比如: @Around 前置处理,@Before),优先级越高,越先执行;
  • 对于从Join Point出来的Advice而言(比如: @Around 后置处理,@After),优先级越高,越后执行;
  • 优先级从高到低依次为: @Around, @Before,@After,@AfterReturning,@AfterThrowing
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇jdk线程池ThreadPoolExecutor优雅.. 下一篇每日算法之二叉搜索树的最近公共..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目