spring自定义切面执行顺序的方法

在Spring框架中,使用AOP时有时需要控制切面的执行顺序。通过设置`@Order`注解或者实现`Ordered`接口,可以指定切面的优先级。当未明确指定顺序时,Spring会按类名的字母顺序决定优先级。在切面类内部,同一类的不同切面方法,如`@Before`、`@After`、`@Around`,会先按注解顺序排列,再按字母序排序,从而确定最终的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值