11.Spring AOP

文章目录

  • 1.什么是 Spring AOP?
  • 2.为什要用 AOP?
  • 3.Spring AOP 应该怎么学习呢?
    • 3.1 AOP 组成
      • 3.1.1 切⾯(Aspect)= 切点 + 通知
      • 3.1.2 连接点(Join Point)
      • 3.1.3 切点(Pointcut)
      • 3.1.4 通知(Advice)
    • 3.2 Spring AOP 实现
      • 3.2.1五大通知类型
      • 3.2.2 @Order注解解析
      • 3.2.3切点表达式
      • 3.2.4@annotation
    • 3.3 Spring AOP 实现原理 - 代理模式(静态代理,动态代理)
      • 3.3.1静态代理 代码实现
      • 3.3.1动态代理 代码实现
        • 3.3.1.1jdk 动态代理实现
        • 3.3.1.2CGLIB 动态代理实现
      • 3.3.2面试题

大家好,我是晓星航。今天为大家带来的是 Spring AOP 相关的讲解!😀

1.什么是 Spring AOP?

Spring两大核心思想:Ioc Aop

在介绍 Spring AOP 之前,⾸先要了解⼀下什么是 AOP?

AOP(Aspect Oriented Programming):⾯向切⾯编程,它是⼀种思想,它是对某⼀类事情的集中处理。⽐如⽤户登录权限的效验,没学 AOP 之前,我们所有需要判断⽤户登录的⻚⾯(中的⽅法),都要各⾃实现或调⽤⽤户验证的⽅法,然⽽有了 AOP 之后,我们只需要在某⼀处配 置⼀下,所有需要判断⽤户登录⻚⾯(中的⽅法)就全部可以实现⽤户登录验证了,不再需要每个⽅法中都写相同的⽤户登录验证了。 ⽽ AOP 是⼀种思想,

⽽ Spring AOP 是⼀个框架,提供了⼀种对 AOP 思想的实现,它们的关系和 IoC 与 DI 类似。

2.为什要用 AOP?

想象⼀个场景,我们在做后台系统时,除了登录和注册等⼏个功能不需要做⽤户登录验证之外,其他⼏ 乎所有⻚⾯调⽤的前端控制器( Controller)都需要先验证⽤户登录的状态,那这个时候我们要怎么处理呢?

我们之前的处理⽅式是每个 Controller 都要写⼀遍⽤户登录验证,然⽽当你的功能越来越多,那么你要写的登录验证也越来越多,⽽这些⽅法⼜是相同的,这么多的⽅法就会代码修改和维护的成本。那有没 有简单的处理⽅案呢?答案是有的,对于这种功能统⼀,且使⽤的地⽅较多的功能,就可以考虑 AOP 来统⼀处理了

除了统⼀的⽤户登录判断之外,AOP 还可以实现:

  • 统⼀⽇志记录
  • 统⼀⽅法执⾏时间统计
  • 统⼀的返回格式设置
  • 统⼀的异常处理
  • 事务的开启和提交等

也就是说使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

3.Spring AOP 应该怎么学习呢?

image-20240331165857684

3.1 AOP 组成

3.1.1 切⾯(Aspect)= 切点 + 通知

切⾯(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包 括了连接点的定义。

切⾯是包含了:通知、切点和切⾯的类,相当于 AOP 实现的某个功能的集合。

3.1.2 连接点(Join Point)

应⽤执⾏过程中能够插⼊切⾯的⼀个点,这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段 时。切⾯代码可以利⽤这些点插⼊到应⽤的正常流程之中,并添加新的⾏为。

连接点相当于需要被增强的某个 AOP 功能的所有⽅法。

3.1.3 切点(Pointcut)

Pointcut 是匹配 Join Point 的谓词。

Pointcut 的作⽤就是提供⼀组规则(使⽤ AspectJ pointcut expression language 来描述)来 匹配 Join Point,给满⾜规则的 Join Point 添加 Advice。

切点相当于保存了众多连接点的⼀个集合(如果把切点看成⼀个表,⽽连接点就是表中⼀条⼀条 的数据)。

3.1.4 通知(Advice)

切⾯也是有⽬标的 ——它必须完成的⼯作。在 AOP 术语中,切⾯的⼯作被称之为通知

通知:定义了切⾯是什么,何时使⽤,其描述了切⾯要完成的⼯作,还解决何时执⾏这个⼯作的问题。

Spring 切⾯类中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本 ⽅法进⾏调⽤:

  • 前置通知使⽤ @Before:通知⽅法会在⽬标⽅法调⽤之前执⾏。
  • 后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
  • 返回之后通知使⽤ @AfterReturning:通知⽅法会在⽬标⽅法返回后调⽤。
  • 抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
  • 环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执 ⾏⾃定义的⾏为。

切点相当于要增强的⽅法。

3.2 Spring AOP 实现

image-20240331193129624 image-20240331193139439

加了Aop方法后,查询消耗的时间:

image-20240331194035125

概念理解:

image-20240331194656711

代码图解:

image-20240331195020533

3.2.1五大通知类型

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

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

image-20240331210300225

image-20240331210651926

定义五个方法:

image-20240331211420360

切点

image-20240331211248832

自定义切点pt

image-20240331211406918

多个切面执行顺序

image-20240331212525726

3.2.2 @Order注解解析

如果我们每次使用切面都要算顺序未免会很麻烦,为了解决这个问题我们引入了 @Order

image-20240331212745657

从结果可以看出,我们给Order传参的数字越小,优先级越高

image-20240331212755786

image-20240331212833026

3.2.3切点表达式

image-20240331213150501

image-20240331213200893

image-20240331213207198

切点表达式支持通配符表达:

image-20240331213409018

3.2.4@annotation

execution表达式更适用有规则的,如果我们要匹配多个无规则的方法呢,比如:TestController中的t1()和UserController中的u1()这两个方法.

这个时候我们使用execution这种切点表达式来描述就不是很方便了

我们可以借助自定义注解的方式以及另一种切点表达式 @annotation 来描述这一类的切点

实现步骤:

  1. 编写自定义注解
  2. 使用 @annotation 表达式来描述切点
  3. 在连接点的方法上添加自定义注解

准备测试代码:

@RequestMapping("/test")
@RestController
public class TestController {
    @RestMapping("/t1")
    public String t1() {
        return "t1";
    }
    @RestMapping("/t2")
    public boolean t2() {
        return true;
    }
}

自定义注解声明: — MyAspect

image-20240401190838189

自定义注解使用:

image-20240401190803670

注意这里的@MyAspect就是我们自定义的@Before生效注解

image-20240401191329947

idea运行结果

3.3 Spring AOP 实现原理 - 代理模式(静态代理,动态代理)

基于动态代理来实现的

代理模式:静态代理模式、动态代理模式

使用代理前:

image-20240401195301717

使用代理后:

image-20240401195318711

生活中的代理

  • 艺人经纪人:广告商找艺人拍广告,需要经过经纪人,由经纪人来和艺人进行沟通
  • 房屋中介:房屋进行租赁时,卖方会把房屋授权给中介,由中介来代理看房,房屋咨询等服务
  • 经销商:厂商不直接对外销售产品,由经销商负责代理销售
  • 秘书/助理:合作伙伴找老板谈合作,需要先经过秘书/助理预约

静态代理:在程序运行前,代理对象就已经对目标对象进行了步骤的预执行代码

例如:我们在结账时买完东西老板会给我们拿袋子装东西,静态代理就是提前把袋子拿好,而动态代理则是需要时再拿,不提前分配。

代理模式的主要角色

  1. Subject: 业务接口类,可以是抽象类或者接口(不一定有)
  2. RealSubject: 业务实现类,具体的业务执行,也就是被代理对象,
  3. Proxy: 代理类. RealSubject的代理

比如房屋租赁
Subject 就是提前定义了房东做的事情,交给中介代理,也是中介要做的事情
RealSubject:房东
Proxy: 中介

UML类图如下:

image-20240401201237749

代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.

根据代理的创建时期,代理模式分为静态代理动态代理

  • 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的.class 文件就已经存在了.
  • 动态代理:在程序运行时,运用反射机制动态创建而成.

3.3.1静态代理 代码实现

房东接口:

image-20240401202622123

房东类:

image-20240401202655742

中介:

image-20240401202723033

主函数:

image-20240401202750149

3.3.1动态代理 代码实现

3.3.1.1jdk 动态代理实现

jdk代理类代码:

image-20240401203714893

主函数:

image-20240401204646157

image-20240402174814753

JDK只能代理接口,不能代理类

3.3.1.2CGLIB 动态代理实现

CGLIB代理类代码:

image-20240402174439013

主函数:

//CGLib 动态代理
        HouseSubject proxy3 = (HouseSubject) Enhancer.create(target.getClass(), new CGLibIntercepter(target));
        proxy3.rentHouse();

//CGLib 代理类

        HouseSubjectClass proxy4 = (HouseSubjectClass) Enhancer.create(subjectClass.getClass(), new CGLibIntercepter(subjectClass));
        proxy4.rentHouse();

image-20240402174846130

CGLIB既可以代理类,又可以代理接口

3.3.2面试题

1.Spring AOP是怎么实现的?

答:基于动态代理实现的。

2.动态代理是怎么实现的?

答:Spirng动态代理是基于JDK和CGlib实现的

3.Spring 使用的哪个动态代理?

答:JDK和CGLIb都用

4.什么时候用JDK,什么时候用CGLIb?

答:代理类只能使用CGlib。代理接口可以使用JDK,也可以使用CGLib。

5.JDK和CGLib有什么区别?

答:SpringBoot 2.X以后,默认使用CGLIB代理
spring.aop.proxy-target-class=false 设置JDK代理

image-20240402175756909

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

53.ReentrantLock原理

ReentrantLock使用 ReentrantLock 实现了Lock接口, 内置了Sync同步器继承了AbstractQueuedSynchronizer。 Sync是抽象类,有两个实现NonfairSync非公平,FairSync公平。 所以ReentrantLock有公平锁和非公平锁。默认是非公平锁。 public sta…

[数据集][目标检测]足球场足球运动员身份识别足球裁判员数据集VOC+YOLO格式312张4类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):312 标注数量(xml文件个数):312 标注数量(txt文件个数):312 标注类别…

Nvidia/算能 +FPGA+AI大算力边缘计算盒子:电力巡检智能机器人

聚焦数字经济与双碳经济赛道,专注于提供集中式新能源场站与分布式综合能源数智化整体解决方案,坚持以场站数字化、综合能源数字化双轮驱动发展。依靠专业化人才队伍与丰富的实证基地研究经验,打造成熟、先进的数智新能源研发平台。 在集中式新…

linux本地搭建apt源

使用apt-mirror搭建 1.安装 apt-get install apt-mirror2.编辑配置文件 vi /etc/apt/mirror.list修改下载目录 set_base_path 后面改为下载镜像的目录,同时删除前面#号 添加同步的源,建议用国内的,速度快,我这里用的阿里云的镜…

Leetcode 力扣109. 有序链表转换二叉搜索树 (抖音号:708231408)

给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为 平衡 二叉搜索树。 示例 1: 输入: head [-10,-3,0,5,9] 输出: [0,-3,9,-10,null,5] 解释: 一个可能的答案是[0,-3,9,-10,null,5],它表示所示的高…

每日一题——Python实现PAT甲级1015 Reversible Primes(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 is_prime函数分析: decimal_to_base函数分析: 主循…

无头+单向+非循环链表的实现

这里写目录标题 1. 链表1.1 链表的概念及结构1.2 链表的分类 2. 接口实现3. 链表的实现3.1 打印链表3.2 头插3.3 尾插3.4 头删3.5 尾删3.6 单链表查找3.7 在pos之前插入3.8 在pos之后插入3.9 删除pos位置的值3.10 删除pos位置之后的值3.11 链表的释放3.12 动态申请一个节点 4. …

STM32F103C8T6 HAL库串口重定向

前言: 这里仅用做个人记录,实现USART1串口通信,并通过printf重定向输出“串口打印测试” 正文开始: 首先在STM32CubeMX上对串口进行配置,其实方法也非常简单。 按照箭头顺序,先点击Connectivity找到USART1…

30分钟吃掉pytorch转onnx及推理

pytorch模型线上部署最常见的方式是转换成onnx然后再转成tensorRT 在cuda上进行部署推理。 本文介绍将pytorch模型转换成onnx模型并进行推理的方法。 #!pip install onnx #!pip install onnxruntime #!pip install torchvision 公众号算法美食屋后台回复关键词:源码…

jmeter -n -t 使用非GUI模式运行脚本说明

命令模式下执行jmx文件 jmeter -n -t fatie.jmx -l results\t4.jtl -e -o results\h1 表示以命令行模式运行当前目录下的脚本fatie.jmx,将结果存入当前目录下的results\t1.jtl,并且生成html格式的报告,写入文件夹results\h1。 说明:生成结果的文件夹r…

《精通ChatGPT:从入门到大师的Prompt指南》第10章:案例分析

第10章:案例分析 10.1 优秀Prompt案例解析 在深入探讨如何精通ChatGPT的使用之前,理解并分析一些优秀的Prompt案例是至关重要的。这不仅有助于更好地掌握Prompt的构建技巧,还能提高与AI交互的效果。在这一节中,我们将详细解析一…

实用的 C 盘搬家软件

一、简介 1、一款专门用于 Windows 系统的文件夹移动工具,它允许用户将程序或游戏的安装文件夹从一台驱动器移动到另一台驱动器,或者同一个驱动器内的不同路径,而无需重新安装或破坏现有的程序安装。 二、下载 1、下载地址: 官网链…

1-Maven-settings配置

1-Maven-settings配置 整理下Maven工具的使用。 【本地仓库、私服、镜像仓库、远程仓库、中央仓库】 本文基于阅读其他博客和对公司Maven配置的学习整理出来的。希望通过本此学习能对Maven有个整体性的掌控。 顺序:profile.repository > pom文件中的repository &…

关于焊点检测(SJ-BIST)模块实现

关于焊点检测(SJ-BIST)模块实现 语言 :Verilg HDL 、VHDL EDA工具:ISE、Vivado、Quartus II 关于焊点检测(SJ-BIST)模块实现一、引言二、焊点检测功能的实现方法(1) 输入接口&#x…

SpringBoot+Vue网上超市(前后端分离)

技术栈 JavaSpringBootMavenMySQLMyBatisVueShiroElement-UI 角色对应功能 用户管理员 功能截图

C基础与SDK调试方法

REVIEW 上次学习了一下软件使用流程zynq PS点灯-CSDN博客 本次学习一下C编程基础与调试方法 1. 硬件编程原理 小梅哥视频链接: 07_Xilinx嵌入式裸机硬件编程原理_哔哩哔哩_bilibili 对应的课程笔记:【zynq课程笔记】【裸机】【第7课 】【硬件编程原理…

eNSP学习——配置RIP路由附加度量值

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、搭建RIP网络 3、配置RIP Metricin 4、配置RIP Metricout 需要eNSP各种配置命令的点击链接自取:华为eNSP各种设备配置命令大全PDF版_ensp配置命令大全资…

Vyper重入漏洞解析

什么是重入攻击 Reentrancy攻击是以太坊智能合约中最具破坏性的攻击之一。当一个函数对另一个不可信合约进行外部调用时,就会发生重入攻击。然后,不可信合约会递归调用原始函数,试图耗尽资金。 当合约在发送资金之前未能更新其状态时&#…

计算机网络-数制转换与子网划分

目录 一、了解数制 1、计算机的数制 2、二进制 3、八进制 4、十进制 5、十六进制 二、数制转换 1、二进制转十进制 2、八进制转十进制 3、十六进制转十进制 4、十进制转二进制 5、十进制转八进制 6、十进制转十六进制 三、子网划分 1、IP地址定义 2、IP的两种协…

Linux之进程信号详解【上】

🌎 Linux信号详解 文章目录: Linux信号详解 信号入门 技术应用角度的信号 信号及信号的产生       信号的概念       信号的处理方式 信号的产生方式         键盘产生信号         系统调用产生信号         软件…