优雅的实现符合开闭原则的流水日志抽取demo

news2025/7/17 20:15:03

如何做出一个标准化记录流水日志(Demo)

昨天晚上 在b站刷到了 极海Channel 海哥的视频 也想去跟着实现一个,作为学习的demo,主要学习思路

可能存在的问题:

  1. 可能每一个需要收集的类里取参数的字段可能是不一样的如何去处理
  2. 如何可以让他更好的作用于新的业务代码上

项目代码日志

问题实现

以订单为例子 :

  • SaveOrder
  • UpdateOrder

两个对象的字段名字和类型都可能不同

SaveOrder

public class SaveOrder {
    private Long id;
}

UpdateOrder

public class UpdateOrder {
    private Long orderId;
}

定义日志流水数据对象

OperateLogDo

public class OperateLogDo {
    private Long orderId;
    private String desc;
    private String result;
}

配置需要生成注释的类型转换接口

接口

这个接口主要是用来对应的不同的类需要生成不同的日志,我们需要拿到他的唯一id 对象就可以操作数据了

public interface Convert<PARAM> {
    OperateLogDo convert(PARAM param);
}

实现类

public class SaveOrderConvert implements Convert<SaveOrder> {
    @Override
    public OperateLogDo convert(SaveOrder saveOrder) {
        OperateLogDo operateLogDo = new OperateLogDo();
        operateLogDo.setOrderId(saveOrder.getId());
        return operateLogDo;
    }
}

public class UpdateOrderConvert implements Convert<UpdateOrder> {
    @Override
    public OperateLogDo convert(UpdateOrder updateOrder) {
        OperateLogDo operateLogDo = new OperateLogDo();
        operateLogDo.setOrderId(updateOrder.getOrderId());
        return operateLogDo;
    }
}

定义注解

RecordOperate

1、 desc 是用来放日志类型的描述

2、 convert 用来放日志类型的转变类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface  RecordOperate {
    //日志描述
    String desc() default "";
    Class<? extends Convert> convert();
}

定义切面

OperateAspect

@Component
@Aspect
public class OperateAspect {
    //根据需求来定义需要多少线程 编写测试demo需求并不高
    private ThreadPoolExecutor executor = new ThreadPoolExecutor(1,1,1, TimeUnit.SECONDS,new LinkedBlockingDeque<>(100));

    @Around("@annotation(com.hyc.annotation.RecordOperate)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result  = proceedingJoinPoint.proceed();
        executor.execute(()->{
            try {
                MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
                RecordOperate recordOperate = signature.getMethod().getAnnotation(RecordOperate.class);
                Class<? extends Convert> convert = recordOperate.convert();
                Convert LogConvert = convert.newInstance();
                OperateLogDo operateLogDo = LogConvert.convert(proceedingJoinPoint.getArgs()[0]);
                operateLogDo.setDesc(recordOperate.desc());
                operateLogDo.setResult(result.toString());
                System.out.println("insert opreateLog"+ JSON.toJSONString(operateLogDo));
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
        return result;
    }
}

查看结果

启动测试

@SpringBootApplication
public class AopPublicLogApplication implements CommandLineRunner  {

    @Autowired
    OrderService orderService;

    public static void main(String[] args) {
        SpringApplication.run(AopPublicLogApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        SaveOrder saveOrder = new SaveOrder();
        saveOrder.setId(1L);
        orderService.saveOrder(saveOrder);
        UpdateOrder updateOrder = new UpdateOrder();
        updateOrder.setOrderId(2L);
        orderService.updateOrder(updateOrder);
    }
}

image-20221119004408533

​ 可以看到 我们确实拿到了不同类不同字段的id 而且跟着海哥的思路 我们编写的这个demo符合开闭原则,

在不改动源代码的情况下拓展功能。很简单的一个小demo但是可以拓展我们平时开发中的思路 多多的思考尽可能的优雅的实现业务和一些需要公共抽取的方式

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

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

相关文章

c++STL库

什么是STLSTL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。STL的版本原始版本Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本&#xff0c…

阿里首次公开企业级 SpringBoot 实战进阶笔记

Spring Boot 的重要性不需要我多说了吧&#xff0c;Java程序员们应该都懂&#xff0c;不仅面试会被提问&#xff0c;工作中也非常需要spring boot 不知道大家是如何学习Spring Boot的&#xff0c;据我所知&#xff0c;很多开发者会试着在网上找一些开源项目&#xff0c;通过阅…

马上2023了,云原生架构还不懂?阿里云原生架构笔记带你完全拿下

前言 软件架构发展至今&#xff0c;经历了从单体架构、垂直架构、SOA 架构到现在的以微服务、服务网格等云原生技术为主的演变过程&#xff0c;云原生技术发展势不可挡&#xff0c;老生常谈的“云原生”将依然会是未来的热门话题。而且随着数字化转型加速&#xff0c;企业对于…

Spring Data JPA之自动创建数据库表

Spring Data JPA之自动创建数据库表前言Spring Data JPA demo实现步骤导入依赖创建实体类编辑application.yml文件配置数据库连接和jpa配置运行测试总结如果博主的文章对您有所帮助&#xff0c;可以评论、点赞、收藏&#xff0c;支持一下博主!!!前言 由于在项目中使用到了Spri…

C++11中篇

文章目录1. 右值引用和移动语义1.1 左值引用和右值引用1.2 左值引用与右值引用比较1.3 右值引用使用场景和意义1.5 完美转发2. default 和delete1. 右值引用和移动语义 1.1 左值引用和右值引用 传统的C语法中就有引用的语法&#xff0c;而C11中新增了的右值引用语法特性&#…

Java_抽象类

目录 1.抽象类语法 2.抽象类特性 3.抽象类的作用 抽象类概念&#xff1a;在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是反过来&#xff0c;并不是所有的类都是用来描绘对象的&#xff0c;如果 一个类中没有包含足够的信息来描绘一个具体的对…

RabbitMQ远程访问

文章目录1. 创建用户2. 关闭防火墙开启端口3. 测试远程访问参考链接背景问题 guest这个用户只能使用localhost登录&#xff0c;而不能使用IP地址登录&#xff1a; amqp://guest:guest127.0.0.1:5672/rabbitVHost 远程无法连接amqp://guest:guest10.10.10.128:5672/rabbitVHost …

Elasticsearch simple(2)ElasticSearch windows本地环境搭建(V8.5.1)

切记安装Kibana的版本要和所安装的elasticsearch版本号完全一致。 这里&#xff1a; elasticsearch-8.5.1 kibana-8.5.1 elasticsearch默认端口为9200&#xff1b; Kibana默认端口为5601。 1 elasticsearch的下载和安装 下载官网&#xff1a;https://www.elastic.co/cn/down…

ArcGIS影像TIF拼接

ArcGIS影像TIF拼接 我们要使用的工具是Mosaic To New Raster 这个工具通过下面的路径找到&#xff1a; &#xff08;我用的是ArcGIS 10.8&#xff09; 输入影像 在这里输入多张待拼接的TIF 输出文件和路径 Output Loacation是输出文件的路径&#xff0c;可以是文件夹名称或…

MATLAB | MATLAB海洋、气象数据colormap配色补充包(NCL color tables)

众所周知&#xff0c;海洋、气象、水文等一系列学科绘制图像时&#xff0c;因很多时候涉及要将陆地海洋分开或者应对一些非常特殊的情况&#xff0c;因此有很多非常特别的colormap&#xff0c;我之前虽然做过一些常用colormap的补充包但是依旧是无法完全应对各种特殊的colormap…

C语言-基础

C-基础参考变量/常量左值/右值&#xff1f;&#xff1f;&#xff1f;字面量/常量变量作用域全局变量与局部变量作用域扩展 python数据与地址存储类autoregisterstaticextern数据类型基本类型整数类型进制数原码/补码/反码int 与 char数值溢出浮点类型字符型字符与整数字符与进制…

Selenium隐藏浏览器和元素截屏实践

文章目录隐藏浏览器介绍示例代码浏览器截图介绍示例代码对整个浏览器页面进行截屏指定特定HTML元素进行截屏隐藏浏览器 介绍 在使用Selenium采集网页数据时&#xff0c;需要不断地调用浏览器。实际上&#xff0c;通过对Selenium的设置&#xff0c;可以达到隐藏浏览器的效果。…

堆 (带图详解)

文章目录1.堆的基本概念1. 概念2.性质1.必须为完全二叉树2.满足大堆/小堆成立的条件3.存储方式1.逻辑结构2.物理结构4. 孩子与父亲之间下标的关系2.堆的基本实现1.push——插入1.代码2. 情况分析情况1情况23. 向上调整算法1.过程分析2. 临界条件的判断2. pop—— 删除1.代码2. …

[附源码]计算机毕业设计JAVA火车票订票管理系统

[附源码]计算机毕业设计JAVA火车票订票管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM myba…

【HDU No. 4006】 第k 大的数 The kth great number

【HDU No. 4006】 第k 大的数 The kth great number 杭电OJ 题目地址 【题意】 小明和小宝正在玩数字游戏。游戏有n轮&#xff0c;小明在每轮中都可以写一个数&#xff0c;或者问小宝第k 大的数是什么&#xff08;第k 大的数指有k -1个数比它大&#xff09;。 游戏格式为&am…

运维开发实践 - Docker - 容器实现原理

1.Docker容器是什么 按照Docker官网&#xff0c;容器是运行在宿主机上的一个进程&#xff0c;但与宿主机上的其他进程相隔离&#xff1b; 2.容器实现原理 这种隔离机制使用了内核中的namespace和cgroups功能&#xff1b; 2.1.Linux namespace Linux通过将系统的资源放置在…

Redis数据类型之string

文章目录stringⅠ. 增删查改Ⅱ. 加减操作Ⅲ. 数据生命周期Ⅳ. 业务场景 - 高频数据Ⅴ. 注意事项提示&#xff1a;以下是本篇文章正文内容&#xff0c;Redis系列学习将会持续更新 string ● 存储的数据&#xff1a;单个数据&#xff0c;最简单的数据存储类型&#xff0c;也是最常…

Paket在Linux下使用问题

1. 系统软件版本 Linux系统&#xff1a;Debian 10&#xff0c;需安装mono-devel Paket版本&#xff1a;7.1.5 关于Paket的介绍&#xff1a;https://github.com/fsprojects/Paket Paket的发布版本&#xff1a;https://github.com/fsprojects/Paket/releases 2. 使用方法 将…

原来背后都是商业利益,看到网易和暴雪的解约之后,原来是要定以后的KPI,坐地起价,但是一个时代已经结束了,都留在了记忆之中

1&#xff0c;大瓜新闻&#xff0c;2023年1月暴雪游戏中国将不会续约&#xff1f;&#xff1f; 2&#xff0c;原因是主要坐地起价&#xff0c;提高分成设置KPI 还好网易有自研游戏&#xff0c;估计早知道会有现在这样的情况。 提前做好了准备。还记得有个公司叫 九城吗&#x…

Linux操作系统~带你理解文件系统与软硬链接

目录 1.C语言中的FILE和文件描述符对应的file 2.Linux的EXT系列的文件系统 &#xff08;1&#xff09;.block group中六个部分的内容 inode索引结点相关 Q&#xff1a;这两个inode有什么不同&#xff1f; &#xff08;2&#xff09;.一个文件的inode和对应的block如何关联…