Spring AOP 的实现和切点表达式的实现方式

 更新时间:2024年12月13日 09:56:26   作者:2的n次方_  
本文给大家介绍了Spring AOP的基本概念、通知类型、切点表达式和切面优先级,并通过示例代码展示了如何实现这些功能,感兴趣的朋友跟随小编一起看看吧

1. 快速入手

AOP:就是面相切面编程,切面指的就是某一类特定的问题,也可以理解为面相特定方法编程,例如之前使用的拦截器,就是 AOP 思想的一种应用,统一数据返回格式和统一异常处理也是 AOP 思想的实现方式

比如说需要统计每个方法执行的耗时,如果正常来写的话,需要在方法的开头和结尾来定义时间戳相减

如果有很多方法都需要计算的话,总不能每个方法都写这些重复的代码吧,接下来看通过使用 AOP 思想是如何实现的

首先需要添加对应的依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后需要添加@Component注解,

@Slf4j
@Aspect
@Component
public class TimeRecordAspect {
    @Around("execution(* com.example.springbook.controller.*.*(..))")
    public Object timeRecord(ProceedingJoinPoint pjt){
        //记录开始时间
        long start = System.currentTimeMillis();
        //执行目标方法
        Object o = null;
        try {
            o = pjt.proceed();
        } catch (Throwable e){
            throw new RuntimeException(e);
        }
        log.info(pjt.getSignature() + "执行耗时:" + (System.currentTimeMillis() - start));
        return o;
    }
}

再去调用接口的话就会计算出来对应方法消耗的时间

来简单分析一下上面的代码:

2. 通知类型

Spring AOP 的通知类型有以下几种

・@Around:环绕通知,在目标方法前、后都被执行。
・@Before:前置通知,在目标方法前被执行。
・@After:后置通知,在目标方法后被执行,无论是否有异常都会执行。
・@AfterReturning:返回后通知,在目标方法后被执行,有异常不会执行。
・@AfterThrowing:异常后通知,发生异常后执行。

接下来同时测试一下这些通知类型,

来看一下接口正常返回的情况下的执行顺序

再来看接口发生异常的情况下的执行顺序:

从上面的结果上就可以看出,Around 可以完成其他类型的功能

需要注意的是:

  • @Around 环绕通知需要调用 ProceedingJoinPoint.proceed () 来让原始方法执行,其他通知不需要考虑目标方法执行。
  • @Around 环绕通知方法的返回值,必须指定为 Object,来接收原始方法的返回值,否则原始方法执行完毕,是获取不到返回值的。

3. @Pointcut

在上面的代码中还存在一个问题,每次写一个方法都需要写一个切点表达式,如果说更换切点的话,那么所有的切点表达式都要修改一下,就可以通过@Pointcut 注解,把公共的切点表达式提取出来,需要用到时引用该切点表达式即可

这样提取出来,其他方法想要调用直接写上方法名称即可,和定义的常量类似,那么同一个类下可以直接调用,如果是不同的类的话需要把全限定名写上,并写明是 xx 类的 xx 方法

@Around("com.example.springaop.aspect.AspectDemo.pt()")

执行之后也是生效了

但是如果定义时设置为了 private 的话其他类就不能执行了

@Pointcut("execution(* com.example.springaop.controller.*.*(..))")
private void pt(){
}

4. 切面优先级

当在一个项目中定义了多个切面类时,并且这些切面类的多个切入点都匹配到了同一个目标方法,那么目标方法执行的时候,这些切面类中的通知方法都会执行,那么这时就会有一个优先级,哪个切面类先执行

通过测试发现,执行的顺序也是类似于一个切面的

关于切面类的执行顺序,默认是按照类名的字典序来执行的

可以@Order注解通过来修改优先级

这样 AspectDemo2 的优先级就变为最高的了,就先执行,也就是数字越大优先级越高

5. 切点表达式

5.1. execution 表达式

访问修饰符和异常可以省略

  • * 表示通配符,匹配任意字符,不过只能匹配一个元素(即只能匹配任意一种返回类型,包名,类名,方法或者方法参数),一层包使用一个 *
  • ' . . ' 表示匹配多个连续的任意符号,可以通配任意层级的包,或者任意类型,任意个数的参数,使用 .. 配置包名,表示此包以及此包下的所有子包

来看具体示例:

表示匹配 TestController 下的 public 修饰,返回类型为 String 方法名为 t1,无参方法

如果省略访问修饰符,表示匹配 public 修饰或者 protected 修饰的方法

表示匹配所有返回类型

如果再把方法名设为 * 表示所有方法,上面就是匹配该类下的所有无参方法

如果设为 .. 就表示所有方法,无论有参还是无参都能匹配

表示 controller 包下的所有类的所有方法都匹配

表示 com 下类名为 TestController 的所有方法

表示 demo 下的所有包的所有类的所有方法 5.2. @annotation

使用 execution 表达式匹配的方法都是具有一定规律的,比如 xx 包的 xx 类的 xx 方法,那么如果没有规律可循的话就需要使用 @annotation 注解了

首先,可以通过自定义注解的方式,自定义注解的创建需要选择 @Annotation

@Retention(RetentionPolicy.RUNTIME) //注解的有效阶段
@Target({ElementType.METHOD}) //表示方法注解
public @interface TimeRecord {
}

然后在原来计时的方法上来使用 @annotation 来指明要使用的注解

接下来只要是添加了自定义的注解都会执行这里的方法

通过这种方式就实现了想要给哪个方法生效就直接加上注解就可以了

除了自定义注解,其他现存的注解也是可以这样使用的

例如,可以把@RequestMapping的路径写在@annotation里,就表示只要加了@RequestMapping的方法都可以生效

到此这篇关于Spring AOP 的实现和切点表达式的实现方式的文章就介绍到这了,更多相关Spring AOP 切点表达式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java中的Filter使用示例详解

    java中的Filter使用示例详解

    Filter是JavaWeb开发中实现全局逻辑控制的核心工具,通过灵活配置拦截路径和类型,可高效完成编码转换、权限校验、日志记录等通用功能,这篇文章主要介绍了java中的Filter使用详解,需要的朋友可以参考下
    2025-05-05
  • 基于Spring p标签和c标签注入方式

    基于Spring p标签和c标签注入方式

    这篇文章主要介绍了Spring p标签和c标签注入方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Springboot @Value获取值为空问题解决方案

    Springboot @Value获取值为空问题解决方案

    这篇文章主要介绍了Springboot @Value获取值为空问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java中notify和notifyAll的区别及何时使用

    Java中notify和notifyAll的区别及何时使用

    本文主要介绍了Java中notify和notifyAll的区别及何时使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Struts2实现文件上传功能实例解析

    Struts2实现文件上传功能实例解析

    这篇文章主要介绍了Struts2实现文件上传功能实例解析,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-01-01
  • mybatis中映射文件include标签的应用

    mybatis中映射文件include标签的应用

    这篇文章主要介绍了mybatis中映射文件include标签的应用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Spring详解使用注解开发流程

    Spring详解使用注解开发流程

    这篇文章主要为大家详细介绍了Spring如何使用注解开发,文中的示例代码讲解详细,对我们学习或工作有一定帮助,需要的可以参考一下
    2022-05-05
  • Java 基础之内部类详解及实例

    Java 基础之内部类详解及实例

    这篇文章主要介绍了 Java 基础之内部类详解及实例的相关资料,需要的朋友可以参考下
    2017-03-03
  • 关于dubbo的超时处理及重试原则

    关于dubbo的超时处理及重试原则

    这篇文章主要介绍了关于dubbo的超时处理及重试原则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 在Mac OS上安装Java以及配置环境变量的基本方法

    在Mac OS上安装Java以及配置环境变量的基本方法

    这篇文章主要介绍了在Mac OS上安装Java以及配置环境变量的基本方法,包括查看所安装Java版本的方法,需要的朋友可以参考下
    2015-10-10

最新评论