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
切面二:環繞返回通知
切面二:環繞最終通知

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM