Spring AOP学习笔记--Advice执行顺序

本文详细探讨了Spring AOP中Advice的执行顺序,包括在同一Aspect内的执行顺序和不同Aspect间的执行顺序。通过实例展示了如何通过Ordered接口调整不同Aspect的Advice执行优先级。

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

一、Advice执行顺序

如果多个Advice和同一个JointPoint连接,我们需要指明每一个Advice的执行顺序,那么我们就需要分两种情况讨论,

  • 第一种是如果Advice在同一个Aspect当中,那么执行的顺序是按照Advice在Aspect的声明顺序执行的。
  • 如果Advice在不同的Aspect当中,那么执行的顺序是需要将Aspect继承Ordered这个类,然后覆写getOrder方法

二、Advice在同一个Aspect中

AdviceOrder.java 在这个Aspect中我们指明了Pointcut和Advice的类型,我们可以看到,两个Before类型的Advice切入到了同一个JointPoint上,两个AfterReturning类型的Advice切入到了同一个JointPoint上。

package com.zbt.day04;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AdviceOrder {
    @Pointcut("execution(* com.zbt.day04.*.*(..))")
    public void methodPoint(){
    }
    @Before("methodPoint()")
    public void beforeAdviceI(){
        System.out.println("before advice I 执行了");
    }
    @Before("methodPoint()")
    public void beforeAdviceII(){
        System.out.println("before advice II 执行了");
    }

    @AfterReturning("methodPoint()")
    public void afterReturningI(){
        System.out.println("After Returning Advice I 执行了");
    }
    @AfterReturning("methodPoint()")
    public void afterReturningII(){
        System.out.println("After Returning Advice I 执行了");
    }
}

TargetClass.java 这是一个目标类,其中的sayHello方法是JointPoint

package com.zbt.day04;

public class TargetClass {
    public void sayHello(){
        System.out.println("Hello,What a good day!");
    }
}

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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:aspectj-autoproxy/>
    <bean id="adviceOrder" class="com.zbt.day04.AdviceOrder"></bean>
    <bean id="targetClass" class="com.zbt.day04.TargetClass"></bean>

</beans>

TestTargetClass.java 测试类

package com.zbt.day04;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAdvice {
    @Test
    public void testTargetClass(){
        ApplicationContext context = new ClassPathXmlApplicationContext("day04_config.xml");
        TargetClass targetClass = context.getBean("targetClass",TargetClass.class);
        targetClass.sayHello();
    }
}

测试结果

before advice I 执行了
before advice II 执行了
Hello,What a good day!
After Returning Advice I 执行了
After Returning Advice II 执行了

从结果我们可以看到,这个beforeAdviceI在beforeAdviceII之前执行,而afterReturningI在afterReturningII之前执行了,正好印证了我们之前所说的在同一个Aspect内,那么如果多个相同类型的Advice连接到同一个JointPoint上,此时执行的顺序就是按照Advice在Aspect中声明的顺序执行的。

三、Advice在不同的Aspect中

如果有多个Aspect的相同类型的Advice切入同一个JointPoint当中,如果我们想要指定这写Advice执行的顺序,因此我们的Aspect需要继承org.springframework.core.Ordered这个类。
AdviceOrderI.java 这个类是一个Aspect继承了Order方法,同时覆写了getOrder方法。切入com.zbt.day05中所有的方法。提供了一个BeforeAdvice和一个AfterAdvice,同时

package com.zbt.day05;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;

@Aspect
public class AdviceOrderI implements Ordered{
    @Pointcut("execution(* com.zbt.day05.*.*(..))")
    public void pointI(){
    }
    @Before("pointI()")
    public void beforeAdviceI(){
        System.out.println("AdviceOrderI 的 Before Advice I 执行了");
    }
    @AfterReturning("pointI()")
    public void afterReturningI(){
        System.out.println("AdviceOrderI 的 After Returning Advice I 执行了");
    }
    @Override
    public int getOrder() {
        return 20;
    }
}

AdviceOrderII.java同样也继承了Ordered类,最后

package com.zbt.day05;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;

@Aspect
public class AdviceOrderII implements Ordered{
    @Pointcut("com.zbt.day05.AdviceOrderI.pointI()")//复用Advice
    public void pointII(){}

    @Before("pointII()")
    public void beforeAdviceII(){
        System.out.println("AdviceOrderII 的 Before Advice II 执行了");
    }

    @AfterReturning("pointII()")
    public void afterReturningII(){
        System.out.println("AdviceOrderII 的 After Returning Advice II 执行了");
    }

    @Override
    public int getOrder() {
        return 10;
    }
}

TargetClass.java是一个目标类,sayHello是一个JointPoint

package com.zbt.day05;

public class TargetClass {
    public void sayHello(){
        System.out.println("Hello,What a good day!");
    }
}

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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <aop:aspectj-autoproxy/>
    <bean id="adviceOrderI" class="com.zbt.day05.AdviceOrderI"></bean>
    <bean id="adviceOrderII" class="com.zbt.day05.AdviceOrderII"></bean>
    <bean id="targetClass" class="com.zbt.day05.TargetClass"></bean>
</beans>

TestTargetClass测试类

package com.zbt.day05;

import com.zbt.day04.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestTargetClass {
    @Test
    public void testTargetClass(){
        ApplicationContext context = new ClassPathXmlApplicationContext("day05_config.xml");
        TargetClass targetClass = context.getBean("targetClass", TargetClass.class);
        targetClass.sayHello();
    }
}

输出结果

AdviceOrderII 的 Before Advice II 执行了
AdviceOrderI 的 Before Advice I 执行了
Hello,What a good day!
AdviceOrderI 的 After Returning Advice I 执行了
AdviceOrderII 的 After Returning Advice II 执行了

从结果我们也可以看如果我们的Ordered返回的order越小,那么这个Aspect的BeforeAdvice就会在前面执行,而AfterReturning类型的Advice就会在后面执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值