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,那么会先扫描出各个方法上的注解,对不同的方法按照上边注解的顺序进行排序,然后按照字母序进行排序,所以最终呈现出来的,同一个切面类中的不同切面方法的执行顺序,就会呈现如上所示的状态。

猜你喜欢

转载自blog.csdn.net/stpice/article/details/102733782