使用AOP思想实现开闭原则下的流水日志输出

主要实现思想:

通过实现Convert接口来抽取公共组件,获取想要的标准模型。

现在有两个订单场景,一个保存订单,一个为更新订单。构造如下的服务类:

import org.springframework.stereotype.Service;@Service
public class OrderService {@RecordOperate(desc = "保存订单", convertLog = SaveOrderConvert.class)public Boolean saveOrder(SaveOrder saveOrder){System.out.println("save order, orderId:"+ saveOrder.getId());return true;}@RecordOperate(desc = "更新订单", convertLog = UpdateOrderConvert.class)public Boolean updateOrder(UpdateOrder updateOrder){System.out.println("update order, orderId:"+updateOrder.getOrderId());return true;}
}

对应的bean中订单属性名称会有差异,如何优雅的解决,后面会用一个转换接口,来获取对应的日志类。

定义的注释属性如下:

(这里有个注意点:

@Retention(RetentionPolicy.RUNTIME)注解用于表示注解的保留策略,在运行时保留注解,意味着注解不仅会被编译到字节码文件中。

@Target({ElementType.METHOD, ElementType.TYPE}) 表示该注解可以应用于方法和类(包括接口、枚举)上。

@Target({ElementType.METHOD,ElementType.TYPE})
@Component
@Retention(RetentionPolicy.RUNTIME)
public @interface RecordOperate {String desc() default "";Class<? extends Convert> convertLog();
}

我们要将SaveOrder和UpdateOrder转换成对应的日志模型,用于日志输出:

public interface Convert<T> {OperateLogDO convert(T t);
}
@Data
public class OperateLogDO {private Long orderId;private String result;private String desc;
}

最终针对不同的订单类实现对应的转换类:

public class SaveOrderConvert implements Convert<SaveOrder>{@Overridepublic OperateLogDO convert(SaveOrder saveOrder) {OperateLogDO operateLogDO = new OperateLogDO();operateLogDO.setOrderId(saveOrder.getId());return operateLogDO;}
}

最终!实现AOP的横向切面逻辑,要注意这边日志打印的过程应为异步,通过注解获取日志转换实例:

@Service
@Aspect
public class OperateLogAspect {/*** 定义切入点*/@Pointcut("@annotation(com.openapi.weekcode.aop.RecordOperate)")public void pointcut(){}private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,1,1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));/*** 定义横向逻辑*/@Around("pointcut()")private Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {Object result = proceedingJoinPoint.proceed();threadPoolExecutor.execute(() ->{try {MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();RecordOperate annotation = methodSignature.getMethod().getAnnotation(RecordOperate.class);Class<? extends Convert> convert = annotation.convertLog();Convert logConvert =  convert.newInstance();OperateLogDO operateLogDO = logConvert.convert(proceedingJoinPoint.getArgs()[0]);operateLogDO.setDesc(annotation.desc());operateLogDO.setResult(result.toString());System.out.println("insert operateLog:"+ operateLogDO.toString());} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}});return result;}}

结果如下

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

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

相关文章

JavaScript-实例-button

1 需求 2 接口 3 点击button跳转到一个页面 在HTML中&#xff0c;当你想要点击一个按钮并跳转到另一个页面时&#xff0c;通常你可以使用<a>标签来包裹按钮的样式&#xff08;尽管这通常不是最佳实践&#xff0c;因为<a>标签是用于链接的&#xff0c;而<button&…

SHAP(SHapley Additive exPlanations)基于XGBoost模型的可解释机器学习

模型可解释性 这是一个关于错误解释机器学习模型的危险以及正确解释它的价值的故事。如果您发现诸如梯度提升机或随机森林之类的集成树模型的鲁棒准确性很有吸引力&#xff0c;但也需要解释它们&#xff0c;那么我希望您发现这些信息有用且有帮助。 试想一下&#xff0c;我们…

julia系列17: tsp问题代码整理

1. 常用库和基础函数 这里是优化版的函数&#xff1a; using TSPLIB,LKH,Distances,PyPlot MaxNum 10000 tspreadTSPLIB(:att48) dist [round.(Int,euclidean(tsp.nodes[i,:],tsp.nodes[j,:])) for i in 1:tsp.dimension,j in 1:tsp.dimension]; pos(tsp::TSP,t::Vector{In…

Groovy中,多种循环方式

1.最常规的for循环 for (def i 0; i < 5; i) { //这个i需要声明println "遍历输出${i}" }2.while循环 def j 0 while (j < 5) {println "遍历输出 ${j}"j }3.for in 循环 def list [0, 1, 2, 3, 4] //这个l无需声明 for (l in list) { printl…

uniapp跨域问题解决

找到menifest文件&#xff0c;在文件的最后添加如下代码&#xff1a; // h5 解决跨域问题"h5":{"devServer": {"proxy": {"/adminapi": {"target": "https://www.demo.com", // 目标访问网址"changeOrigin…

数据库的存储引擎,数据类型,约束条件,严格模式

【一】存储引擎 1.什么是存储引擎存储引擎可以理解为处理数据的不同方式 2.查看存储引擎show engines; 3.须知的引擎MyISAM5.5之前版本MySQL默认的存储引擎特点:存取数据的速度快 但是功能很少 安全性较低速度快因为自带索引InnoDB5.5之后版本MySQL默认的存储引擎特点:有诸多功…

工程施工合同无效但竣工交付,应当参照合同关于工程价款的约定计算折价补偿款

审判实践中&#xff0c;对于建设工程施工合同无效但工程竣工并交付使用的&#xff0c;应以何种标准计算折价补偿款的问题&#xff0c;认识不一致。【法官会议意见】&#xff1a;建设工程施工合同是承包人进行工程建设、交付工作成果即建设工程并由发包人支付价款的合同。建设工…

httpd目录显示乱码问题

vim /etc/httpd/conf/httpd.conf 在<Directory “/var/www/html”>下添加&#xff1a; IndexOptions CharsetUTF-8重启httpd: systemctl restart httpd.service还是不好看&#xff0c;调整下显示宽度&#xff0c;还是这个位置&#xff1a; <Directory “/var/www/ht…

区块链论文速读A会-ISSTA 2023(2/2)如何检测DeFi协议中的价格操纵漏洞

Conference&#xff1a;ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2023 第1~5篇区块链文章 请点击此…

09视图,触发器,事务,存储过程,函数,流程控制,索引,隔离机制,锁机制,三大范式

【一】视图 (1)视图须知概念 1.什么是视图&#xff1f; 视图就是通过查询得到一张虚拟表&#xff0c;然后保存下来&#xff0c;下次可以直接使用 2.为什么要用视图&#xff1f; 如果要频繁操作一张虚拟表(拼表组成)&#xff0c;就可以制作成视图&#xff0c;后续直接操作 注意…

IDEA 创建springboot项目杂记-更新中

一、工具使用杂记 1、使用maven 创建新springboot项目时&#xff0c;因为https://start.spring.io/ 连接不上项目无法创建。直接把脚手架地址换为国内的 http://start.aliyun.com

田忌赛马 贪心

本题是更难的那道,一场50 最低为o 第一行一个整数 &#x1d45b;n &#xff0c;表示他们各有几匹马&#xff08;两人拥有的马的数目相同&#xff09;。第二行 &#x1d45b;n 个整数&#xff0c;每个整数都代表田忌的某匹马的速度值&#xff08;0≤0≤ 速度值 ≤100≤1…

Python】从文本字符串中提取数字、电话号码、日期、网址的方法

关于从文本字符串中提取数字、电话号码、日期和网址的方法&#xff1a; 提取数字&#xff1a; 在 Python 中&#xff0c;使用正则表达式 \d 来匹配数字。 \d 表示匹配一个数字字符&#xff08;0-9&#xff09;。如果要匹配连续的数字&#xff0c;可以使用 \d 。 import re def …

C++面向对象的常见面试题目(一)

1. 面向对象的三大特征 &#xff08;1&#xff09;封装&#xff1a;隐藏对象的内部状态&#xff0c;只暴露必要的接口。 #include <iostream> #include <string>// 定义一个简单的类 Person class Person { private: // 私有成员&#xff0c;外部不可直接访问std…

Mac OS ssh 连接提示 Permission denied (publickey)

这错误有点奇葩&#xff0c;MacBook的IDE(vscode和pycharm)远程都连不上&#xff0c;terminal能连上&#xff0c;windows的pycharm能连上&#xff0c;见鬼了&#xff0c;所以肯定不是秘钥的问题了&#xff0c;查了好久竟然发现是权限的问题。。 chmod 400 ~/.ssh/id_rsa http…

华为机试HJ37统计每个月兔子的总数

华为机试HJ37统计每个月兔子的总数 题目&#xff1a; 想法&#xff1a; 上述题目实际是一个斐波那契数列&#xff0c;利用斐波那契数列对问题进行求解 input_number int(input())def fib(n):if n < 2:return 1else:n_1 1n_2 1count 2while count < n:n_1, n_2 n_…

【Android】【多屏】多屏异显异触调试技巧总结

这里写目录标题 如何获取多屏IDs获取多屏的size/density如何启动应用到指定DisplayId多屏截屏/录屏screencapscreenrecord发送按键到指定DisplayId 如何获取多屏IDs dumpsys display | grep mDisplayIdtrinket:/ # dumpsys display | grep mDisplayIdmDisplayId0mDisplayId2 t…

【AI资讯】可以媲美GPT-SoVITS的低显存开源文本转语音模型Fish Speech

Fish Speech是一款由fishaudio开发的全新文本转语音工具&#xff0c;支持中英日三种语言&#xff0c;语音处理接近人类水平&#xff0c;使用Flash-Attn算法处理大规模数据&#xff0c;提供高效、准确、稳定的TTS体验。 Fish Audio

区块链技术的应用场景和优势。

区块链技术具有广泛的应用场景和优势。 区块链技术的应用场景&#xff1a; 1. 金融服务&#xff1a;区块链可用于支付、跨境汇款、借贷和结算等金融服务&#xff0c;提高交易效率、降低成本并增强安全性。 2. 物联网&#xff08;IoT&#xff09;&#xff1a;区块链可以用于物…

机器学习Day12:特征选择与稀疏学习

1.子集搜索与评价 相关特征&#xff1a;对当前学习任务有用的特征 无关特征&#xff1a;对当前学习任务没用的特征 特征选择&#xff1a;从给定的特征集合中选择出相关特征子集的过程 为什么要特征选择&#xff1f; 1.任务中经常碰到维数灾难 2.去除不相关的特征能降低学习的…