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、福利:工程代码的获取1、前言 PCIE(PCI Express)采用了目前业内流行的点对点串行连接,比起 PCI …...
ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析
查看原文>>>ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析 目录 专题一、空间数据获取与制图 专题二、ArcGIS专题地图制作 专题三、空间数据采集与处理 专题四、遥感数据处理与应用 专题五、DEM数据…...
怎么找回回收站里已经删除的文件
作为忙忙碌碌的打工人,电脑办公是在所难免的,而将使电脑存储着大量的数据文件,不少小伙伴都养成了定期清理电脑的习惯。而清理简单快捷的方法,无疑是直接把文件拖进回收站里。再一键清空,清理工作就完成了。但如果发现…...
Spring Boot、Cloud、Alibaba 版本说明
Spring Boot、Cloud、Alibaba 版本说明 一、毕业版本依赖关系(推荐使用) 由于 Spring Boot 3.0,Spring Boot 2.7~2.4 和 2.4 以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存…...
软件测试入门第一步:编写测试报告
什么是测试报告? 1、说明:是指把测试的过程和结果写成文档,对发现的问题和缺陷进行分析,为纠正软件的存在的质量问题提供依据,同时为软件验收和交付打下基础。 ps. 【测试过程和测试结果的分析报告,以及上线…...
【Vue】vue中的路由导航守卫(路由的生命周期)
文章目录全局前置守卫可选的第三个参数 next全局解析守卫router.beforeResolve全局后置钩子路由独享的守卫组件内的守卫可用的配置 API使用组合 API完整的导航解析流程正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入…...
NumPy 基础知识 :6~10
原文:Numpy Essentials 协议:CC BY-NC-SA 4.0 译者:飞龙 六、NumPy 中的傅立叶分析 除其他事项外,傅立叶分析通常用于数字信号处理。 这要归功于它在将输入信号(时域)分离为以离散频率(频域&am…...
实现vue的条件渲染
我的需求是根据设备不同的状态 渲染不同的标签。设备状态用device_State表示。 在线上面是一个vue的标签,我有一个数据state ,如何让这个标签根据数据的取值 ,修改内容,如state1时,标签修改为离线 要根据数据的取值动态…...
第四章 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()算子
😊😊😊欢迎来到本博客😊😊😊 🌟🌟🌟 Halcon算子太多,学习查找都没有系统的学习查找路径,本专栏主要分享Halcon各类算子含义及用法,有…...
第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性
文章目录第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性删除镜像成员时删除镜像数据库属性编辑或删除异步成员第三十一章 配置镜像 - 删除镜像成员时删除镜像数据库属性 删除镜像成员时删除镜像数据库属性 当从镜像中删除成员时,始终可以选择从属于该镜…...
自动写作ai-自动写作神器
自动生成文章 自动生成文章是指使用自然语言处理和人工智能技术,通过算法来自动生成文章的过程。一些自动生成文章的工具可以使用大量数据,学习数据背后的语言规范和知识结构,从而生成高质量和有用的文章。这种技术能够减少写作时间和人力成…...
P1368 【模板】最小表示法(SAM 求最小循环移位)
【模板】最小表示法 题目描述 小敏和小燕是一对好朋友。 他们正在玩一种神奇的游戏,叫 Minecraft。 他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。…...
投票感知器参数学习算法
投票感知器参数学习算法 以下为投票感知器参数学习算法的伪代码: 输入:训练集 (x1,y1),(x2,y2),...,(xn,yn)(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)(x1,y1),(x2,y2),...,(xn,yn),学习率 η\etaη,最大迭代次数 TTT…...
Hyper-v下安装CentOS-Stream-9
1、我不想要动态扩展的硬盘,固定大小硬盘性能更高,所以这里我先创建一个固定硬盘(如果你想用动态扩展的硬盘,那么可以省略前面几步,直接从第7步开始,并在第12步选择创建可动态扩展的虚拟硬盘)&a…...
数据结构之顺序表,实现顺序表的增删改查
目录 一、顺序表的概念 二、顺序表的分类 1.静态顺序表 2.动态顺序表 3.顺序表的增删改查 总结 一、顺序表的概念 顺序表是一段物理地址连续的村塾单元依次存储数据元素的线性结构,一般情况下使用数组存储,在数组上完成数据的增删改查。 二、顺…...
HTB-Jeeves
HTB-Jeeves信息收集80端口50000端口开机kohsuke -> Administrator信息收集 80端口 ask jeeves是一款以回答用户问题提问的自然语言引擎,面对问题首先查看数据库里是否…...
大力出奇迹——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进行编译时,可能出现以下错误 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. 等等,原因是meson版本跟设置的不适配。 …...
谷歌DeepMind让AI学会“主动查资料“
这项由爱丁堡大学与谷歌DeepMind联合开展的研究,以预印本形式发布于2026年5月13日,论文编号为arXiv:2605.13050v1,有兴趣深入了解的读者可以通过该编号查询完整论文。**研究概要**假设你有一位助理,学识渊博,但所有知识…...
用C#给PowerMill做个外挂:手把手教你写第一个连接与断开PM的WinForm工具
用C#打造PowerMill效率工具:从零构建自动化控制面板 在CNC编程工程师的日常工作中,PowerMill作为行业领先的CAM软件,其强大的功能背后也隐藏着大量重复性操作。每天数十次的项目打开关闭、连接状态检查、刀具路径查询等机械式点击,…...
别再乱改Rime配置了!先搞懂用户文件夹和程序文件夹的区别(Windows/Ubuntu路径详解)
Rime配置进阶指南:用户文件夹与程序文件夹的深度解析 1. 理解Rime配置的核心架构 Rime输入法以其高度可定制性著称,但这也意味着用户需要对其配置结构有清晰认知。许多初学者在修改配置时常常陷入困惑:为什么我的修改没有生效?为什…...
告别网络限制!手把手教你离线安装ModHeader插件(附最新4.3.8版本下载)
开发者必备:ModHeader插件安全离线安装全指南 对于经常需要调试API接口的开发者来说,能够自由修改HTTP请求头是刚需。ModHeader作为Chrome浏览器上最受欢迎的请求头管理工具之一,却因为网络访问限制让不少国内开发者望而却步。本文将为你彻底…...
从理论到PCB:20dB耦合度的宽带定向耦合器设计全流程与性能测试
从理论到PCB:20dB耦合度的宽带定向耦合器设计全流程与性能测试 在射频电路设计中,定向耦合器作为关键的无源器件,其性能直接影响整个系统的信号监测、功率分配和反射测量精度。特别是工作于1-4GHz频段、耦合度为20dB的宽带定向耦合器…...
LinuxVLAN接口异常定位实战
LinuxVLAN接口异常定位实战这是一篇面向中级 Linux 使用者的技术文章,主题聚焦在VLAN接口,重点讨论链路隔离、子接口和二层网络划分。在真实生产环境中,VLAN接口相关问题往往不会以单一错误形式出现,而是混杂在日志、权限、资源状…...
出口欧美设备机箱:必须符合HASCO模架与DME顶针标准
在出口欧美市场的设备机箱领域,符合HASCO模架与DME顶针标准是至关重要的。这不仅关乎产品的质量和性能,还影响着企业在国际市场的竞争力。本文将深入探讨这一标准的重要性,并结合深圳市机汇五金制品有限公司(以下简称“机汇五金”…...
【路径规划】基于A星算法实现图结构中的多机器人路径规划附matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎完整代码获取 定制创新 论文复现点击:Matlab科研工作室👇 关注我领取海量m…...
企业视频会议系统从公有云迁移到私有化环境:完整数据迁移指南
摘要:企业从Zoom、腾讯会议等公有云SaaS视频会议系统迁移到私有化部署的会议平台时,需要处理用户数据、历史会议记录、录制文件等关键资产的平滑过渡。本文提供一套经过生产验证的迁移方案,涵盖数据导出、批量导入、API对接、录制文件转存及验…...
CTFSHOW-WEB入门(1)信息收集
web1f12得到flagweb2虽然f12不能打开,但是curlU就直接开了得到flag也可以在url前面加个view-source,效果一样也可以通过浏览器打开开发者工具web3没思路的时候抓个包看看,可能会有意外收获得到flagweb4总有人把后台地址写入robots,…...
