spring自定義切面執行順序的方法

使用spring框架的時候,用aop需要控制自己寫的切面的順序,例如如下切面代碼:

@Aspect
@Order(-1) //會先掃描註解的值,如果註解的值找不到,再找getOrder()的值
public class AspectJOrderLow implements Ordered {

    @Pointcut("execution(* *.test(..))")
    public void testPointcut() {
    }

    @Before("testPointcut()")
    public void beforeTest() {
        System.out.println("trigger [before] in " + AspectJOrderLow.class.getName());
    }

    @Order(-100) //同一切點的同一類型通知方法,例如Before,這個Order註解沒用,根據方法字母序決定執行先後順序
    @Before("testPointcut()")
    public void beforeTest() {
        System.out.println("trigger [before] in " + AspectJOrderLow.class.getName());
    }
    
    @After("testPointcut()")
    public void afterTest() {
        System.out.println("trigger [after] in " + AspectJOrderLow.class.getName());
    }

    @Around("testPointcut()")
    public Object aroundTest(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("trigger [beforeAround] in " + AspectJOrderLow.class.getName());
        Object o = pjp.proceed();
        System.out.println("trigger [afterAround] in " + AspectJOrderLow.class.getName());
        return o;
    }

    @Override
    public int getOrder() {
        return 0; //這裏返回的執行的順序,數字越小,優先級越高範圍Integer
    }
}
@Aspect
public class AspectJOrderHigh implements Ordered {

    @Pointcut("execution(* *.test(..))")
    public void testPointcut() {
    }

    @Before("testPointcut()")
    public void beforeTest() {
        System.out.println("trigger [before] in " + AspectJOrderHigh.class.getName());
    }

    @After("testPointcut()")
    public void afterTest() {
        System.out.println("trigger [after] in " + AspectJOrderHigh.class.getName());
    }

    @Around("testPointcut()")
    public Object aroundTest(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("trigger beforeAround in " + AspectJOrderHigh.class.getName());
        Object o = pjp.proceed();
        System.out.println("trigger afterAround in " + AspectJOrderHigh.class.getName());
        return o;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
public class TestOrder {

    private String testStr = "testOrder";

    public String getTestStr() {
        return testStr;
    }

    public void setTestStr(String testStr) {
        this.testStr = testStr;
    }

    public void test() {
        System.out.println(this.testStr);
    }

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("aopOrder.xml");
        TestOrder bean = (TestOrder) ac.getBean("testOrder");
        bean.test();
    }
}

testOrder.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	   		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
			http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

    <!-- AOP配置 -->
    <aop:aspectj-autoproxy/>

    <bean class="com.stpice.spring.demo.aop.order.AspectJOrderHigh"/>
    <bean class="com.stpice.spring.demo.aop.order.AspectJOrderLow"/>
    <bean id="testOrder" class="com.stpice.spring.demo.aop.order.TestOrder"/>
</beans>

定義了兩個切面類,TestOrder是切面織入的目標類,testOrder.xml是配置文件。運行後打印出來如下的內容,可以看到高低優先級不同的切面中的before、after、around切面的執行順序如下。

trigger beforeAround in com.stpice.spring.demo.aop.order.AspectJOrderHigh
trigger [before] in com.stpice.spring.demo.aop.order.AspectJOrderHigh
trigger [beforeAround] in com.stpice.spring.demo.aop.order.AspectJOrderLow
trigger [before] in com.stpice.spring.demo.aop.order.AspectJOrderLow
testOrder
trigger [afterAround] in com.stpice.spring.demo.aop.order.AspectJOrderLow
trigger [after] in com.stpice.spring.demo.aop.order.AspectJOrderLow
trigger afterAround in com.stpice.spring.demo.aop.order.AspectJOrderHigh
trigger [after] in com.stpice.spring.demo.aop.order.AspectJOrderHigh

因爲目前在兩個切面AspectJOrderHighAspectJOrderLow中覆寫的getOrder方法中返回的是0,就是還沒有顯式的指定不同的順序,所以,根據跟蹤源碼,可以發現在order相同的情況下, 是根據切面類的名稱字母序進行優先級控制的,字母序越靠前,優先級越高。字母序的比較,首先將類名轉換爲字符串,然後調用StringcompareTo()方法,對兩個類名進行比對,決定切面的排序的。如果切面類使用了@Order註解或者是實現了Ordered接口,那麼可以在比對的時候自動調用getOrder()的方法,然後比較返回的值大小,值越小,優先級越高。同一個切面類中的方法,如果有多個不同的切入方式,例如@Around,@Before,@After,@AfterReturning,@AfterThrowing,那麼會先掃描出各個方法上的註解,對不同的方法按照上邊註解的順序進行排序,然後按照字母序進行排序,所以最終呈現出來的,同一個切面類中的不同切面方法的執行順序,就會呈現如上所示的狀態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章