一. 概述
-
本文主要讲述以下几点
- 单AOP切面时,各通知方法的执行顺序。
- 多AOP切面时,多切面的执行顺序和各通知方法的执行顺序。
二. 讲述
1. 单切面中各通知方法的执行顺序
单切面中各通知方法执行顺序·总结
- spring aop就是一个同心圆,以要执行的方法为圆心。从最外层按照依次执行切面的@Around方法,@Before方法。然后执行method方法,最后再依次执行@After、@AfterReturning方法。
- 图示
![]()
- 代码示例
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Aop1 {
}
@Component
@Aspect
@Slf4j
@Order(1)
public class Aop1Aspect {
@Pointcut("@annotation(com.zijikanwa.ssmspringboottest.manager.aop.Aop1)")
private void pointCutMethod() {
}
//声明前置通知
@Before("pointCutMethod()")
public void doBefore(JoinPoint point) {
System.out.println("Aop1Aspect:doBefore");
return;
}
//声明后置通知
@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
System.out.println("Aop1Aspect:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
System.out.println("Aop1Aspect:doAfterThrowing");
}
//声明最终通知
@After("pointCutMethod()")
public void doAfter() {
System.out.println("Aop1Aspect:doAfter");
}
//声明环绕通知
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Aop1Aspect:doAround1");
Object obj = pjp.proceed();
System.out.println("Aop1Aspect:doAround2");
return obj;
}
}
@Component
public class TEst {
@Aop1
public void testAop(){
System.out.println("testAop");
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TestApplication.class })
@EnableAutoConfiguration
class SsmspringboottestApplicationTests {
@Test
public void test(){
tEst.testAop();
}
}
- 执行结果
Aop1Aspect:doAround1
Aop1Aspect:doBefore
testAop
Aop1Aspect:doAround2
Aop1Aspect:doAfter
Aop1Aspect:doAfterReturning
2. 多切面中各通知方法的执行顺序
多切面各通知方法的执行顺序·总结
- 多切面的执行顺序:按照切面给定的order执行,order越小越先执行,但最先执行的最后结束。
- 多切面中各通知方法的执行顺序:与单切面类似。spring aop就是一个同心圆,以要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行@Around方法,@Before方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行@After、@AfterReturning方法。
- 图示
![]()
- 代码示例:在AOP1的基础上增加AOP2
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Aop2 {
}
@Component
@Aspect
@Slf4j
@Order(2)
public class Aop2Aspect {
@Pointcut("@annotation(com.zijikanwa.ssmspringboottest.manager.aop.Aop2)")
private void pointCutMethod() {
}
//声明前置通知
@Before("pointCutMethod()")
public void doBefore(JoinPoint point) {
System.out.println("Aop2Aspect:doBefore");
return;
}
//声明后置通知
@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
public void doAfterReturning(JoinPoint point, Object returnValue) {
System.out.println("Aop2Aspect:doAfterReturning");
}
//声明例外通知
@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
public void doAfterThrowing(Exception e) {
System.out.println("Aop2Aspect:doAfterThrowing");
}
//声明最终通知
@After("pointCutMethod()")
public void doAfter() {
System.out.println("Aop2Aspect:doAfter");
}
//声明环绕通知
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Aop2Aspect:doAround1");
Object obj = pjp.proceed();
System.out.println("Aop2Aspect:doAround2");
return obj;
}
}
@Component
public class TEst {
@Aop1
@Aop2
public void testAop(){
System.out.println("testAop");
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { TestApplication.class })
@EnableAutoConfiguration
class SsmspringboottestApplicationTests {
@Test
public void test(){
tEst.testAop();
}
}
- 执行结果
Aop1Aspect:doAround1
Aop1Aspect:doBefore
Aop2Aspect:doAround1
Aop2Aspect:doBefore
testAop
Aop2Aspect:doAround2
Aop2Aspect:doAfter
Aop2Aspect:doAfterReturning
Aop1Aspect:doAround2
Aop1Aspect:doAfter
Aop1Aspect:doAfterReturning
3. 多切面的通知方法中抛出异常
-
AOP1中
@Around
注解的方法抛出异常:执行@After和@AfterThrowing,然后抛出异常。
@Component
@Aspect
@Slf4j
@Order(1)
public class Aop1Aspect {
@Around("pointCutMethod()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Aop1Aspect:doAround1");
int i = 1 / 0; // java.lang.ArithmeticException: / by zero
Object obj = pjp.proceed();
System.out.println("Aop1Aspect:doAround2");
return obj;
}
}
- 运行结果
Aop1Aspect:doAround1
Aop1Aspect:doAfter
Aop1Aspect:doAfterThrowing
java.lang.ArithmeticException: / by zero
- Method方法抛出异常:依次执行多个切面的@After和@AfterThrowing
@Component
public class TEst {
@Aop1
@Aop2
public void testAop(){
System.out.println("testAop"); // 可以执行到
int i = 1 / 0;
System.out.println("testAop---"); //执行不到
}
}
- 执行结果
Aop1Aspect:doAround1
Aop1Aspect:doBefore
Aop2Aspect:doAround1
Aop2Aspect:doBefore
testAop
Aop2Aspect:doAfter
Aop2Aspect:doAfterThrowing
Aop1Aspect:doAfter
Aop1Aspect:doAfterThrowing
java.lang.ArithmeticException: / by zero
-
AOP1中
@After
注解的方法抛出异常:执行@After抛出异常前的部分和@AfterThrowing,然后抛出异常。
@Component
@Aspect
@Slf4j
@Order(1)
public class Aop1Aspect {
@After("pointCutMethod()")
public void doAfter() {
System.out.println("Aop1Aspect:doAfter"); // 可以执行到
int i = 1 / 0;
System.out.println("Aop1Aspect:doAfter----"); //执行不到
}
}
- 执行结果
Aop1Aspect:doAround1
Aop1Aspect:doBefore
Aop2Aspect:doAround1
Aop2Aspect:doBefore
testAop
Aop2Aspect:doAround2
Aop2Aspect:doAfter
Aop2Aspect:doAfterReturning
Aop1Aspect:doAround2
Aop1Aspect:doAfter
Aop1Aspect:doAfterThrowing
java.lang.ArithmeticException: / by zero
参考资料
版权声明:本文为zijikanwa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。