Spring不同版本Aop执行顺序差异
前言
Spring升级过程过发现Spring4和Spring5版本之间的AOP差异是比较大的,
Spring4的执行顺序是:
正常情况: @Around前环绕通知–>@Before–>@Around后环绕通知–>@After–>@AfterReturning
异常情况:@Around前环绕通知–>@Before–>@After–>@AfterThrowing
Spring5的执行顺序是:
正常情况:@Around前环绕通知–>@Before–>@AfterReturning–>@After–>@Around后环绕通知
异常情况:@Around前环绕通知–>@Before–>@AfterThrowing–>@After
刨了Spring的版本修改记录发现在Spring-5.2.7.RELEASE版本调整了aop的执行顺序:
https://github.com/spring-projects/spring-framework/issues/25186
下面就撸代码测试一把:
Spring5的
maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
上代码
public interface EmployeeService {
public int fun(int x,int y);
}
@Service
public class EmployeeServiceImpl implements EmployeeService{
@Override
public int fun(int x, int y) {
int result = x / y;
System.out.println("业务代码被执行了");
return result;
}
}
@Aspect
@Component
public class EmployeeAspect {
@Before("execution(public int com.pandamig.aop.EmployeeServiceImpl.*(..))")
public void before() {
System.out.println("@Before");
}
@After("execution(public int com.pandamig.aop.EmployeeServiceImpl.*(..))")
public void after() {
System.out.println("@After");
}
@AfterReturning("execution(public int com.pandamig.aop.EmployeeServiceImpl.*(..))")
public void afterReturning() {
System.out.println("@AfterReturning");
}
@AfterThrowing("execution(public int com.pandamig.aop.EmployeeServiceImpl.*(..))")
public void afterThrowing() {
System.out.println("@AfterThrowing");
}
@Around("execution(public int com.pandamig.aop.EmployeeServiceImpl.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object retvalue = null;
System.out.println("@Around 前");
retvalue = proceedingJoinPoint.proceed();
System.out.println("@Around 后");
return retvalue ;
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class EmployeeServiceImplTest {
@Resource
EmployeeService employeeService;
@Test
public void funTest(){
System.out.println("Spring:"+SpringVersion.getVersion()+"--SpringBoot:"+ SpringBootVersion.getVersion());
System.out.println();
employeeService.fun(10,2);
}
}
上测试结果
Spring:5.2.8.RELEASE--SpringBoot:2.3.3.RELEASE
@Around 前
@Before
业务代码被执行了
@AfterReturning
@After
@Around 后
把pom中的Springboot版本修改为1.5.9.Release看看效果是什么样的:
Spring:4.3.13.RELEASE--SpringBoot:1.5.9.RELEASE
@Around 前
@Before
业务代码被执行了
@Around 后
@After
@AfterReturning
小结
Spring5的aop执行顺序更符合常规逻辑:
// @Around
public void test(){
try {
// @Before
// 业务代码
// @AfterReturning
}catch (Exception e){
// @AfterThrowing
}finally {
// @After
}
}
// @Around