java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringAop切面执行顺序

SpringAop切面执行顺序实践

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

您可能感兴趣的文章:
阅读全文