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

米饭9个月前行业资讯548

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


相关文章

一个初级运维工程师对于运维工作的一些浅显认知

一个初级运维工程师对于运维工作的一些浅显认知

最近因为部门架构调整,之前工作做了交接,新的安排又没有确定,领导建议学习下JAVA开发,后续直接参与到研发工作中而不再负责运维工作。周围同事也都在说运维工作比较low,转研发会好一些。但是毕竟从毕业之...

Linux--多路转接之epoll

Linux--多路转接之epoll

epoll 是 Linux 下多路复用 I/O 接口 select/poll 的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统 CPU 利用率。它是 Linux 下多路复用 AP...

Docker:LXC容器操作实战

Docker:LXC容器操作实战

前言通过LXC来完成容器的创建、体会什么是容器。利用LXC容器技术来隔离特定的应用,提供虚拟执行环境,从而优化资源管理和部署效率。什么是LXC?LXC为Linux Container的简写,是一种可以...

微服务保护和分布式事务(3)

微服务保护和分布式事务(3)

1.3 请求限流:在簇点链路后面点击流控按钮,即可对其做限流配置:在弹出的菜单中填写:这样就把查询购物车列表这个簇点资源的流量限制在了每秒 6 个,也就是最大 QPS 为 6。1.4 线程隔离:限流可...

如何理解运维

如何理解运维

运维工程师(运营),负责维护并确保整个服务的高可用性,同时不断优化系统架构提升部署效率,优化资源利用率提高整体的投资回报率。运维工程师面对的最大挑战是大规模集群的管理问题,如何管理好几十万台服务器上的...

CMP?MSP?1+1才能大于2

CMP?MSP?1+1才能大于2

CMP与MSP都已经出现有一段时间了,而业界对于两个名词略有混淆,CMP和MSP到底是什么,能做什么,互相边界是什么,是互补还是互相竞争傻傻分不清楚。笔者试从自己十多年的云计算实践以及对于Gartne...

发表评论    

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