通知的选取规则
五大通知类型中,环绕通知功能最为强大,因为环绕通知,可以控制目标方法是否执行。
如果需要记录异常信息,使用异常通知。
其他通知,只能做记录工作,不能做处理,所以执行顺序其实对整个程序影响不大,没有必要太深究。
Spring版本不一样,通知执行顺序可能也会存在差异
下面以Spring4.0版本、Spring5.28版本进行测试
一、单个切面类
(1)@Before、@After、@AfterReturning、@AfterThrowing执行顺序
①Spring4.0
正常情况:@Before=====目标方法=====@After=====@AfterReturning
异常情况:@Before=====目标方法=====@After=====@AfterThrowing
②Spring5.28
正常情况:@Before=====目标方法=====@AfterReturning=====@After
异常情况:@Before=====目标方法=====@AfterThrowing=====@After
@Service public class BookService { public int add(int i,int j) { int result=i+j; System.out.println("目标方法执行"); //System.out.println(1/0); return result; } } @Aspect @Component public class BookServiceProxy { @Pointcut(value = "execution(* com.orz.spring.aop.BookService.add(..))") public void myPointCut(){} @Before(value = "myPointCut()") public void before() { System.out.println("@Before"); } @After(value = "myPointCut()") public void after() { System.out.println("@After"); } @AfterReturning(value = "myPointCut()") public void afterReturning() { System.out.println("@AfterReturning"); } @AfterThrowing(value = "myPointCut()") public void afterThrowing() { System.out.println("@AfterThrowing"); } } @Test public void test2() { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml"); BookService bookService = applicationContext.getBean("bookService", BookService.class); bookService.add(1,2); } Spring4.0 正常情况 @Before 目标方法执行 @After @AfterReturning 异常情况 @Before 目标方法执行 @After @AfterThrowing Spring5.28 正常情况 @Before 目标方法执行 @AfterReturning @After 异常情况 @Before 目标方法执行 @AfterThrowing @After
(2)@Around的执行顺序
@Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) { Object[] args = proceedingJoinPoint.getArgs(); Object result=null; try { //前置通知@Before System.out.println("环绕前置通知"); //目标方法执行 result = proceedingJoinPoint.proceed(args); //环绕返回通知@AfterReturning System.out.println("环绕返回通知"); } catch (Throwable throwable) { //环绕异常通知@AfterThrowing System.out.println("环绕异常通知"); throw new RuntimeException(throwable); } finally { //最终通知@After System.out.println("环绕最终通知"); } return result; }
①Spring4.0
正常情况:环绕前置=====目标方法执行=====环绕返回=====环绕最终
异常情况:环绕前置=====目标方法执行=====环绕异常=====环绕最终
②Spring5.28
正常情况:环绕前置=====目标方法执行=====环绕返回=====环绕最终
异常情况:环绕前置=====目标方法执行=====环绕异常=====环绕最终
@Service public class BookService { public int add(int i,int j) { int result=i+j; System.out.println("目标方法执行"); return result; } } @Aspect @Component public class BookServiceProxy { @Pointcut(value = "execution(* com.orz.spring.aop.BookService.add(..))") public void myPointCut(){} @Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) { Object[] args = proceedingJoinPoint.getArgs(); Object result=null; try { //前置通知@Before System.out.println("环绕前置通知"); //目标方法执行 result = proceedingJoinPoint.proceed(args); //环绕返回通知@AfterReturning System.out.println("环绕返回通知"); } catch (Throwable throwable) { //环绕异常通知@AfterThrowing System.out.println("环绕异常通知"); throw new RuntimeException(throwable); } finally { //最终通知@After System.out.println("环绕最终通知"); } return result; } } @Test public void test2() { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml"); BookService bookService = applicationContext.getBean("bookService", BookService.class); bookService.add(1,2); } Spring4.0 环绕前置通知 目标方法执行 环绕返回通知 环绕最终通知 异常情况 环绕前置通知 目标方法执行 环绕异常通知 环绕最终通知 Spring5.28 正常情况 环绕前置通知 目标方法执行 环绕返回通知 环绕最终通知 异常情况 环绕前置通知 目标方法执行 环绕异常通知 环绕最终通知
(3)五大通知执行顺序
①Spring4.0
正常情况:环绕前置=====@Before======目标方法执行=====环绕返回=====环绕最终=====@After=====@AfterReturning
异常情况:环绕前置=====@Before======目标方法执行=====环绕异常=====环绕最终=====@After=====@AfterThrowing
②Spring5.28
正常情况:环绕前置=====@Before=====目标方法执行=====@AfterReturning=====@After=====环绕返回=====环绕最终
异常情况:环绕前置=====@Before=====目标方法执行=====@AfterThrowing=====@After=====环绕异常=====环绕最终
@Service public class BookService { public int add(int i,int j) { int result=i+j; System.out.println("目标方法执行"); //System.out.println(1/0); return result; } } @Aspect @Component public class BookServiceProxy { @Pointcut(value = "execution(* com.orz.spring.aop.BookService.add(..))") public void myPointCut(){} @Before(value = "myPointCut()") public void before() { System.out.println("@Before"); } @After(value = "myPointCut()") public void after() { System.out.println("@After"); } @AfterReturning(value = "myPointCut()") public void afterReturning() { System.out.println("@AfterReturning"); } @AfterThrowing(value = "myPointCut()") public void afterThrowing() { System.out.println("@AfterThrowing"); } @Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint) { Object[] args = proceedingJoinPoint.getArgs(); Object result=null; try { //前置通知@Before System.out.println("环绕前置通知"); //目标方法执行 result = proceedingJoinPoint.proceed(args); //环绕返回通知@AfterReturning System.out.println("环绕返回通知"); } catch (Throwable throwable) { //环绕异常通知@AfterThrowing System.out.println("环绕异常通知"); throw new RuntimeException(throwable); } finally { //最终通知@After System.out.println("环绕最终通知"); } return result; } } @Test public void test2() { ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml"); BookService bookService = applicationContext.getBean("bookService", BookService.class); bookService.add(1,2); } Spring4.0 正常情况 环绕前置通知 @Before 目标方法执行 环绕返回通知 环绕最终通知 @After @AfterReturning 异常情况 环绕前置通知 @Before 目标方法执行 环绕异常通知 环绕最终通知 @After @AfterThrowing Spring5.28 正常情况 环绕前置通知 @Before 目标方法执行 @AfterReturning @After 环绕返回通知 环绕最终通知 异常情况 环绕前置通知 @Before 目标方法执行 @AfterThrowing @After 环绕异常通知 环绕最终通知
二、多个切面
①Spring4.0
正常情况:切面1环绕前置===切面1@Before===切面2环绕前置===切面2@Before===目标方法执行===切面2环绕返回===切面2环绕最终===切面2@After===切面2@AfterReturning===切面1环绕返回===切面1环绕最终===切面1@After===切面1@AfterThrowing
异常情况:切面1环绕前置===切面1@Before===切面2环绕前置===切面2@Before===目标方法执行===切面2环绕异常===切面2环绕最终===切面2@After===切面2@AfteThrowing===切面1环绕异常===切面1环绕最终===切面1@After===切面1@AfterThrowing
②Spring5.28
正常情况:切面1环绕前置===切面1@Before===切面2环绕前置===切面2@Before===目标方法执行===切面2@AfterReturning===切面2@After===切面2环绕返回===切面2环绕最终===切面1@AfterReturning===切面1@After===切面1环绕返回===切面1环绕最终
异常情况:切面1环绕前置===切面1@Before===切面2环绕前置===切面2@Before===目标方法执行===切面2@AfterThrowing===切面2@After===切面2环绕异常===切面2环绕最终===切面1@AfterThrowing===切面1@After===切面1环绕异常===切面1环绕最终
@Service
public class BookService {
public int add(int i,int j)
{
int result=i+j;
System.out.println("目标方法执行");
//System.out.println(1/0);
return result;
}
}
@Aspect
@Component
public class BookServiceProxy {
@Pointcut(value = "execution(* com.orz.spring.aop.BookService.add(..))")
public void myPointCut(){}
@Before(value = "myPointCut()")
public void before()
{
System.out.println("切面一:@Before");
}
@After(value = "myPointCut()")
public void after()
{
System.out.println("切面一:@After");
}
@AfterReturning(value = "myPointCut()")
public void afterReturning()
{
System.out.println("切面一:@AfterReturning");
}
@AfterThrowing(value = "myPointCut()")
public void afterThrowing()
{
System.out.println("切面一:@AfterThrowing");
}
@Around(value = "myPointCut()")
public Object myAround(ProceedingJoinPoint proceedingJoinPoint)
{
Object[] args = proceedingJoinPoint.getArgs();
Object result=null;
try {
//前置通知@Before
System.out.println("切面一:环绕前置通知");
//目标方法执行
result = proceedingJoinPoint.proceed(args);
//环绕返回通知@AfterReturning
System.out.println("切面一:环绕返回通知");
} catch (Throwable throwable) {
//环绕异常通知@AfterThrowing
System.out.println("切面一:环绕异常通知");
throw new RuntimeException(throwable);
} finally {
//最终通知@After
System.out.println("切面一:环绕最终通知");
}
return result;
}
}
@Test
public void test2()
{
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean2.xml");
BookService bookService = applicationContext.getBean("bookService", BookService.class);
bookService.add(1,2);
}
Spring4.0
正常情况
切面一:环绕前置通知
切面一:@Before
切面二:环绕前置通知
切面二:@Before
目标方法执行
切面二:环绕返回通知
切面二:环绕最终通知
切面二:@After
切面二:@AfterReturning
切面一:环绕返回通知
切面一:环绕最终通知
切面一:@After
切面一:@AfterReturning
异常情况
切面一:环绕前置通知
切面一:@Before
切面二:环绕前置通知
切面二:@Before
目标方法执行
切面二:环绕异常通知
切面二:环绕最终通知
切面二:@After
切面二:@AfterThrowing
切面一:环绕异常通知
切面一:环绕最终通知
切面一:@After
切面一:@AfterThrowing
Spring5.28
正常情况
切面一:环绕前置通知
切面一:@Before
切面二:环绕前置通知
切面二:@Before
目标方法执行
切面二:@AfterReturning
切面二:@After
切面二:环绕返回通知
切面二:环绕最终通知
切面一:@AfterReturning
切面一:@After
切面一:环绕返回通知
切面一:环绕最终通知
异常情况
切面一:环绕前置通知
切面一:@Before
切面二:环绕前置通知
切面二:@Before
目标方法执行
切面二:@AfterThrowing
切面二:@After
切面二:环绕异常通知
切面二:环绕最终通知
切面一:@AfterThrowing
切面一:@After
切面一:环绕异常通知
切面一:环绕最终通知
三、可以使用@Order注解指定先后顺序,数字越小,优先级越高,先进后出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|