Spring AOP

目录

AOP

理解AOP

AOP组成

AOP的优点

Spring AOP

使用Spring AOP

定义切面和切点

定义通知

动态代理 

织入


AOP

理解AOP

AOP即面向切面编程,简单来说,就是把一部分通用的功能集中的放在一个地方处理的思想。假如某一段代码很多地方要用到,比如说登录验证,在传统编程中,有两个做法,要么每次复制粘贴,要么把他封装成一个函数再调用。复制粘贴显然是最坏的一种做法,一旦涉及到修改就会很麻烦。因此封装成函数是一种更优的做法。而AOP可以看作是一种更为高级和抽象的封装,它可以动态地植入通用功能。Spring AOP是AOP思想的一种具体实现。

AOP组成

AOP的基本组成包含切面(Aspect)、切点(Pointcut)、连接点(Joinpoint)、通知(Advice)。

  • 切面(Aspect):由连接点、切点和通知组成。简单来说切面就是一个包含了连接带你、切点和通知的类。即实现某个或某些功能的集合。
  • 连接点(Joinpoint):程序运行时可以切入切面执行通知的点。例如执行方法前、执行方法后、程序异常时等都可以作为连接点。
  • 切点(Pointcut):提供规则,匹配符合要求的连接点。满足切点规则的连接点才可以切入切面执行逻辑。
  • 通知(Advice):包括切入切面后执行的功能和执行时机。可以使用注解的方式来确定执行时机。

AOP的优点

  • 提高代码复用性和可维护性: AOP可以像函数封装那样,不必重复写相同的代码;
  • 提高开发的效率:AOP可以把不同的业务功能分块,例如日志、安全等模块分成不同的切面,在每个切面处理特定的功能;

Spring AOP

Spring AOP虽然属于Spring全家桶的产品,但是在创建项目时并不能找到相应的依赖:

 因此需要自行添加(注意版本号):

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

使用Spring AOP

定义切面和切点

使用@Aspect注解表示当前类为一个切面,使用@Pointcut注解定义切点(即设定规则):

@Component
@Aspect
public class ExperimentalAspect {@Pointcut("execution(* com.example.demo.controller.ExperimentalController.*(..))")public void pointcut() {}// 空方法,只起到标识的作用}

@Pointcut注解的参数是一个切点表达式,用于匹配连接点。使用AspectJ语法。切点表达式由切点函数组成,如:execution()、within()、target()、@annotation()等,其中最常用的时execution()函数,用来匹配方法连接点,语法为:

execution(<访问权限修饰符(可省略)><返回类型><包.类.方法(参数)><异常(可省略)>)

访问权限修饰符省略不写表示匹配所有权限,除参数部分外任意一个部分都可以使用通配符'*'来匹配任意字符,例如返回类型使用'*'表示任意返回值都满足规则。

参数中写具体的类型例如(int)表示参数为一个整型,使用'..'表示任意参数都满足。

上文的@Pointcut参数的含义就是匹配任意权限且在ExperimentalController包中的任意方法(返回值任意,参数任意)

其他切点函数用法可以参考Spring官网:Declaring a Pointcut :: Spring Framework

定义通知

Spring AOP通知注解包括:

  • @Before——方法执行前执行通知
  • @After——方法执行后执行通知(方法执行失败也会执行通知)
  • @AfterReturning——方法返回后(成功执行方法)执行通知
  • @AfterThrowing——抛出异常时执行通知
  • @Around——方法执行前后执行通知
// 执行前置通知
@Before("pointcut()")
public void runBefore() {System.out.println("执行了前置通知");
}
// 执行后置通知
@After("pointcut()")
public void runAfter() {System.out.println("执行了后置通知");
}

类似的@AfterReturning和@AfterThrowing写法一样,注解参数设置为上文设置的声明切点规则的函数名即可。

@Around注解除了遵守这个规则外,还需要设置返回值为Object类,参数设置为ProceedingJoinPoint类:

@Around("pointcut()")
public Object runAround(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("开始执行环绕方法");Object obj = null;// 执行拦截方法obj = joinPoint.proceed();System.out.println("结束执行环绕方法");return obj;
}

动态代理 

Spring AOP是基于动态代理技术实现的。调用者首先要通过代理才能到达目标对象,就比如说破在内陆访问chatgpt,就要先通过代理,代理就会把这些请求拦截下来,因此在内陆无法访问chatgpt等。动态代理包含两种方式:JDK动态代理和CGLib动态代理。

  • JDK动态代理:被代理类需要实现接口,然后通过反射机制,生成代理对象。
  • CGLib动态代理:被代理类可以不实现接口,通过继承被代理类的方式,生成代理对象。

Spring AOP默认使用JDK动态代理,如果没有实现接口就使用CGLib动态代理。

在Spring Boot2.x以后,默认使用CGLib动态代理。如果目标类实现了至少一个接口,就会优先考虑使用JDK动态代理。

可以在配置文件中设置属性为true强制使用CGLib代理(false强制使用JDK代理):

// 强制使用CGLib代理
spring.aop.proxy-target-class=true

织入

织入,把切面应用到目标对象并创建新的代理对象的过程,切面在指定的连接点被织入到目标对象中。简单来说就是动态代理的生成时机。织入可以在编译期、类加载期和运行期。Spring AOP是在运行期织入切面的。

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

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

相关文章

创建型模式 - 建造者模式

概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某个对象的构建过程复杂的情况。 由于实现了构建和装配的解耦。…

pytest 参数化进阶

目录 前言&#xff1a; 语法 参数化误区 实践 简要回顾 前言&#xff1a; pytest是一个功能强大的Python测试框架&#xff0c;它提供了参数化功能&#xff0c;可以帮助简化测试用例的编写和管理。 语法 本文就赶紧聊一聊 pytest 的参数化是怎么玩的。 pytest.mark.par…

openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句

文章目录 openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句13.1 语法格式13.2 参数说明13.3 示例 openGauss学习笔记-13 openGauss 简单数据管理-DELETE语句 DELETE语句可以从指定的表里删除满足WHERE子句的行。如果WHERE子句不存在&#xff0c;将删除表中所有行&…

css 禁止多次点击导致的选中了目标div的文字

像下面这样的情况&#xff0c;就可以用这种方法避免掉 禁止多次点击&#xff0c;导致的&#xff0c;选中了目标div的文字 或者 禁止多次点击&#xff0c;导致&#xff0c;html结构被选中显示出来 .targetDiv {-webkit-user-select: none;-moz-user-select: none;-ms-user-sel…

【云原生】Docker的初步认识,安装与基本操作

一、Docker的相关知识 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的…

SpringCloud整合Sentinel

文章目录 1、Sentinel介绍2、安装Sentinel控制台3、微服务整合Sentinel 1、Sentinel介绍 阿里开源的流量控制组件官网&#xff1a;https://sentinelguard.io/zh-cn/index.html承接了阿里双十一大促流量的核心场景&#xff0c;如秒杀、消息削峰填谷、集群流量控制、实时熔断下游…

Python自动化之pytest常用插件

目录 1、失败重跑 pytest-rerunfailures 2、多重校验 pytest-assume 3、设定执行顺序 pytest-ordering 4、用例依赖&#xff08;pytest-dependency&#xff09; 5.分布式测试(pytest-xdist) 6.生成报告&#xff08;pytest-html&#xff09; 1、失败重跑 pytest-rerunfailu…

Flutter 小技巧之滑动控件即将“抛弃” shrinkWrap 属性

相信对于 Flutter 开发的大家来说&#xff0c; ListView 的 shrinkWrap 配置都不会陌生&#xff0c;如下图所示&#xff0c;每当遇到类似的 unbounded error 的时候&#xff0c;总会有第一反应就是给 ListView 加上 shrinkWrap: true 就可以解决问题&#xff0c;那为什么现在会…

椒图——靶场模拟

先查看ip&#xff0c;10.12.13.232模拟的外网ip&#xff0c;其他的模拟内网ip&#xff0c;服务里面搭建好的漏洞环境。 #第一个测试项目&#xff0c;web风险发现 新建&#xff0c;下发任务&#xff0c;点威胁检测&#xff0c;webshell&#xff0c;点扫描任务&#xff0c;点新…

QT中QTimer的循环时间与槽函数执行时间以及在事件循环中触发,不同时间的结果分析

目录 当循环时间小于槽函数时间时&#xff1a; 当循环间隔时间大于槽函数时间时&#xff1a; 当存在两个定时器器&#xff0c;其中一个还是间隔100ms&#xff0c;另一个间隔1000ms&#xff1a; 当两个定时器的循环周期大于槽函数执行时间时 当在主程序中添加一个for循环…

js - 对forEach()函数的一些理解

1&#xff0c;定义和用法 定义&#xff1a; forEach() 方法用于调用数组的每个元素&#xff0c;并将元素传递给回调函数。注意: forEach() 对于空数组是不会执行回调函数的。 用法&#xff1a; // 箭头函数 forEach((element) > { /* … */ }) forEach((element, index) &…

mcu 启动流程

MCU启动流程 MCU启动流程 MCU启动流程1 MCU的启动方式2 MCU程序启动执行过程3 启动过程的执行工作4 keil调式过程验证5 调试文件map 1 MCU的启动方式 单片机的启动方式&#xff0c;以stm32为例&#xff0c;如下&#xff1a; 不同的下载方式对应的不同的启动方式&#xff0c;st…

truffle 进行智能合约测试

本方法使用了可视化软件Ganache 前两步与不使用可视化工具的步骤是一样的&#xff08;有道云笔记&#xff09;&#xff0c;到第三步的时候需要注意&#xff1a; 在truffle插件下找到networks目录&#xff0c;提前打开Ganache软件 在Ganache中选择连接或者新建&#xff0c;我在…

如何学习Java集合框架? - 易智编译EaseEditing

要学习Java集合框架相关的技术和知识&#xff0c;可以按照以下步骤进行&#xff1a; 掌握Java基础知识&#xff1a; 在学习集合框架之前&#xff0c;确保你已经具备良好的Java编程基础&#xff0c;包括语法、面向对象编程&#xff08;OOP&#xff09;原理和常用的核心类库等。…

MySQL备份与还原/索引/视图

MySQL备份与还原/索引/视图练习 文章目录 一、备份与还原1、使用mysqldump命令备份数据库中的所有表2、备份booksDB数据库中的books表3、使用mysqldump备份booksDB和test数据库4、使用mysqldump备份服务器中的所有数据库5、使用mysql命令还原第二题导出的book表6、进入数据库使…

STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块 硬件平台 野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块 GY-39 是一款低成本&#xff0c;气压&#xff0c;温湿度&#xff0c;光强度传感器模块。工作电压 3-5v…

thinkphp 上传图片

public function upload_img(){// 读取图片资源// 存储路径$path "uploads/avatar";$file request()->file(background_img);// 存储图片$info $file->rule(uniqid)->move($path);// 存储成功if ($info) {//获取到上传图片的路径名称$name_img $path . …

linux查看ipynb文件

linux查看ipynb文件 使用jupyter查看 使用jupyter查看 安装 pip install jupyter添加配置好的环境到jupyter notebook的kernel中&#xff1a; python -m ipykernel install --user --name mmdet --display-name "mmdet"运行jupyter notebook &#xff08;在ipynb…

WebSocket理论和实战

一 WebSocket理论 1.1 什么是http请求 http链接分为短链接、长链接&#xff0c;短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接&#xff08;但是是单向的&#xff0c;只能从客户端向服务端发消息&#x…

pycharm import的类库修改后要重启问题的解决方法

通过将以下行添加到pycharm中的settings-> Build,Excecution,Deployment-> Console-> Python Console中&#xff0c;可以指示Pycharm在更改时自动重新加载模块&#xff1a; %load_ext autoreload %autoreload 2