Spring-AOP-基于注解的AOP通知执行顺序
Spring-AOP-基于注解的AOP通知执行顺序
通知的选取规则
五大通知类型中,环绕通知功能最为强大,因为环绕通知,可以控制目标方法是否执行。
如果需要记录异常信息,使用异常通知。
其他通知,只能做记录工作,不能做处理,所以执行顺序其实对整个程序影响不大,没有必要太深究。
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注解指定先后顺序,数字越小,优先级越高,先进后出
可以使用@Order注解指定先后顺序,数字越小,优先级越高,先进后出 @Order(value = 1) @Aspect @Component public class BookServiceProxy {} @Order(value = 0) @Aspect @Component public class BookServiceProxy2 {} 切面二:环绕前置通知 切面二:@Before 切面一:环绕前置通知 切面一:@Before 目标方法执行 切面一:@AfterReturning 切面一:@After 切面一:环绕返回通知 切面一:环绕最终通知 切面二:@AfterReturning 切面二:@After 切面二:环绕返回通知 切面二:环绕最终通知