【无标题】
2023-12-18 05:52:34
spring boot 多个切面的执行顺序分析
前言
spring boot 单个切面内,多个通知处理一个切点执行的顺序是怎样的?多个切面,多个通知处理一个切点的执行顺序又是怎样的?请看下文:
一、单个切面,多个通知处理一个切点的执行顺序分析
1.单个切面中,多个通知中没有重复的情况下:
2.单个切面中,多个通知中存在重复的情况下:
大体逻辑依然是:1.around > 2.before > 切点方法 > 3.around > 4.after > 5.afterReturning(or afterThrowing)
相同类型的通知根据通知方法名称的字典序执行
注: @Order 放在相同类型的通知根据方法上并不会改变同类通知的执行顺序
二、多个切面,多个通知处理一个切点的执行顺序分析
1. 各个切面内部,通知中没有重复的情况下:
注: 多个切面默认按照切面类名称的字典序执行,@Order注解放在切面类上可以改变切面的执行顺序,值越小,切面越先执行
2. 各个切面内部,通知中有重复的情况下:
整体类似于同心圆,局部与单个切面执行逻辑一致
整体执行顺序如下:
详细执行顺序如下:
注: 同一个切面内,相同类型的通知根据通知方法名称的字典序执行
三、验证代码
切面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。
文章来源:https://blog.csdn.net/qq_42282792/article/details/135053148
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!