SpringAop切面执行顺序实践

本文介绍Spring AOP中自定义切面与内置切面的执行顺序控制方法,通过@Order注解设置切面优先级,确保业务逻辑正确执行。

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

用过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字段可以改变各自切面的执行顺序,可以满足我们的要求。

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

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

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

总结:

记录开发过程中的点点滴滴,与大家一起成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值