当前位置: 首页 > news >正文

AOP使用场景记录总结(缓慢补充更新中)

测试项目结构:

在这里插入图片描述

目前是测试两个日志记录和 代码的性能测试 后面如果有其他的应用场景了在添加.其实一中就包括了二,但是没事,多练一遍

1. 日志记录

比如说对service层中的所有增加,删除,修改方法添加日志, 记录内容包括操作的时间 操作的方法, 方法的参数, 方法所在的类, 方法执行的时间. 等进行日志记录.后面可以把数据存到数据库中,也可以把数据存到日志文件中这里就简单的做一个演示,直接输出到控制台了.

对于AOP有两种方式可以实现, 由于注解较为灵活,所以这里就使用注解的方式来实现.如果不太会使用注解的方式,可以看一下我之前的笔记.

SpringAop中的五种常见的通知的注解及@annotation 切入点表达式_yfs1024的博客-CSDN博客

第一步: 定义注解

这里因为是对方法切入,所以创建了一个MethodLog注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodLog {
}

第二步: 在对应的方法上添加注解 这里是对Service层所以就加到Service上了

类如下: 其中包括增删改查, 因为我们要求的是对增删改进行日志记录,所以就把注解加到增删改的方法上即可

@Service
public class EmployeeServiceImpl implements EmployeeService {@Override@MethodLogpublic void insertEmployee(Employee employee) {System.out.println("新增");}@Override@MethodLogpublic void deleteEmployee(Long EmployeeId) {System.out.println("删除");}@Overridepublic List<Employee> list() {ArrayList<Employee> employees = new ArrayList<>();employees.add(new Employee());return employees;}@Override@MethodLogpublic void updateEmployee(Employee employee) {System.out.println("更新员工信息");}
}

第三步: 定义切面 定义切入点, 定义通知

@Aspect
@Component
@Slf4j
public class MyAspect {//  定义切入点 对那些方法进行切入// com.yfs1024.service任意子包下的任意类中任意参数,任意返回值   并且 使用@MethodLog注解的方法@Pointcut("execution(* com.yfs1024.service..*.*(..)) && @annotation(com.yfs1024.annocation.MethodLog)")public void pointCutForMethodLog() {}//  定义通知  做什么@Around("pointCutForMethodLog()")public Object methodLog(ProceedingJoinPoint joinPoint) throws Throwable {//操作时间LocalDateTime operateTime = LocalDateTime.now();//操作类名String className = joinPoint.getTarget().getClass().getName();//操作方法名String methodName = joinPoint.getSignature().getName();//操作方法参数Object[] args = joinPoint.getArgs();String methodParams = Arrays.toString(args);long begin = System.currentTimeMillis();// 为了防止时间太短,睡会Thread.sleep(3);//调用原始目标方法运行Object result = joinPoint.proceed();long end = System.currentTimeMillis();//操作耗时Long costTime = end - begin;log.info("方法操作时间{},方法所在类{},方法名{},方法的参数{},方法执行耗时			{}",operateTime,className,methodName,methodParams,costTime);
// 注意一定要返回return result;}}

第四步: 测试

在测试类中进行测试, 注意因为我们使用了Spring的注解所以一定要在测试类上加上@SpringBootTest 默认会加但是还是要注意一下.

测试方法如下:

@SpringBootTest
class SpringAopApplicationTests {@Autowiredprivate EmployeeService employeeService;@Testvoid methodLog() {Employee employee = new Employee();employeeService.insertEmployee(employee);employeeService.deleteEmployee(10001L);employeeService.list();employeeService.updateEmployee(employee);}
}

控制台结果:

在这里插入图片描述

嗯,真香 其实想想如果使用动态代理让我们自己写应该也能写出来这样的效果. 在之前的笔记中也有记录感兴趣的话可以看一下,在笔记的最后的案例中

试着让动态代理变得通俗易懂,通过三个案例_yfs1024的博客-CSDN博客

2. 性能测试.

需求: 现在有两个工具包, 分别是AliyunOssUtils 和 AliyunOssUtilsOld ,我们现在要通过AOP来对这两个工具包进行测试

你可能会问,就两个我还用AOP? 没错确实麻烦,但是这里就是举个例子. 后面如果多个的话我们只需要,修改切入点即可.

依然是上面的四步

第一步: 定义注解

// 性能测试日志记录
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PTLog {
}

第二步: 在对应的方法上添加注解 (也可以添加到,类上,但是其实还是执行方法的时候记录,因为有多个吗. 也可以是接口上,这样接口的实现类的所有的方法就都被切入了)

AliyunOssUtils

@Component
public class AliyunOssUtils {/*** 公共方法* @throws InterruptedException*/@PTLogpublic void load(MultipartFile multipartFile) throws InterruptedException {Thread.sleep(10);}
}

AliyunOssUtilsOld

@Component
public class AliyunOssUtilsOld {/*** 公共方法* @throws InterruptedException*/@PTLogpublic void load(MultipartFile multipartFile) throws InterruptedException {Thread.sleep(10);}
}

第三步: 定义切面 定义切入点, 定义通知

@Aspect
@Component
@Slf4j
public class MyAspect {   // com.yfs1024.utils任意子包下的任意类中任意参数,任意返回值   并且 使用@PTLog注解的方法@Pointcut("execution(* com.yfs1024.utils..*.*(..)) && @annotation(com.yfs1024.annocation.PTLog)")public void pointCutForPTLog() {}@Around("pointCutForPTLog()")public Object ptLog(ProceedingJoinPoint joinPoint) throws Throwable {String className = joinPoint.getTarget().getClass().getName();long begin = System.currentTimeMillis();
//        为了防止时间太短,睡会Thread.sleep(3);//调用原始目标方法运行Object result = joinPoint.proceed();long end = System.currentTimeMillis();Long costTime = end - begin;log.info("{}类中方法执行耗时{}",className,costTime);return result;}
}

第四步: 测试

@SpringBootTest
class SpringAopApplicationTests {
// 这里因为测试用, 所以上面的工具类上就加了@Component注解, 一般不加哈,其实也可以通过一个配置类配合@Bean注入到容器这里懒了,嘿@Autowiredprivate AliyunOssUtils aliyunOssUtils;@Autowiredprivate AliyunOssUtilsOld aliyunOssUtilsOld;@Testvoid myPTLog() throws InterruptedException {aliyunOssUtils.load();aliyunOssUtilsOld.load();}
}

控制台结果:

在这里插入图片描述

3.公共字段的填充

首先介绍一下什么是公共字段的填充, 我们在对数据进行更新操作的时候,或者插入操作的时候往往都需要记录一下操作的时间, 基本所有的表都会有这两个字段,即 更新日期, 创建日期, 另外我们的每张表还需要记录创建该条记录的人是谁,以及修改这条记录的是谁,等这些就叫做公共字段. 对于不同的表可能要求不同视情况而定, 可见我们对于公共字段的操作往往是在 对数据库的更新操作和插入操作. 所以我们可以定义一个枚举来表示这两个操作,以供后期的使用.

第0步:

public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT
}

第一步: 定义注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoFill {OperationType value() default OperationType.INSERT;   // 设置枚举的参数,默认为插入操作
}

第二步: 在对应的方法上添加注解

这个时候就该想了, 我们把这些注解添在哪里合适?

答案是Mapper层, 因为Mapper层是和数据库交互的最后一个步骤, 我不管你之前怎么处理,知道在插入数据库之前把公共字段填充即可

代码如下:

@Mapper
public interface EmployeeMapper {/*** 根据用户名查询员工** @param username* @return*/@Select("select * from employee where username = #{username}")Employee getByUsername(String username);/*** @param employee*/
//    @Options(useGeneratedKeys = true,keyProperty = "id")@AutoFill()void insertEmployee(Employee employee);/*** 根据条件查询用户列表** @param employee* @return*/Page<Employee> select(Employee employee);/*** 更新员工信息*/@AutoFill(OperationType.UPDATE)void updateEmployee(Employee employee);
}

此时对插入和更新操作添加注解:

第三步: 定义切面 定义切入点, 定义通知

此时AOP的强大就体现的淋漓尽致

@Component
@Aspect
@Slf4j
public class AutoFillAspect {//    设置通知的连接点所在的位置@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annocation.AutoFill)")public void insertOrUpdateCommonsMeg() {}//    当前切入位置是mapper层,所以是在方法执行之前,即Service层执行之后,再给公共的属性赋值@Before("insertOrUpdateCommonsMeg()")public void beforeAutoFillCommonsField(JoinPoint joinPoint) throws Exception {
//        获取连接点的方法对象Object[] args = joinPoint.getArgs();
//        判断如果不为空,再执行操作,如果为空直接返回if (args == null || args.length == 0) {return;}
//        此时就可以获取参数列表中的第一个对象,即为当前需要添加数据的对象Object NowMethodObject = args[0];Class<?> obj = NowMethodObject.getClass();
//    判断当前的方法是Insert还是Update那些方法进行切入MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
//        获取当前的注解对象,通过value值进行判断if (annotation.value() == OperationType.INSERT) {
//            获取创建时间方法这个对象Method setCreateTime = obj.getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
//            获取设置创建者id的方法对象Method setCreateUser = obj.getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
//            调用传入参数setCreateTime.invoke(NowMethodObject, LocalDateTime.now());setCreateUser.invoke(NowMethodObject, BaseContext.getCurrentId());}
//        其次我要知道对谁切入Method setUpdateTime = obj.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
//            获取设置创建者id的方法对象Method setUpdateTUser = obj.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//            调用传入参数setUpdateTime.invoke(NowMethodObject, LocalDateTime.now());setUpdateTUser.invoke(NowMethodObject, BaseContext.getCurrentId());}
}

第四步: 测试

此时运行SpringBoot项目,进行更新和插入操作, 此时我们就可以看到数据库中的数据已经自动的填充进去

相关文章:

AOP使用场景记录总结(缓慢补充更新中)

测试项目结构: 目前是测试两个日志记录和 代码的性能测试 后面如果有其他的应用场景了在添加.其实一中就包括了二,但是没事,多练一遍 1. 日志记录 比如说对service层中的所有增加,删除,修改方法添加日志, 记录内容包括操作的时间 操作的方法, 方法的参数, 方法所在的类, 方法…...

FPGA基于XDMA实现PCIE X4的HDMI视频采集 提供工程源码和QT上位机程序和技术支持

目录1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案5、vivado工程详解6、驱动安装7、QT上位机软件8、上板调试验证9、福利&#xff1a;工程代码的获取1、前言 PCIE&#xff08;PCI Express&#xff09;采用了目前业内流行的点对点串行连接&#xff0c;比起 PCI …...

ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析

查看原文>>>ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析 目录 专题一、空间数据获取与制图 专题二、ArcGIS专题地图制作 专题三、空间数据采集与处理 专题四、遥感数据处理与应用 专题五、DEM数据…...

怎么找回回收站里已经删除的文件

作为忙忙碌碌的打工人&#xff0c;电脑办公是在所难免的&#xff0c;而将使电脑存储着大量的数据文件&#xff0c;不少小伙伴都养成了定期清理电脑的习惯。而清理简单快捷的方法&#xff0c;无疑是直接把文件拖进回收站里。再一键清空&#xff0c;清理工作就完成了。但如果发现…...

Spring Boot、Cloud、Alibaba 版本说明

Spring Boot、Cloud、Alibaba 版本说明 一、毕业版本依赖关系(推荐使用) 由于 Spring Boot 3.0&#xff0c;Spring Boot 2.7~2.4 和 2.4 以下版本之间变化较大&#xff0c;目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下&#xff0c;为了同时满足存…...

软件测试入门第一步:编写测试报告

什么是测试报告&#xff1f; 1、说明&#xff1a;是指把测试的过程和结果写成文档&#xff0c;对发现的问题和缺陷进行分析&#xff0c;为纠正软件的存在的质量问题提供依据&#xff0c;同时为软件验收和交付打下基础。 ps. 【测试过程和测试结果的分析报告&#xff0c;以及上线…...

【Vue】vue中的路由导航守卫(路由的生命周期)

文章目录全局前置守卫可选的第三个参数 next全局解析守卫router.beforeResolve全局后置钩子路由独享的守卫组件内的守卫可用的配置 API使用组合 API完整的导航解析流程正如其名&#xff0c;vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入…...

NumPy 基础知识 :6~10

原文&#xff1a;Numpy Essentials 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、NumPy 中的傅立叶分析 除其他事项外&#xff0c;傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号&#xff08;时域&#xff09;分离为以离散频率&#xff08;频域&am…...

实现vue的条件渲染

我的需求是根据设备不同的状态 渲染不同的标签。设备状态用device_State表示。 在线上面是一个vue的标签&#xff0c;我有一个数据state &#xff0c;如何让这个标签根据数据的取值 &#xff0c;修改内容&#xff0c;如state1时&#xff0c;标签修改为离线 要根据数据的取值动态…...

第四章 word2vec 的高速化

目录4.1 word2vec 的改进①4.1.1 Embedding 层4.1.2 Embedding 层的实现4.2 word2vec 的改进②4.2.1 中间层之后的计算问题4.2.2 从多分类到二分类4.2.3 sigmoid 函数和交叉熵误差4.2.4 多分类到二分类的实现4.2.5 负采样4.2.6 负采样的采样方法4.2.7 负采样的实现4.3 改进版 w…...

【四】3D Object Model之创建Creation——clear_object_model_3d()/copy_object_model_3d()算子

&#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; &#x1f31f;&#x1f31f;&#x1f31f; Halcon算子太多&#xff0c;学习查找都没有系统的学习查找路径&#xff0c;本专栏主要分享Halcon各类算子含义及用法&#xff0c;有…...

第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性

文章目录第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性删除镜像成员时删除镜像数据库属性编辑或删除异步成员第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性 删除镜像成员时删除镜像数据库属性 当从镜像中删除成员时&#xff0c;始终可以选择从属于该镜…...

自动写作ai-自动写作神器

自动生成文章 自动生成文章是指使用自然语言处理和人工智能技术&#xff0c;通过算法来自动生成文章的过程。一些自动生成文章的工具可以使用大量数据&#xff0c;学习数据背后的语言规范和知识结构&#xff0c;从而生成高质量和有用的文章。这种技术能够减少写作时间和人力成…...

P1368 【模板】最小表示法(SAM 求最小循环移位)

【模板】最小表示法 题目描述 小敏和小燕是一对好朋友。 他们正在玩一种神奇的游戏&#xff0c;叫 Minecraft。 他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的&#xff0c;而且由于机器的要求&#xff0c;他们只能做到把这个工艺品最左边的方块放到最右边。…...

投票感知器参数学习算法

投票感知器参数学习算法 以下为投票感知器参数学习算法的伪代码&#xff1a; 输入&#xff1a;训练集 (x1,y1),(x2,y2),...,(xn,yn)(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)(x1​,y1​),(x2​,y2​),...,(xn​,yn​)&#xff0c;学习率 η\etaη&#xff0c;最大迭代次数 TTT…...

Hyper-v下安装CentOS-Stream-9

1、我不想要动态扩展的硬盘&#xff0c;固定大小硬盘性能更高&#xff0c;所以这里我先创建一个固定硬盘&#xff08;如果你想用动态扩展的硬盘&#xff0c;那么可以省略前面几步&#xff0c;直接从第7步开始&#xff0c;并在第12步选择创建可动态扩展的虚拟硬盘&#xff09;&a…...

数据结构之顺序表,实现顺序表的增删改查

目录 一、顺序表的概念 二、顺序表的分类 1.静态顺序表 2.动态顺序表 3.顺序表的增删改查 总结 一、顺序表的概念 顺序表是一段物理地址连续的村塾单元依次存储数据元素的线性结构&#xff0c;一般情况下使用数组存储&#xff0c;在数组上完成数据的增删改查。 二、顺…...

HTB-Jeeves

HTB-Jeeves信息收集80端口50000端口![在这里插入图片描述](https://img-blog.csdnimg.cn/5824bf345bc040ee9e449bebeade9495.png)开机kohsuke -> Administrator信息收集 80端口 ask jeeves是一款以回答用户问题提问的自然语言引擎&#xff0c;面对问题首先查看数据库里是否…...

大力出奇迹——GPT系列论文学习(GPT,GPT2,GPT3,InstructGPT)

目录说在前面1.GPT1.1 引言1.2 训练范式1.2.1 无监督预训练1.2.2 有监督微调1.3 实验2. GPT22.1 引言2.2 模型结构2.3 训练范式2.4 实验3.GPT33.1引言3.2 模型结构3.3 训练范式3.4 实验3.4.1数据集3.5 局限性4. InstructGPT4.1 引言4.2 方法4.2.1 数据收集4.2.2 各部分模型4.3 …...

Linux ubuntu更新meson版本

问题描述 在对项目源码用meson进行编译时&#xff0c;可能出现以下错误 meson.build:1:0: ERROR: Meson version is 0.45.1 but project requires > 0.58.0. 或者 meson_options.txt:1:0: ERROR: Unknown type feature. 等等&#xff0c;原因是meson版本跟设置的不适配。 …...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...