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.mzph.cn/news/850460.shtml

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

相关文章

《python程序语言设计》2018版第5章第46题均值和标准方差-下部(本来想和大家说抱歉,但成功了)

接上回,5.46题如何的标准方差 本来想和大家说非常抱歉各位同学们。我没有找到通过一个循环完成两个结果的代码。 但我逐步往下的写,我终于成功了!! 这是我大前天在单位找到的公式里。x上面带一横是平均值。 我不能用函数的办法…

数据处理之图像压缩

简介 图像压缩是很多应用场景中非常重要的技术,主要有以下几个原因: 减小文件大小 原始的图像文件通常非常大,尤其是高分辨率或者 RAW 格式的图片。压缩图像可以显著减小文件大小,有利于存储和传输。 节省存储空间 在许多应用中,需要存储大量的图像数据,如相册、电子商务平…

腾讯医疗大模型,不止大模型

“千呼万唤始出来,腾讯健康终于祭出医疗大模型。但或许这只是新故事的开始。下一步通过应用场景的打磨,全面嵌入生态合作伙伴,才能让医疗行业加速全面拥抱「数智化」工具。 在今年几乎所有企业都卷入AI大模型这场豪赌时,腾讯健康…

苹果智能:iOS 18 AI增强功能

苹果计划在 2024 年 WWDC 上推出一项名为“Apple Intelligence”的重大 AI 举措,将 AI 功能深度整合到其操作系统和核心应用程序中,同时优先考虑用户的隐私和安全。 该计划的名称是“Apple Intelligence”,这个名字很有市场价值。名字很简单…

Pod之间的通信详解

在Kubernetes集群中,Pod之间的通信是非常核心的功能。Pod是Kubernetes中的最小部署单元,它们之间经常需要进行通信以完成各种任务。本文将深入探讨Pod之间的通信方式,并通过示例代码来进一步解释。 目录 第一章. Pod间通信的实现原理 第二章…

C++做题

我们可以将0——9看成一个一维数组&#xff1a;a[11] #include<cstdio> int a[11],n; int x,p; int main(){scanf("%d",&n);for(int i1;i<n;i){pi;while(p!0){xp%10;a[x];//让下标x每次出现时增加1(描述不清楚)p/10;}}for(int i0;i<9;i){printf(&qu…

Flink学习-时间语义

含义 事件时间&#xff1a;数据产生的时间 处理时间&#xff1a;数据的处理时刻 水位线 用来衡量事件时间进展的标记&#xff0c;就被称作『水位线』&#xff0c;水位线可以看作是一条特殊的数据记录&#xff0c;是插入到数据流中的一个标记点&#xff0c;主要内容是个时间戳…

IO多路复用详解

1. 概念 IO多路复用也称IO多路转接&#xff0c;它是一种网络通信的手段&#xff08;机制&#xff09;&#xff0c;通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的&#xff0c;一旦检测到有文件描述符就绪&#xff08; 可以读数据或者可以写数据&#xff09;程序的…

Oracle基本操作

操作 DDL(Data Definition Language 数据定义语言)用于操作对象和对象的属性,这种对象包括数据库本身,以及数据库对象,像:表、视图等等,DDL 对这些对象和属性的管理和定义具体表现在 create、drop 和 alter 上。 create 可以创建数据库和数据库的一些对象 drop …

TypeScript看这篇就够了

TypeScript 技术文档 目录 TypeScript 技术文档1. 简介2. 安装与配置3. 基本类型3.1 布尔值3.2 数字3.3 字符串3.4 数组3.5 元组3.6 枚举3.7 Any3.8 Void3.9 Null 和 Undefined3.10 Never3.11 Object 4. 接口4.1 简单示例4.2 可选属性4.3 只读属性4.4 函数类型4.5 可索引类型 5…

轻NAS玩客云使用Docker部署小雅并挂载到AList详细流程分享

文章目录 前言1. 本地部署AList2. AList挂载网盘3. 部署小雅alist3.1 Token获取3.2 部署小雅3.3 挂载小雅alist到AList中 4. Cpolar内网穿透安装5. 创建公网地址6. 配置固定公网地址 前言 本文主要介绍如何在安装了CasaOS的玩客云主机中部署小雅AList&#xff0c;并在AList中挂…

C语言基础学习之位运算

枚举类型 enum 枚举名 { 枚举常量 //名字 }; 注意: 1.c语言中 对于枚举类型 实际上是 当作整型处理的 2.提高代码可读性&#xff0c; 写成枚举&#xff0c;可以做语法检查 3.枚举常量&#xff0c;之间用逗号隔开 4.枚举常量&#xff0c;可以给初值&#xff0c;给了初值之后&…

新电脑必装的7款软件,缺一不可

如果你买了新电脑或者是重装了新系统&#xff0c;那么这7款软件你一定要安装。 1、SpaceSniffer 如果你的C盘经常爆红&#xff0c;但是不知道是什么原因&#xff0c;那么你应该需要SpaceSniffer这款软件&#xff0c;它可以把你C盘中文件的空间占用情况&#xff0c;以大小方框…

当我拿到百度文心智能体大赛top1后,我又开发了...

目录 一、写在前面 二、代码助手 三、关于智能体 四、写在后面 一、写在前面 在不久前结束的文心智能体大赛&#xff08;第一期&#xff09;中&#xff0c;我有幸凭借一款名为恋爱助手的智能体斩获了大赛的桂冠。这个成绩&#xff0c;既是对我努力的认可&#xff0c;也是对…

Qt中图表图形绘制类介绍

接上篇介绍QChart 相关的类&#xff0c;本片主要在QChart 载体上进行图表图形绘制使用各种形状的图类。 一.QXYSeries类 QXYSeries类是QLineSeries折线图&#xff0c;QSplineSeries样条曲线图&#xff0c;QScatterSeries散点图的基类&#xff1b; QXYSeries类的使用都可以参考…

人工智能_机器学习096_PCA主成分分析降维算法_PCA降维原理_介绍和使用_模式识别_EVD特征值分解_SVD奇异值分解---人工智能工作笔记0221

首先我来看PCA降维,可以看到在图像处理中经常用到PCA,经过对数据进行降维可以去除数据噪声,发现数据中的模式,也就是 发现数据的规律. 这里的模式识别就是 机器学习中的一个分支 就是在数据中找规律的意思 我们使用代码看一下 from sklearn.docomposition import PCA from skl…

ecursionError: maximum recursion depth exceeded while calling a Python object

在 Python 中&#xff0c;RecursionError: maximum recursion depth exceeded 错误通常发生在一个函数递归调用自身太多次&#xff0c;超出了 Python 默认的递归深度限制时。Python 默认的递归深度限制是比较低的&#xff0c;以避免无限递归导致的栈溢出。 在你的代码中&#…

考虑风光场景生成的电动汽车并网优化调度【遗传算法】【IEEE33】

目录 主要内容 部分代码 部分结果 下载链接 主要内容 程序主要内容是考虑风光场景生成的电动汽车并网优化调度&#xff0c;采用的方法如下所述&#xff1a; ①采用蒙特卡洛方法&#xff0c;结合copula函数以及fuzzy-kmeans&#xff0c;获取6个典型风光出力场景&…

Linux C语言:输入输出(printf scanf)

一、数据输出 1、C语言I/O操作由函数实现 #include <stdio.h> 2、字符输出函数 格式: int putchar( int c ) 参数: c为字符常量、变量或表达式 功能&#xff1a;把字符c输出到显示器上 返值&#xff1a;putchar函数的返回值是参数的ASCLL码值&#xff1b; #inclu…

深入理解交叉熵损失CrossEntropyLoss - 乘积符号在似然函数中的应用

深入理解交叉熵损失CrossEntropyLoss - 乘积符号在似然函数中的应用 flyfish 乘积符号prod&#xff0c;通常写作 ∏ \prod ∏&#xff0c;它类似于求和符号 ∑ \sum ∑&#xff0c;但它表示的是连续乘积。我们来看一下这个符号的具体用法和例子。 乘积符号 ∏ \prod ∏ …