SpringAop切面执行顺序实践

 更新时间:2026年04月22日 08:31:08   作者:A沐风001  
本文介绍Spring AOP中自定义切面与内置切面的执行顺序控制方法,通过@Order注解设置切面优先级,确保业务逻辑正确执行,感兴趣的可以了解一下

用过SpringAop的人都知道,这玩意是非常的强大,可以实现我们很多横切面的功能,包括Spring自己的很多东西,比如事务(@Transactional)和缓存(@Cacheable)等功能的实现都是依赖于切面,那么一个方法被多个切面注解修饰后,切面的执行顺序到底是什么样的?如果改变Spring里已有切面的执行顺序,我们下面来一一实践一下。

一、自定义切面的执行顺序

定义两个切面注解@AopOne @AopTwo

写两个切面的逻辑

package chen.huai.jie.springboot.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * @author chenhj_sh
 */
@Slf4j
@Aspect
@Component
@Order(value = 20)
public class AopOneAspect {
    /**
     * @Description 定义切入点
     */
    @Pointcut(value = "@annotation(chen.huai.jie.springboot.aop.annotation.AopOne)")
    public void pointCut() {
    }
    /**
     * 环绕通知
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("切面1执行前");
        Object result = joinPoint.proceed();
        log.info("切面1执行后");
        return result;
    }
}
package chen.huai.jie.springboot.aop.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * @author chenhj_sh
 */
@Slf4j
@Aspect
@Component
@Order(value = 11)
public class AopTwoAspect {
    /**
     * @Description 定义切入点
     */
    @Pointcut(value = "@annotation(chen.huai.jie.springboot.aop.annotation.AopTwo)")
    public void pointCut() {
    }
    /**
     * 环绕通知
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("切面2执行前");
        Object result = joinPoint.proceed();
        log.info("切面2执行后");
        return result;
    }
}

方法执行:

package chen.huai.jie.springboot.aop.service;
import chen.huai.jie.springboot.aop.annotation.AopOne;
import chen.huai.jie.springboot.aop.annotation.AopTwo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
 * @author chenhuaijie
 */
@Slf4j
@Service
public class AopService {
    @AopOne
    @AopTwo
    public void aop() {
        log.info("执行业务逻辑");
    }
}

执行结果:

因为切面2的order为11,比切面1的order要小,所以切面2先执行,注意,切面的执行其实是一个同心圆模样,先执行的后结束,如下图:

二、自定义切面和Spring内置切面的执行顺序

除了上述我们自定义的切面注解外,很多时候我们自定义的注解可能会跟Spring里已经做好的注解一起使用,比如:我做了一个分布式锁的注解@DistributedLock,它可能会跟@Transactional @Cacheable注解一起使用.

跟事务注解一起使用的时候,我们希望分布式锁注解要早于事务注解执行,晚于事务注解结束。

跟缓存注解一起使用的时候,为了防止缓存击穿,我们需要缓存注解优先于分布式锁注解执行。

怎么做到呢?怎么改变Spring内置的一些切面的执行逻辑呢?如下:

@EnableCaching(order = 10)
@EnableTransactionManagement(order  = 15)

这两个注解里的orderz字段可以改变各自切面的执行顺序,可以满足我们的要求。

举例自定义注解和事务注解:

事务优先于自定义注解执行:

事务晚于自定义注解执行: 

总结:

到此这篇关于SpringAop切面执行顺序实践的文章就介绍到这了,更多相关SpringAop切面执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring创建BeanDefinition之路径扫描详解

    Spring创建BeanDefinition之路径扫描详解

    这篇文章主要介绍了Spring创建BeanDefinition之路径扫描方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Java如何自定义类数组的创建和初始化

    Java如何自定义类数组的创建和初始化

    这篇文章主要介绍了Java如何自定义类数组的创建和初始化,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java原子操作CAS原理解析

    Java原子操作CAS原理解析

    这篇文章主要介绍了Java原子操作CAS原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 详解Java 中的函数式接口

    详解Java 中的函数式接口

    这篇文章主要为大家介绍了Java中的函数式接口,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助<BR>
    2021-12-12
  • Jenkins+git+maven+tomcat自动打包部署全过程

    Jenkins+git+maven+tomcat自动打包部署全过程

    文章介绍了如何在CentOS 7系统上配置网络和防火墙,安装和配置Jenkins、Git、Maven和Tomcat,以及如何进行多分支构建和配置Jenkins触发器,文章还解决了在Spring Boot项目、Maven打包和Tomcat启动过程中遇到的一些常见问题
    2025-12-12
  • java截取网页图片的方法

    java截取网页图片的方法

    这篇文章主要介绍了java截取网页图片的方法,涉及java调用第三方控件实现截图的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • 在lambda中使用外部变量的一些心得分享

    在lambda中使用外部变量的一些心得分享

    这篇文章主要介绍了在lambda中使用外部变量的一些心得,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • SpringBoot实现redis延迟队列的示例代码

    SpringBoot实现redis延迟队列的示例代码

    延时队列场景在我们日常业务开发中经常遇到,它是一种特殊类型的消息队列,本文就来介绍一下SpringBoot实现redis延迟队列的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • 解读nacos获取配置文件的大致过程

    解读nacos获取配置文件的大致过程

    这篇文章主要介绍了nacos获取配置文件的大致过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Spring AI集成DeepSeek的详细步骤

    Spring AI集成DeepSeek的详细步骤

    DeepSeek 作为一款卓越的国产 AI 模型,越来越多的公司考虑在自己的应用中集成,对于 Java 应用来说,我们可以借助 Spring AI 集成 DeepSeek,非常简单方便,本文给大家介绍了Spring AI集成DeepSeek的详细步骤,需要的朋友可以参考下
    2025-02-02

最新评论