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

news2024/11/24 1:36:09

主要实现思想:

通过实现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>{

    @Override
    public 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.coloradmin.cn/o/1904605.html

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

相关文章

VSCode神仙插件——CodeSnap (好看的代码截图)

1 安装 2 使用 选中要截图的代码,右键 此时右侧会出现代码截图的预览图 如果要将截图保存到本地,则点击上图红色框中的图标 也可以点击下面截的图,CtrlC复制,然后就可以CtrlV粘贴到其他应用程序里了

Pycharm python解释器 unsupported python 3.1 解决

Pycharm 环境 unsupported python 3.1解决 1. 问题重现2. 原因分析3. 解决方法 1. 问题重现 之前使用Pycharm 2024.1.1的时候&#xff0c;环境配置的Python 3.11.9&#xff0c;现在改成使用Pycharm 2020.2.2&#xff0c;结果Python解释器显示“unsupported python 3.1”&#…

GIT 使用相关技巧记录

目录 1、commit 用户信息变更 全局用户信息&#xff08;没有特殊配置的情况下默认直接用全局信息&#xff09; 特定仓库用户信息&#xff08;只针对于当前项目&#xff09; 方法一&#xff1a;修改config文件 方法二&#xff1a;命令方式 2、idea同一代码推向多个远端仓库…

如何在Ubuntu环境下使用加速器配置Docker环境

一、安装并打开加速器 这个要根据每个加速器的情况来安装并打开&#xff0c;一般是会开放一个代理端口&#xff0c;比如1087 二、安装Docker https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script 三、配置Docker使用加速器 3.1 修改配置…

搜索广告召回技术在美团的实践

内容整理自美团技术沙龙第81期《美团在广告算法领域的探索及实践》&#xff08;B站视频&#xff09;。本文首先介绍了美团搜索广告的三个阶段&#xff1a;多策略关键词挖掘、分层召回体系、生成式召回&#xff1b;然后重点介绍了生成式关键词召回、多模态生成式向量召回、生成式…

MyBatis中二级缓存的配置与实现原理

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的金融摸鱼侠&#xff0c;欢迎大家加入 Java 人自己的交流群“共同富裕的 Java 人”。 上一篇文章《MyBatis中一级缓存的配置与实现原理》中&#xff0c;我们已经掌握了 MyBatis 一级缓存的配置&#xff08;虽然…

14-40 剑和诗人14 - 为什么机器学习需要合成数据

​​​​​​ 数据是人工智能的命脉。如果没有高质量、有代表性的训练数据&#xff0c;我们的机器学习模型将毫无用处。但随着神经网络规模越来越大、人工智能项目越来越雄心勃勃&#xff0c;人们对数据的需求也越来越大&#xff0c;我们面临着一场危机——现实世界的数据收集和…

STM32-ADC+DMA

本内容基于江协科技STM32视频学习之后整理而得。 文章目录 1. ADC模拟-数字转换器1.1 ADC模拟-数字转换器1.2 逐次逼近型ADC1.3 ADC框图1.4 ADC基本结构1.5 输入通道1.6 规则组的转换模式1.6.1 单次转换&#xff0c;非扫描模式1.6.2 连续转换&#xff0c;非扫描模式1.6.3 单次…

C语言中32位浮点数的格式

以 GNU C为例&#xff0c;它遵循 IEEE 754-2008标准中制定的浮点表示规范。在该规范中定义了 5种不同大小的基础二进制浮点格式&#xff0c;包括&#xff1a;16位&#xff0c;32位&#xff0c;64位&#xff0c;128位&#xff0c;256位。其中&#xff0c;32位的格式被用作标准 C…

基于PSOGWO-CNN-BiLSTM数据回归预测(多输入单输出)-粒子群结合灰狼算法优化-CNN-BiLSTM

基于PSOGWO-CNN-BiLSTM数据回归预测(多输入单输出)-粒子群结合灰狼算法优化-CNN-BiLSTM 1.数据均为Excel数据&#xff0c;直接替换数据就可以运行程序。 2.所有程序都经过验证&#xff0c;保证程序可以运行。 3.具有良好的编程习惯&#xff0c;程序均包含简要注释。 获取方式…

恢复出厂设置后如何从 iPhone 恢复数据

在 iPhone 恢复出厂设置后&#xff0c;所有数据都会被删除&#xff0c;并且 iPhone 将恢复到原始出厂设置&#xff0c;这意味着您的所有 iPhone 数据&#xff0c;包括照片、视频、联系人和应用程序都将消失。 幸运的是&#xff0c;如果您有备份可以恢复&#xff0c;这并不一定…

JavaSe系列二十七: Java正则表达式

正则表达式 为什么要学习正则表达式再提几个问题解决之道-正则表达式正则表达式基本介绍介绍 正则表达式底层实现实例分析 正则表达式语法基本介绍元字符-转义号 \\\\元字符-字符匹配符元字符-选择匹配符元字符-限定符元字符-定位符分组非贪婪匹配 应用实例对字符串进行如下验证…

cloudflare tunnels tcp

这里是官网的说明Cloudflare Tunnel Cloudflare Zero Trust docs 根据实际情况安装环境 tunnels除了http,https协议是直接暴露公网&#xff0c;tcp是类似ssh端口转发。 在需要内网穿透的局域网找一条机子部署代理 我这边是window cloudflared tunnel login #生成一个身份校…

【论文阅读】-- Visual Analytics for Model Selection in Time Series Analysis

时间序列分析中模型选择的可视化分析 摘要1 引言2 相关工作3 问题表征3.1 Box-Jenkins 方法论3.2 ARIMA 和季节性 ARIMA 模型3.3 模型规范3.4 模型拟合3.5 模型诊断 4 需求分析5 VA 用于时间序列分析中的模型选择5.1 VA选型流程说明5.2 TiMoVA 原型5.2.1 实施选择5.2.2 图形用户…

(详细版)学生管理系统(姓名、成绩、学号)---顺序表

//1:创建顺序表 //2:判满 //3:判空 //4:插入学生信息 //5:输出学生信息 //6:按位置插入学生信息 //7:按位置删除学生信息 //8:按位置修改学生信息 //9:按学号查找学生信息 //10:顺序表去重 //11:销毁顺序表 main.c&#xff1a; int main(int argc, const char *argv[]) {seq_p…

第一周周日总结

题目总结 1.给你一个整数数组 hours&#xff0c;表示以 小时 为单位的时间&#xff0c;返回一个整数&#xff0c;表示满足 i < j 且 hours[i] hours[j] 构成 整天 的下标对 i, j 的数目。 整天 定义为时间持续时间是 24 小时的 整数倍 。 例如&#xff0c;1 天是 24 小时…

DHCP的原理及配置

目录 一、了解DHCP服务 1.什么是DHCP 1.1DHCP广播 2.使用DHCP的好处 2.1为什么使用DHCP 3.DHCP的模式与分配方式 3.1分配方式 3.2模式 二、DHCP工作原理 1.四次回话 2.重新登录 3.更新租约 4.扩展 三、安装DHCP服务 四、DHCP局部配置并且测试 五、使用…

PyQt5中如何实现指示灯点亮和指示灯熄灭功能

一般上位机界面都会涉及指示灯点亮和指示灯熄灭功能&#xff0c;从网上下载该功能的上位机界面&#xff0c;学习如何使用PyQt5搭建具备指示灯点亮和指示灯熄灭效果的界面。 1. 上位机界面的效果展示 使用PyQt5实现以下界面&#xff0c;界面效果如下&#xff0c;界面图片是从网…

【CUDA】

笔者在学习Softmax实现时遇到了一个问题&#xff0c;很多文章直接将softmax的计算分成了五个过程&#xff0c;而没有解释每个过程的含义&#xff0c;尤其是在阅读这篇文章时&#xff0c;作者想计算最基本的softmax的效率&#xff0c;以展示可行的优化空间&#xff1a; 贴一个g…

相见恨晚的《新程序员》 AI 专辑

声明&#xff1a;本文并不什么“软文”&#xff0c;是我的真实感受分享。本人和《新程序员》无任何利益关系&#xff0c;读者购买专栏我不会获得任何分成。 一、前言 前不久有位朋友送我一本 CSDN 出品的 《新程序员 006&#xff1a;人工智能新十年》 的杂志。 说实话&#x…