Spring AOP 实战指南:从入门到精通(3)

米饭13小时前行业资讯7

3.3 @PointCut:

Spring 提供了 @PointCut 注解,把公共的切点表达式提取出来,需要用到时引用该切入点表达式即可,便于后续代码的维护。

@Aspect
@Slf4j
@Component
public class TestAspect {
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void pt(){}
    @Around("pt()")
    public Object demo(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("方法执行前执行");
        Object result = joinPoint.proceed();
        log.info("方法执行后执行");
        return result;
    }
}

当切点定义使用 private 修饰时,仅能在当前切面类中使用,当其他切面类也要使用当前切点定义时,就需要把 private 改为 public。引用方式为:全限定类名.方法名()。

@Slf4j
@Component
@Aspect
public class TestAspect2 {
    @Before("com.example.demo.aspect.TestAspect.pt()")
    public void doBefore() {
        log.info("执⾏ TestAspect2 -> Before ⽅法");
    }
}

3.4 切面优先级 @Order:

当我们在一个项目中,定义了多个切面类时,并且这些切面类的多个切入点都匹配到了同一个目标方法。当目标方法运行的时候,这些切面类中的通知方法都会执行,那么这几个通知方法的执行顺序是什么样的呢?

我们通过程序来进行验证。

@Slf4j
@Component
@Aspect
public class TestAspect2 {
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    private void pt(){}
    //前置通知
    @Before("pt()")
    public void doBefore() {
        log.info("执行 TestAspect2 -> Before 方法");
    }
    //后置通知
    @After("pt()")
    public void doAfter() {
        log.info("执行 TestAspect2 -> After 方法");
    }
}

@Aspect
@Component
@Slf4j
public class TestAspect3 {
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    private void pt(){}
    //前置通知
    @Before("pt()")
    public void doBefore() {
        log.info("执行 TestAspect3 -> Before 方法");
    }
    //后置通知
    @After("pt()")
    public void doAfter() {
        log.info("执行 TestAspect3 -> After 方法");
    }
}

@Aspect
@Component
@Slf4j
public class TestAspect4 {
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    private void pt(){}
    //前置通知
    @Before("pt()")
    public void doBefore() {
        log.info("执行 TestAspect4 -> Before 方法");
    }
    //后置通知
    @After("pt()")
    public void doAfter() {
        log.info("执行 TestAspect4 -> After 方法");
    }
}

运行上面程序:

cb19833aeabd9c7f63a21963145c3bf5.png

通过上述程序的运行结果,可以看出:


存在多个切面类时,默认按照切面类的类名字母排序:


@Before 通知:字母排名靠前的先执行。


@After 通知:字母排名靠前的后执行。


但这种方式不方便管理,我们的类名更多还是具备一定含义的。


Spring 给我们提供了一个新的注解,来控制这些切面通知的执行顺序:@Order。

@Slf4j
@Component
@Aspect
@Order(10)
public class TestAspect2 {
    //代码省略
}

@Aspect
@Component
@Slf4j
@Order(5)
public class TestAspect3 {
    //代码省略
}

@Aspect
@Component
@Slf4j
@Order(1)
public class TestAspect4 {
    //代码省略
}

运行程序:

36b3fca9c1995634a8524b640652fc6a.png

通过上述程序的运行结果,得出结论:

@Order 注解标识的切面类,执行顺序如下:

  • @Before 通知:数字越小先执行。

  • @After 通知:数字越大先执行。

@Order 的执行顺序可以抽象成下面这张图:

image-20241011084901893

本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!  

云掣基于多年在运维领域的丰富时间经验,编写了《云运维服务白皮书》,欢迎大家互相交流学习:

《云运维服务白皮书》下载地址:https://fs80.cn/v2kbbq

想了解更多大数据运维托管服务、数据库运维托管服务、应用系统运维托管服务的的客户,欢迎点击云掣官网沟通咨询:https://yunche.pro/?t=shequ


相关文章

linux之危险操作

在 Linux 中,某些命令可以对系统造成不可逆的影响,尤其是当以 root 用户(或使用 sudo)执行时。以下是一些不推荐轻易执行的高危命令,除非你非常清楚它们的作用和潜在的后果:rm -rf /...

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

【K8S系列】Kubernetes Pod节点CrashLoopBackOff 状态及解决方案详解【已解决】

在 Kubernetes 中,Pod 的状态为 CrashLoopBackOff 表示某个容器在启动后崩溃,Kubernetes尝试重启该容器,但由于持续崩溃,重启的间隔时间逐渐增...

【Docker】0.空间资源隔离

【Docker】0.空间资源隔离

NameSpacedd + option : 可以从标准输入或文件中读取数据,根据指定格式来转换数据,再输出到文件、设备或标准输出 --help 显...

MySQL运维之分库分表与读写分离

MySQL运维之分库分表与读写分离

分库分表1.介绍问题分析随着互联网以及移动互联网的发展,应用系统的数据量也是成指数式增长,若采用单数据库进行数据存储,存在以下性能瓶颈:IO瓶颈:热点数据太多,数据库缓存不足,产生大量磁盘IO,效率较...

Docker:容器化和虚拟化

Docker:容器化和虚拟化

虚拟化虚拟化是一种资源管理技术,它将计算机的各种实体资源(如CPU、内存、磁盘空间、网络适配器等)予以抽象、转换后呈现出来,并可供分割、组合为一个或多个电脑配置环境。这些资源的新虚拟部分是不受现有资源...

MyBatisPlus从零到一:快速入门与核心功能详解(6)

MyBatisPlus从零到一:快速入门与核心功能详解(6)

四、分页插件MybatisPlus 提供了很多的插件功能,进一步拓展其功能。目前已有的插件有:PaginationInnerInterceptor:自动分页TenantLineInnerInterce...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。