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版本跟设置的不适配。 …...

匹配yyyy-MM-dd日期格式的正则表达式
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ 解释: ^:匹配行的开头 \d{4}:匹配四个数字,表示年份 -:匹配一个横杠 (0[1-9]|1[0-2]):匹配01到12的月份,0开头的要匹配两位数字,1开…...

【失业预告】生成式人工智能 (GAI)AIGC
文章目录AIGCGAIAGI应用1. 计算机领域2. 金融领域3. 电商领域4. C端娱乐5. 游戏领域6. 教育领域7. 工业领域8. 医疗领域9. 法律领域10. 农业/食品领域11. 艺术/设计领域来源AIGC AIGC,全称为Artificial Intelligence Generated Content,是一种新型的人工…...

TensorFlow 2.0 的新增功能:第一、二部分
原文:What’s New in TensorFlow 2.0 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象,只关心如何实现目…...

Spring Boot配置文件详解
前言 Spring Boot 官方提供了两种常用的配置文件格式,分别是properties、YML格式。相比于properties来说,YML更加年轻,层级也是更加分明。 1. properties格式简介 常见的一种配置文件格式,Spring中也是用这种格式,语…...

实习面试题整理1
1、进行一下自我介绍 2、介绍一下你简历里的两个项目 3、说说vue的生命周期(具体作用) 4、说说你对vue单页面和多页面应用的理解 5、说说vue里自带的数组方法(七种,往响应式数据上靠) 6、说说vue双向数据绑定&…...

最新阿里、腾讯、华为、字节等大厂的薪资和职级对比,看看你差了多少...
互联网大厂新入职员工各职级薪资对应表(技术线)~ 最新阿里、腾讯、华为、字节跳动等大厂的薪资和职级对比 上面的表格不排除有很极端的收入情况,但至少能囊括一部分同职级的收入。这个表是“技术线”新入职员工的职级和薪资情况,非技术线(如产品、运营、…...

OpenCV——常用函数
cv::circle(overlay, pt, 2, cv::Scalar(0,green,red),-1); 使用OpenCV库中的circle()函数在图像上绘制圆形的代码。 具体来说,它的参数如下: - overlay:图像,在该图像上绘制圆形; - pt:圆心位置的cv:…...

超详细从入门到精通,pytest自动化测试框架实战-fixture多样玩法(九)
目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 在编写测试用例&…...

OJ练习第70题——困于环中的机器人
困于环中的机器人 力扣链接:1041. 困于环中的机器人 题目描述 在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。注意: 北方向 是y轴的正方向。 南方向 是y轴的负方向。 东方向 是x轴的正方向。 西方向 是x轴的负方向。 机器人可以接受…...

运行时内存数据区之虚拟机栈——局部变量表
这篇内容十分重要,文字也很多,仔细阅读后,你必定有所收获! 基本内容 与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stack)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型…...