前言:之前听尚硅谷周阳阳哥讲课,说是spring5的aop执行顺序和spring4不一样了,并且选用了springboot2.3.10版本测试,结果确实变化了。但是,本人亲自测试以后发现自己使用的springboot2.2.2顺序并没有发生变化,为了弄清楚原因,特意查了下资料和官网,经过代码测试最后得出结果如下:
从spring 5.2.7.RELEASE开始(包括5.2.7),spring aop的执行顺序发生了变化。
测试代码:
public interface CommonService {
String targetMethod1(String name);
int targetMethod2(Integer num);
}
@Service
public class CommonServiceImpl implements CommonService{
@Override
public String targetMethod1(String name) {
System.out.println("======CommonServiceImpl targetMethod1======");
if(name==null || "".equals(name)){
throw new NullPointerException("name cannot be null");
}
return name;
}
@Override
public int targetMethod2(Integer num) {
System.out.println("======CommonServiceImpl targetMethod2======");
if(num==null){
throw new NullPointerException("num cannot be null");
}
return num;
}
}
@Component
@Aspect
public class MyAspect {
@Pointcut("execution(* org.example.service.CommonService.*(..))")
public void pointcutCommonService(){}
@Before("pointcutCommonService()")
public void before(){
System.out.println("=====before=====");
}
@After("pointcutCommonService()")
public void after(){
System.out.println("=====after=====");
}
@Around("pointcutCommonService()")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("=====around before=====");
proceedingJoinPoint.proceed();
System.out.println("=====around after=====");
}
@AfterReturning("pointcutCommonService()")
public void afterReturning(){
System.out.println("=====afterReturning=====");
}
@AfterThrowing("pointcutCommonService()")
public void afterThrowing(){
System.out.println("=====afterThrowing=====");
}
}
@EnableAspectJAutoProxy
@SpringBootApplication
public class TestSpringAopApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringAopApplication.class,args);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringAopTest {
@Resource
private CommonService commonService;
@Test
public void testSpringAop526(){
//springboot 2.2.7.RELEASE ==> spring 5.2.6.RELEASE
// 正常
commonService.targetMethod1("张三");
//=====around before=====
//=====before=====
//======CommonServiceImpl targetMethod1======
//=====around after=====
//=====after=====
//=====afterReturning=====
commonService.targetMethod1(null);
//=====around before=====
//=====before=====
//======CommonServiceImpl targetMethod1======
//=====after=====
//=====afterThrowing=====
//java.lang.NullPointerException: name cannot be null
}
@Test
public void testSpringAop527(){
//springboot 2.2.8.RELEASE ==> spring 5.2.7.RELEASE
// 正常
commonService.targetMethod1("张三");
//=====around before=====
//=====before=====
//======CommonServiceImpl targetMethod1======
//=====afterReturning=====
//=====after=====
//=====around after=====
commonService.targetMethod1(null);
//=====around before=====
//=====before=====
//======CommonServiceImpl targetMethod1======
//=====afterThrowing=====
//=====after=====
//java.lang.NullPointerException: name cannot be null
}
}
spring 5.2.7.RELEASE以前,spring aop的执行顺序为(本次选取springboot 2.2.7.RELEASE
对应 spring 5.2.6.RELEASE),具体注解的执行顺序经测试为:
//正常 //=====around before===== //=====before===== //======CommonServiceImpl targetMethod1====== //=====around after===== //=====after===== //=====afterReturning=====
//异常 //=====around before===== //=====before===== //======CommonServiceImpl targetMethod1====== //=====after===== //=====afterThrowing===== //java.lang.NullPointerException: name cannot be null
修改pom版本:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.7.RELEASE</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
从spring 5.2.7.RELEASE开始(包括5.2.7),spring aop的执行顺序为(本次选取springboot 2.2.8.RELEASE对应 spring 5.2.7.RELEASE),具体注解的执行顺序经测试为:
//正常 //=====around before===== //=====before===== //======CommonServiceImpl targetMethod1====== //=====afterReturning===== //=====after===== //=====around after=====
//异常 //=====around before===== //=====before===== //======CommonServiceImpl targetMethod1====== //=====afterThrowing===== //=====after===== //java.lang.NullPointerException: name cannot be null
修改pom版本:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.8.RELEASE</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
官网说明:
参考: spring4到spring5 AOP执行顺序的转变_wcherish7的博客-CSDN博客_spring4升级到spring5
https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-framework-reference/core.html#aop-ataspectj-advice-ordering
翻译一下意思就是从5.2.7开始,@After将会在任何@AfterReturning或者@AfterThrowing注解后调用。
补充:从5.2.7开始,@Around注解的around after正常结束时被放在了@After的后面(也就是最后面),异常结束时和之前的版本一样不会执行。