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切面执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java使用DFA算法实现过滤多家公司自定义敏感字功能详解

    Java使用DFA算法实现过滤多家公司自定义敏感字功能详解

    这篇文章主要介绍了Java使用DFA算法实现过滤多家公司自定义敏感字功能,结合实例形式分析了DFA算法的实现原理及过滤敏感字的相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • Spring-AOP @AspectJ进阶之如何绑定代理对象

    Spring-AOP @AspectJ进阶之如何绑定代理对象

    这篇文章主要介绍了Spring-AOP @AspectJ进阶之如何绑定代理对象的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java实现双向循环链表

    Java实现双向循环链表

    这篇文章主要为大家详细介绍了Java实现双向循环链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10
  • 深入理解Spring Aop的执行顺序

    深入理解Spring Aop的执行顺序

    本文将结合实例代码,介绍Spring Aop的执行顺序,非常具有实用价值,需要的朋友可以参考下
    2021-06-06
  • SpringBoot 利用RestTemplate http测试

    SpringBoot 利用RestTemplate http测试

    这篇文章主要介绍了SpringBoot 利用RestTemplate http测试,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java守护线程和用户线程的区别

    Java守护线程和用户线程的区别

    这篇文章主要介绍了Java守护线程和用户线程的区别,用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程,下文更多详细内容需要的小伙伴可以参考一下
    2022-05-05
  • 用dom4j生成xml,去掉xml头的方法

    用dom4j生成xml,去掉xml头的方法

    今天小编就为大家分享一篇用dom4j生成xml,去掉xml头的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • Gateway集成Netty服务的配置加载详解

    Gateway集成Netty服务的配置加载详解

    这篇文章主要为大家介绍了Gateway集成Netty服务的配置加载详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Java利用剪贴板实现交换程序间数据的方法

    Java利用剪贴板实现交换程序间数据的方法

    这篇文章主要介绍了Java利用剪贴板实现交换程序间数据的方法,需要的朋友可以参考下
    2014-07-07
  • Spring Boot 3.0升级指南

    Spring Boot 3.0升级指南

    这篇文章主要为大家介绍了Spring Boot 3.0升级指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02

最新评论