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
View Code

(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

正常情况
环绕前置通知
目标方法执行
环绕返回通知
环绕最终通知

异常情况
环绕前置通知
目标方法执行
环绕异常通知
环绕最终通知
View Code

(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
环绕异常通知
环绕最终通知
View Code

 

二、多个切面

 

 

   ①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
切面一:环绕异常通知
切面一:环绕最终通知
View Code

三、可以使用@Order注解指定先后顺序,数字越小,优先级越高先进后出

 

可以使用@Order注解指定先后顺序,数字越小,优先级越高,先进后出
@Order(value = 1)
@Aspect
@Component
public class BookServiceProxy {}

@Order(value = 0)
@Aspect
@Component
public class BookServiceProxy2 {}

切面二:环绕前置通知
切面二:@Before
切面一:环绕前置通知
切面一:@Before
目标方法执行
切面一:@AfterReturning
切面一:@After
切面一:环绕返回通知
切面一:环绕最终通知
切面二:@AfterReturning
切面二:@After
切面二:环绕返回通知
切面二:环绕最终通知

 

  

 

posted @ 2020-10-24 15:51  orz江小鱼  阅读(5190)  评论(0编辑  收藏  举报