Spring AOP 快速入门

news2024/11/15 15:56:42

文章目录

    • 一. 什么是Spring AOP
    • 二. 为什么要学习Spring AOP
    • 三. 学习 Spring AOP
      • 3.1 AOP 的组成
        • 3.1.1 切面 (Aspect)
        • 3.1.2 切点 (Pointcut)
        • 3.1.3 通知 (advice)
        • 3.1.4 连接点(Joinpoint)
      • 3.2 实现 Spring AOP
        • 1. 添加 Spring Boot 的 AOP 框架
        • 2. 创建切面
        • 3. 创建切点
        • 4. 创建通知
        • 5. 创建链接点
        • 6. 切点表达式说明
      • 3.3 Spring AOP 实现原理
    • 总结

一. 什么是Spring AOP

AOP(Aspect Oriented Programming): 面向切面编程 , 它是一种思想 , 提供了一种基于切面编程的方式来对应用程序进行模块化和横向切割的方法 , 是对某一类事情的集中处理. 例如用户登录权限的效验 , 没学 AOP 之前 , 我们所有需要判断用户登录页面的方法 , 都要各自实现或调用用户验证的方法 , 这样会导致代码冗余维护成本高 , 而使用 Spring AOP 之后 , 我们只需定义一个切面 , 通过在切面中编写代码实现用户的登录验证 , 具体实现步骤是在切面中定义切点(Pointcut)和通知(Advice),切点指定需要拦截的方法,通知则指定需要在拦截方法前、后或者异常抛出时执行的代码 , 所有需要判断用户登录页面的方法就全部实现用户登录验证了 , 无需在每个方法中都实现用户登录验证.

简而言之 , AOP 是一种思想 , Spring AOP 是一个框架 , 提供了一种对 AOP 思想的实现 , 它们的关系和 loC 和 DI 类似.


二. 为什么要学习Spring AOP

想象一个场景 , 我们做后台系统时 , 除了注册和登录等几个功能无需做用户登录验证之外 , 其他几乎所有页面的 Controller 都需要先验证用户的登录状态 , 那么此时怎么处理呢?

之前的处理方式是所有的 Controller 都写一遍用户登录验证 , 然而当实现的功能越来越复杂 , 那么代码的冗余会越来越多 , 导致代码的可维护性变得非常差 , 那么如果能将这些冗余的代码统一处理 , 工作者只需专注于当前业务 , 开发效率就会大大增加. 因此对于这种功能统一 , 且使用地方较多的功能 , 就可以考虑 AOP 统一处理了.

除了统一用户登录验证之外 , AOP 还可以实现:

  • 统一日志记录
  • 统一方法执行时间统计
  • 统一返回格式设置
  • 统一的异常处理
  • 事务的开启和提交等

也就是说 AOP 可以扩充多个对象的某个能力 , 所以 AOP 可以说是 OOP (Objec Oriented Programming ) 面向对象编程的补充.


三. 学习 Spring AOP

3.1 AOP 的组成

3.1.1 切面 (Aspect)

切面(Aspect) 由切点(Pointcut) 和通知(Advice) 组成 , 而某一方面的具体内容就是一个切面 , 比如用户的登录判断就是一个切面 , 简而言之 , 切面就是一个特殊的类 , 里面包含了切点和通知.

3.1.2 切点 (Pointcut)

定义一个拦截规则 , 指在应用程序中需要拦截的方法集合,可以使用表达式或者正则表达式等方式进行定义。切点是一个抽象的概念,它并不代表具体的方法,而是代表一组方法,这些方法需要被拦截并执行通知。

3.1.3 通知 (advice)

执行 AOP 具体的业务逻辑 , 指在切点上执行的操作。通知可以在切点执行前、执行后、抛出异常时执行,以便实现不同的功能需求。

通知包括以下几种类型:

  • 前置通知(Before advice):在切点执行前执行的通知。

  • 后置通知(After advice):在切点执行后执行的通知,不管切点执行成功或者失败都会执行。

  • 返回通知(After returning advice):在切点执行成功后执行的通知。

  • 异常通知(After throwing advice):在切点抛出异常后执行的通知。

  • 环绕通知(Around advice):在切点执行前后都可以执行的通知,可以控制切点的执行。

3.1.4 连接点(Joinpoint)

所有可能触发切点的点就叫做连接点 , 指在应用程序中实际执行的方法,即切点所定义的方法的实际执行过程。连接点是一个具体的概念,它代表了程序中的一个具体的执行点,例如方法的调用、异常抛出、字段的访问等

AspectJ 支持三种通配符

*****: 匹配任意字符串 , 只匹配一个元素 (包 , 类 , 方法 , 方法参数)

: 匹配任意字符 , 可以匹配多个元素 , 在表示类时 , 必须和 * 联合使用

+: 表示按类型匹配指定类的所有类 , 必须跟在类名后面 , 如 com.cad.Car+ , 表示继承该类的所有子类包括本身

切点表达式由切点函数组成 , 其中 execution() 是最常用的切点函数 , 用来匹配函数 , 语法为:

execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

image-20230513211744233

3.2 实现 Spring AOP

1. 添加 Spring Boot 的 AOP 框架

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Tips: 虽然 Spring 框架内置了原生 AOP , 但由于我们目前是 SpringBoot 项目 , 所以需要添加 SpringBoot 框架的 AOP.

image-20230513200644222

2. 创建切面

//创建切面
@Aspect//表明此类为一个切面
@Component
public class UserAOP {

}

3. 创建切点

@Aspect
@Component
public class UserAOP {
//    定义切点 , 此处使用 AspectJ 语法 (配置拦截规则)
    @Pointcut("execution(* com.example.demo.controller.UserController.*(..)")
    public void pointcut(){
        
    }
}

4. 创建通知

//创建切面
@Aspect
@Component
public class UserAOP {
//    定义切点 , 此处使用 AspectJ 语法 (配置拦截规则)
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut(){
    }
//    前置通知
    @Before("pointcut()")
    public void doBefore(){
        System.out.println("执行了前置通知: " + LocalDateTime.now());
    }
//    后置通知
    @After("pointcut()")
    public void doAfter(){
        System.out.println("执行流后置通知:" + LocalDateTime.now());
    }
//    环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("开始执行环绕通知");
        Object obj = joinPoint.proceed();
        System.out.println("结束执行环绕通知");
        return obj;
    }
}

5. 创建链接点

@RestController
public class UserController {
    @RequestMapping("/user/sayhi")
    public String sayhi(){
        System.out.println("执行了 sayhi 方法");
        return "hi springboot aop";
    }
}

6. 切点表达式说明

AspectJ 支持三种通配符

*: 匹配任意字符 , 只匹配一个元素 (包 , 类 , 方法 , 方法参数)

… : 匹配任意字符 , 匹配多个元素 , 在表示类时必须和 * 连用.

+: 表示按照类型匹配指定类的所有类 , 必须跟在类名之后 , 如 com.cad.Car+ , 表示继承该类的所有子类包括本身.

切点表达式由切点函数组成 , 其中 execution() 就是常见的切点函数 , 用来匹配方法 , 语法为:

execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

修饰符和异常可以省略

表达式示例

  • execution(* com.example.demo.UserController.*(…)) 匹配UserController 类里的所有方法
  • execution(* com.example.demo.UserController+.*(…)) 匹配该类的子类包括该类的所有方法

3.3 Spring AOP 实现原理

Spring AOP 是构建在动态代理基础上 , 因此 Spring 对 AOP 的支持局限于方法级别的拦截.

Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理. 默认情况下 , 实现了接口的类 , 使用 AOP 会基于 JDK 生成动态代理类 , 没有实现接口的类 , 会基于 CGLIB 生成代理类.

织入(Weaving): 代理的生成时机

织入就是把切面应用到目标对象并创建新的代理的过程 , 切面在指定的连接点被织入到目标对象中.

在目标对象的生命周期里有多个点可以织入:

  • 编译期: 切面在目标类编译时被织入. AspectJ 的织入编译器就是以这种方式织入切面的. 例如 lombok
  • 类加载期: 切面在目标类加载到 JVM 时被织入. 这种方式需要特殊的类加载器(ClassLoader). 它可以在目标类被引入应用之前增强该目标类的字节码.
  • 运行期: 切面在应用运行的某一时刻被织入. 一般情况下 , 在织入切面时 , AOP 容器会为目标对象动态创建一个代理对象. Spring AOP 就是以这种方式实现的.

Spring AOP 底层实现:

1.JDK 动态代理

速度快 , 通过反射调用目标方法

要求被代理的类一定要实现接口

2.CGLIB

通过实现代理类的子类来实现动态代理 , 但不能代理被 final 修饰的类和方法.

综上所述,JDK动态代理和CGLIB动态代理各有优缺点,应根据实际情况选择使用。如果目标类实现了接口,则建议使用JDK动态代理;如果目标类没有实现接口或者需要代理类中的非接口方法,则建议使用CGLIB动态代理。


总结

AOP 是对某方面功能的统一实现 , 它是一种思想 , Spring AOP 是对 AOP 的具体实现 , Spring AOP 可通过 AspectJ 注解的方式来实现 AOP 功能 , Spring AOP 的实现步骤是:

  1. 添加 AOP 支持框架
  2. 定义切面和切点
  3. 定义通知

Spring AOP 是通过动态代理的方式 , 在运行期间将 AOP 代码织入到程序中的 , 实现方式有两种 , JDK Porxy 和 CGLIB.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/637984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3自定义指令——元素平滑移动

vue提供一个用户可以高度自定义的指令入口directives 利用这个入口我们实现一个常见的元素平滑移动的自定义指令 ‘sl’ 首先我们结合指令创建一个多元素的界面&#xff1a; 这个场景我们在很多网站&#xff0c;商城都有见过&#xff0c;特别对于移动端的清单类界面 我们的终极…

Linux如何找回root密码

Linux如何找回root密码 首先&#xff0c;启动系统&#xff0c;进入开机界面&#xff0c;在界面中按“e”进入编辑界面。如图 进入编辑界面&#xff0c;使用键盘上的上下键把光标往下移动&#xff0c;找到以““Linux16”开头内容所在的行数”&#xff0c;在行的最后面输入&…

【几分醉意赠书活动 - 03期】 | 《Python系列丛书》

个人主页&#xff1a; 几分醉意的CSDN博客主页_传送门 个人主页&#xff1a; 陈老板的CSDN博客主页_传送门 赠书活动 | 第三期 本期好书推荐&#xff1a;《Python系列丛书》 粉丝福利&#xff1a;书籍赠送&#xff1a;共计送出30本 参与方式&#xff1a;关注公众号&#xff1a;…

IP-GUARD是否支持对打了水印的文档去除水印?

是否支持对打了水印的文档去除水印&#xff1f; 支持&#xff0c;从4.64.1005.0版本开始&#xff0c;支持对打了文档水印的文档做去水印的操作&#xff0c;但只是支持去除非图片类型的显式水印。支持右键文件去除、申请去除、自我备案去除三种方式。 例如&#xff1a; 对客户端…

短视频电商平台的流量货币化率

通过对内容社区的流量规模流量货币化率的估算&#xff0c;可以得出对应的商业化即变现能力&#xff0c;如电商GMV&#xff0c;广告收入规模。 货币化率 Take Rate 货币化率&#xff08;Take Rate&#xff0c;TR&#xff09;是电商平台报表指标而非业务指标&#xff0c;是广告收…

一步到位Python Django部署,浅谈Python Django框架

Django是一个使用Python开发的Web应用程序框架&#xff0c;它遵循MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;旨在帮助开发人员更快、更轻松地构建和维护高质量的Web应用程序。Django提供了强大的基础设施和工具&#xff0c;以便于处理复杂的业务逻…

【Eclipse】Eclipse的下载与安装

一.下载 下载地址&#xff1a;https://www.eclipse.org/downloads/packages/ 根据自己电脑的操作系统下载对应的版本 二.安装 解压到你想存放的路径上 设置该路径作为项目/代码存放的默认路径 \

修改knative func build的image

问题描述 基于func create创建的function的source code&#xff0c;并基于build创建出function对应的image。我们需在该image内创建安装iperf3。 解决步骤及遇到的errors 1. 查看本地的image&#xff0c;并运行该image podman images docker run -it -u root -p 10001:22 $…

Stream流 - 取最大对象、最小对象

需求&#xff1a;Dnl 对象包含属性 ygz&#xff08;有功总&#xff09;、wgz&#xff08;无功总&#xff09;&#xff0c;统计 Dnl 对象集合的最大有功总、最小有功总的对象。 集合&#xff1a; 对象1&#xff1a;ygz11.1、wgz22.2 对象2&#xff1a;ygz22.1、wgz66.2 对象3&a…

2023网络安全面试题汇总(附答案)

大家好&#xff0c;我是小V ,本人 17 年就读于一所普通的本科学校&#xff0c;20 年 6 月在三年经验的时候顺利通过校招实习面试进入大厂&#xff0c;现就职于某大厂安全联合实验室。 又到了毕业季&#xff0c;大四的漂亮学姐即将下架&#xff0c;大一的小学妹还在来的路上&…

网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

朋友们如果有需要全套《黑客&网络安全入门&进阶学习包》&#xff0c;可以&#x1f447;下方自取&#xff08;如遇问题&#xff0c;可以在评论区留言哦&#xff09;~ &#x1f447;&#x1f447;&#x1f447; 《黑客&网络安全入门&进阶学习包》 &#x1f446;&…

STM32F407硬件I2C实现MPU6050通讯(CUBEIDE)

STM32F407硬件I2C实现MPU6050通讯 文章目录 STM32F407硬件I2C实现MPU6050通讯cubeide设置写操作与读操作函数实现复位&#xff0c;读取温度&#xff0c;角度等函数封装mpu6050.cmpu6050.h代码分析 DMP移植1.修改头文件路径为自己的头文件路径2.修改I2C读写函数为自己mcu平台的读…

6.12黄金何时走出区间震荡?后市如何布局

近期有哪些消息面影响黄金走势&#xff1f;下周黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周一(6月12日)亚市盘中&#xff0c;现货黄金维持震荡&#xff0c;金价现报1960美元/盎司。本周黄金交易员将迎来美国CPI数据以及美联储利率决议&#xff0c;预计将对…

vue3+ts+vite实现pinia

本篇文章主要从事3部分 单个store下的文件进行使用模块下进行使用(pinia不像vuex那样使用模块化了 直接在store下定义ts文件即可)pinia持久化使用 安装pinia : cnpm install pinia 安装持久化 cnpm install pinia-plugin-persistedstate 1.单文件: index.ts (先不要管user.ts)…

详细讲解!如何模拟后台API调用场景

目录 简介 Postman 迁移至 ApiFox ApiFox 导入 Postman ApiFox 展示 API 调用场景 增加断言验证 API 使用测试执行场景 API 序列 总结 简介 在进行Web性能测试时&#xff0c;我们不仅需要测试前端页面的性能&#xff0c;还需要测试与后台API的交互性能&#xff0c;以及…

Spring Cloud常用组件介绍(Netflix、Alibaba)

Spring Cloud常用组件介绍 文章目录 **Spring Cloud常用组件介绍**一、说明**1.1.什么是Spring Cloud**1.2.Spring Cloud的组件选型 **二、组件介绍****2.1.服务注册与发现****2.1.1.Netflix Eureka****1&#xff09;分布式模型****2&#xff09;主要组件****3&#xff09;工作…

骑行陡坡村,潇潇洒洒出品

2023年6月10日群峰环抱小村庄盘山陡坡蜜桃香唇干舌燥咬一口甘甜香沁嘴边淌久旱叶枯悯农急乌云密布盼雷响但得雷神甘露下雨中狂奔又何妨

高效搞定文件重命名和归类!使用文件批量改名高手轻松实现

文件夹管理是计算机使用中非常重要的一项任务&#xff0c;对于个人电脑用户或企业机构来说&#xff0c;都需要对文件夹进行有效管理归类和重命名。 第一步&#xff0c;打开文件批量改名高手&#xff0c;进入文件批量重命名板块并点击添加文件&#xff0c;选择需要重命名的文件…

IOS应用跳转URL scheme和Universal Links

简介 IOS常见的跳转方式有URL scheme和Universal Links。这两个均可以实现App之间的跳转&#xff0c;以及通过网页实现跳转到对应的App内。通过本文章可以了解到两者的区别和具体的使用方法&#xff0c;以及参数的传递。应对常见的几种跳转需求。 URL scheme:需要配置URL sch…

增值税高不再是难事,只需一招即可解决!

《税筹顾问》专注于园区招商&#xff0c;您的贴身节税小能手&#xff0c;合理合规节税&#xff01; 任何一家企业&#xff0c;都逃脱不了一种税费的缴纳&#xff0c;那就是增值税。但其实小规模纳税人增值税缴纳&#xff0c;是可以享受到一些税收优惠照顾的&#xff0c;未达到月…