关于SpringBoot中AOP的深入理解

一,AOP入门

1、AOP概述

AOP,Aspect Oriented Programming面向切面编程思想,是对OOP(面向对象)进行的补充

OOP是纵向继承技术,可以将程序中一段连续的代码进行封装

AOP是横向抽取技术,可以将程序中四个位置(核心概念之前、返回值之后、catch、finally)的非核心业务代码封装到一个类中(切面),在将切面中的功能套到(织入)目标对象具体的方法上

AOP在不改变源码的基础上实现功能的增强

AOP的重要应用是日志和事务等

2、AOP的专业术语

代理对象:代理目标对象的对象

目标对象:被代理的对象

横切关注点:指从核心代码中抽取的非核心业务代码,例: 添加日志功能

切面:封装非核心业务代码(横切关注点)的类

通知:切面中封装横切关注点的方法为通知方法,例: 把日志功能封装的方法

切入点:切面中通知作用于目标对象中方法的位置(通知之后)

切入点表达式:定位切入点的一种表达式

切入点是一个用于筛选连接点的表达式或者规则。它的主要作用是从众多的连接点中选择出符合特定条件的那些连接点。它就像一个过滤器,决定了 AOP 的横切逻辑应该应用到哪些具体的位置。只有符合这个表达式的连接点才会被性能监控这个 AOP 功能所增强

并且同一个连接点可能会被多个不同的切入点选中,也可能一个都不被选中。

连接点:在目标对象中抽取横切关注点的位置(方法)(通知之前)

连接点是在程序执行过程中能够插入切面(Aspect)的点。在 Spring AOP 中,这些点通常是方法的调用。

在准备使用AOP技术对哪个方法添加额外功能的方法就是一个连接点,这些点在 Spring AOP 中主要是指方法的调用、方法的执行、异常的抛出等位置。通常指的方法名

在使用AOP技术之前要添加额外功能的方法叫做连接点,在创建了切面类后,准备把切面类插入到哪里执行的位置也就是哪个方法(经过切入点表达式进行过滤后要使用的方法)叫做切入点。

可以说就是同一个方法,只是因为时间上的不同,分别给了不同的命名。

连接点(Join Point)和切入点(Pointcut)是不同的概念。
定义角度
连接点

​ 在 Spring AOP 中,连接点主要是基于方法调用的。在底层,Spring AOP 使用动态代理或者字节码增强技术来拦截这些方法调用,从而实现 AOP 功能。从开发者的角度看,只要知道在方法调用的这个时刻,AOP 机制就可以介入。

​ 连接点是在程序执行流程中,能够被切面(Aspect)插入额外逻辑的特定位置。从本质上讲,它是程序运行过程中的一个点,这些点在 Spring AOP 中主要是指方法的调用、方法的执行、异常的抛出等位置。例如,在一个 Java 的 Web 应用中,每次调用一个 Servlet 的doGet或doPost方法时,这个方法调用的位置就是一个连接点。连接点是一个比较宽泛的概念,它代表了所有可能被 AOP 增强的位置。
切入点

​ 切入点表达式通常使用 AspectJ 的语法

​ 切入点是一个用于筛选连接点的表达式或者规则。它的主要作用是从众多的连接点中选择出符合特定条件的那些连接点。例如,我们可以定义一个切入点表达式,用来选择某个特定包下所有以 “add” 开头的方法调用作为连接点,那么这个表达式所确定的这些特定的方法调用位置就是切入点所筛选出来的连接点。
数量角度
连接点
​ 连接点的数量通常是由程序的结构和执行流程决定的。一个复杂的应用程序可能有大量的连接点。例如,一个包含多个业务层、持久层和控制层的大型企业级应用,其中每个层都有许多方法,这些方法的调用位置都是连接点,数量可能会有成百上千个。
切入点
​ 切入点的数量是由开发者定义的。可以根据业务需求和功能模块等因素来定义不同的切入点。例如,可能为日志记录功能定义一个切入点,为事务管理功能定义另一个切入点。并且同一个连接点可能会被多个不同的切入点选中,也可能一个都不被选中。
功能角度
连接点
​ 连接点只是提供了一个可以插入切面逻辑的机会,它本身并没有对 AOP 增强的范围进行任何限制。例如,在一个方法调用这个连接点上,如果没有切入点的筛选,我们不知道是否要对这个方法调用进行日志记录、事务管理或者其他 AOP 操作。
切入点
​ 切入点则明确了哪些连接点需要进行 AOP 增强。它就像一个过滤器,决定了 AOP 的横切逻辑应该应用到哪些具体的位置。例如,我们通过一个切入点表达式确定了只对某个特定模块下的方法调用进行性能监控,那么只有符合这个表达式的连接点才会被性能监控这个 AOP 功能所增强。

二、基于注解的AOP的实现

1、实现步骤

a>导入aop的场景启动器

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

b>创建切面,并将目标对象和切面类的对象交给IOC容器管理

c>使用**@Aspect注解标记切面组件,并加上@Component**把切面类交给IOC作为一个bean使用

d>在配置类上使用**@EnableAspectJAutoProxy**注解开启AspectJ的自动代理功能,注意,在SpringBoot的环境中可以省略不写

2、通知

前置通知:使用@Before注解标记切面中方法,将其标记为前置通知的方法,在目标对象方法执行之前执行

后置通知:使用@After注解标记切面中的方法,将其标记为后置通知的方法,在目标对象方法的finally中执行

后置通知也叫做最终通知,不管目标对象中是否有异常都会执行

返回通知:使用@AfterReturning注解标记切面中的方法,将其标记为返回通知的方法,在目标对象方法的返回值之后执行

异常通知:使用@AfterThrowing注解标记切面中的方法,将其标记为异常通知的方法,在目标对象方法的catch中执行

环绕通知:使用@Around注解标记切面中的方法,将其标记为环绕通知的方法,相当于以上四种通知结合使用

注意:

1、环绕通知的方法的形参位置必须设置ProceedingJoinPoint类型的形参,通过joinPoint.proceed()表示目标对象方法的执行

2、环绕通知的方法必须设置Object类型的返回值,将joinPoint.proceed()方法的返回值进行返回,joinPoint.proceed()方法的返回值就是目标对象方法的返回值;若环绕通知没有返回值则直接抛出异常AopInvocationException

@Around("pointCut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint) {Object result = null;try {System.out.println("环绕通知(前置)");//调用目标对象的方法result = joinPoint.proceed();System.out.println("环绕通知(返回)");} catch (Throwable e) {System.out.println("环绕通知(异常)");throw new RuntimeException(e);} finally {System.out.println("环绕通知(后置)");}return result;
}

3、切入点表达式

@Before(“execution(public int com.yuan.aop.CalcImpl.add(int, int))”)

* 包名.类名.方法名(参数类型) —>(* yuan.*.*(..))

任意的访问修饰符和返回值类型使用* ,这里用一个* 代替类似于 public int 的访问修饰符和返回值

类中任意的方法使用*

包下任意的类使用*

包名和类名以指定的内容开始使用xxx*

包名和类名以指定的内容结束使用*xxx

任意的参数类型使用…

  • 切入点表达式通常使用 AspectJ 的语法。例如,execution(* com.example.service.UserService.update*(..))就是一个切入点表达式。其中execution是关键字,表示执行方法的连接点。*在返回值类型位置表示任意返回值类型,com.example.service.UserService.update*(..)表示com.example.service.UserService类中以update开头的所有方法,(..)表示方法可以有任意参数。

4、公共的切入点表达式

作用:把切入点表达式作为一个过滤器,对要插入额外功能的连接点方法进行筛选,然后插入切面类

a>声明公共的切入点表达式

//声明公共的切入点表达式
@Pointcut("execution(* com.yuan.aop.*.*(..))")
public void pointCut(){}

b>使用公共的切入点表达式

@Before("pointCut()")
public void beforeMethod() {System.out.println("前置通知");
}

5、获取连接点信息

a>获取连接点所对应方法的方法名和参数

在通知方法的形参位置设置JoinPoint类型的形参,其中封装了连接点相关信息

//获取连接点所对应方法的方法名
String methodName = joinPoint.getSignature().getName();
//获取连接点所对应方法的参数
Object[] args = joinPoint.getArgs();

b>在返回通知中获取目标对象方法的返回值

在通知方法的形参位置设置一个Object类型的形参,使用@AfterReturning注解中的returning属性,将该参数设置为接收目标对象方法的返回值的参数

@AfterReturning(value = "pointCut()", returning = "result")
public void afterReturningMethod(JoinPoint joinPoint, Object result) {String methodName = joinPoint.getSignature().getName();System.out.println("返回通知,方法名:"+methodName+",结果:"+result);
}

c>在异常通知中获取目标对象方法出现的异常

在通知方法的形参位置设置一个Exception或Throwable类型的形参,使用@AfterThrowing注解中的throwing属性,将该参数设置为接收目标对象方法出现的异常的参数

@AfterThrowing(value = "pointCut()", throwing = "e")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable e) {String methodName = joinPoint.getSignature().getName();System.out.println("异常通知,方法名:"+methodName+",异常:"+e);
}

6、切面的优先级

使用@Order注解标记切面,设置优先级,通过value属性设置一个整数,值越小优先级越高,

@Component
@Aspect  //标记为一个切面组件
@Order(1)  //优先级,默认优先级都是Integer的最大值,所以你无论写多大,都会比Integer的最大值小,都会先执行设置优先级的切面类
public class ValidateAspect {@Before("com.yuan.aop.LoggerAspect.poinCut()")public void before(JoinPoint joinPoint){System.out.println("ValidateAspect------->前置通知");}
}

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

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

相关文章

【Python】利用函数模拟创建【栈】的数据结构操作

知识解读&#xff1a;来自&#xff1a;https://fishc.com.cn[#FwSB,M 9xKOA!^6fP)_EC(nsd什么是栈呢&#xff1f;Powered by https://fishc.com.cn3>A?5JXL#_}YBGD"FWdubKeyhQP栈是一种具有 FILO 特性的数据结构&#xff0c;即先放入的数据反而后取出。e&"%b…

JAVA入门:使用IDE开发

JAVA入门:使用IDE开发 什么是IDE IDE(Integrated Development Environment,集成开发环境)是一种软件应用程序,它为程序开发、软件设计、项目管理等提供全面的设施。 简单来说就是简化开发过程,让编程更加方便。 IDEA 业界公认最好用的JAVA IDE 安装IDEA 打开IDEA官…

机器学习《西瓜书》学习笔记《待续》

如果说&#xff0c;计算机科学是研究关于“算法”的学问&#xff0c;那么机器学习就是研究关于“学习算法”的学问。 目录 绪论引言基本术语 扩展向量的张成-span使用Markdown语法编写数学公式希腊字母的LaTex语法插入一些数学的结构插入定界符插入一些可变大小的符号插入一些函…

o1 Pro模型架构揭秘与 Scaling Law 深度解析 | Claude 3.5 Opus、草莓训练、推理成本剖析

引言 近期&#xff0c;Semianalysis 发布了一篇重磅万字长文&#xff0c;首次披露 OpenAI 的 o1 Pro 模型架构与推理训练方法&#xff0c;同时深入探讨了当前 AI 领域的重要话题&#xff1a; Claude 3.5 Opus 是否失败&#xff1f;Scaling Laws&#xff08;扩展法则&#xff…

流程引擎Activiti性能优化方案

流程引擎Activiti性能优化方案 Activiti工作流引擎架构概述 Activiti工作流引擎架构大致分为6层。从上到下依次为工作流引擎层、部署层、业务接口层、命令拦截层、命令层和行为层。 基于关系型数据库层面优化 MySQL建表语句优化 Activiti在MySQL中创建默认字符集为utf8&…

labml.ai Deep Learning Paper Implementations (带注释的 PyTorch 版论文实现)

labml.ai Deep Learning Paper Implementations {带注释的 PyTorch 版论文实现} 1. labml.ai2. labml.ai Deep Learning Paper Implementations3. Sampling Techniques for Language Models (语言模型的采样技术)4. Multi-Headed Attention (MHA)References 1. labml.ai https…

qemu源码解析【04】qom实例

目录 qemu源码解析【04】qom实例1. type_init()宏2. type_register_static()宏3. arm_sbcon_i2c_init()何时被qemu系统调用 qemu源码解析【04】qom实例 qemu源码解析【总目录】 继续分析arm_sbcon_i2c实例&#xff0c;代码从行尾往上逐步分析 #include "qemu/osdep.h&q…

【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题

目录 背包问题简介 问题描述 输入&#xff1a; 输出&#xff1a; 动态规划解法 动态规划状态转移 代码实现 代码解释 动态规划的时间复杂度 例子解析 输出&#xff1a; 总结 作者我蓝桥杯&#xff1a;2023第十四届蓝桥杯国赛C/C大学B组一等奖&#xff0c;所以请听我…

【C++】抽象之神:类和对象(中)万字详解

Hi&#xff0c;朋友们&#xff0c;好久不见 我们上次学到了C类和对象&#xff08;上&#xff09;&#xff0c;感觉那难度还行&#xff0c;能接受&#xff0c;但这次的类和对象&#xff08;中&#xff09;&#xff0c;一开始真是让我觉得脑子转不动的无力感&#xff0c;难呐&am…

C++手动实现一个HashMap

1.HashMap原理 参考我的博客&#xff1a;https://blog.csdn.net/Revendell/article/details/110009858 开链法&#xff1a;STL的hashtable便是采用开链法解决冲突。这种做法是在每一个表格元素中维护一个list&#xff1a;散列函数为我们分配某一个list&#xff0c;然后我们在…

【Linux】深入理解进程信号机制:信号的产生、捕获与阻塞

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 时间不语&#xff0c;却回答了所有问题 目录 &#x1f4da;前言 &#x1f4da;一、信号的本质 &#x1f4d6;1.异步通信 &#x1f4d6;2.信…

sql server 数据库还原,和数据检查

右键数据库选择还原&#xff0c; 还原的备份文件必须选择在本地的文件&#xff08;远程文件没有试过&#xff09;还原数据库名字可以修改&#xff0c;然后file选择中有个2个目录data file 的目录 &#xff0c;和log data 的目录都可以重新选择还原到的新的目录&#xff0c;不要…

v31蓝牙信标方案

革新点 带蜂鸣器功能 容易安装和移动 多彩均匀明显的指示灯 长电池寿命&#xff0c;常规使用1-2年 自带1个按键 钮扣电池组供电 产品概述 电子标签拣货系统是一组安装在货架储位上的电子设备&#xff0c;通过计算机与软件的控制&#xff0c;藉由指示灯或数字显示作为辅助…

内存中优雅的csv对象(Python)

磁盘*.csv文件是文本&#xff0c;以行结构的二维list是内存中的“csv”。 (笔记模板由python脚本于2024年12月18日 10:15:23创建&#xff0c;本篇笔记适合学习过list、panda的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

OpenGL —— 2.6.1、绘制一个正方体并贴图渲染颜色(附源码,glfw+glad)

源码效果 C++源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version

H5 中 van-popup 的使用以及题目的切换

H5 中 van-popup 的使用以及题目的切换 在移动端开发中&#xff0c;弹窗组件是一个常见的需求。vant 是一个轻量、可靠的移动端 Vue 组件库&#xff0c;其中的 van-popup 组件可以方便地实现弹窗效果。本文将介绍如何使用 van-popup 实现题目详情的弹窗展示&#xff0c;并实现…

Metaploit-永恒之蓝漏洞利用

1&#xff1a;Metaploit介绍   本次测试主要是利用永恒之蓝漏洞对windows7进行控制利用&#xff0c;掌握Metaploit工具的使用&#xff0c;知道永恒之蓝的漏洞利用原理。永恒之蓝是在Windows的SMB服务处理SMB v1请求时发生的漏洞&#xff0c;这个漏洞导致攻击者在目标系统上可…

FPGA高速下载器SZ901

SZ901基于AMD(Xilinx) Virtual Cable协议. 本设备使用千兆网络接口。基于此接口,本设备可以同时支持多达四路FPGA板卡同时调试,每组相互独立,互不干扰。 特点 1,支持JTAG 速度最高53Mb/s&#xff0c;电压范围1.2-3.3V,最高支持200cm排线 2,支持4路JTAG独立使用 3,支持多路…

【递归,搜索与回溯算法】穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝算法入门专题详解

前言 什么是回溯算法&#xff1f; 回溯算法是一种经典的递归算法&#xff0c;通常用于解决组合问题、排列问题和搜索问题等。 回溯算法的基本思想 从一个初始状态开始&#xff0c;按照一定的规则向前搜索&#xff0c;当搜索到某个状态无法前进时&#xff0c;回退…

设计模式之桥接模式:抽象与实现之间的分离艺术

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” 桥接模式概述与角色组成 想象一下你家里的电视遥控器&#xff0c;无论是索尼还是三星的电视机&#xff0c;遥控器的按键功能都差不多&#xff1…