通过切面编程(AOP)实现不同字段转换为同一字段

文章目录

  • 前言
  • 一、切面编程(AOP)是什么?
  • 二、demo样例
    • 1.实体类
      • a.新增订单
      • b.更新订单
      • b.日志实体类
    • 2.实现相关
      • a.类型转换接口类
      • b.类型转换接口实现类
      • c.自定义注解
      • d.切面配置
      • e.运行
  • 三、结果示例
  • 四、其他


前言

项目中有很多场景需要去记日志,,也可能存在有很多接入方,日志表是同一种,但是外部数据的字段可能与日志表不一一对应,如果每一种业务都写一种方法去做转化,代码量很大,因此可采用横向切入逻辑去做一个整体处理,异步去写入,对代码的侵入也相关较少。


一、切面编程(AOP)是什么?

  1. 切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,旨在通过将横切关注点(cross-cutting concerns)从核心业务逻辑中分离出来,以提高代码的模块化性、可维护性和复用性。
  2. AOP 主要通过切面(Aspect)和连接点(Join Point)来实现,其中:切面(Aspect)是横切关注点的模块化单元,它包含了通知(Advice)和切点(Pointcut)。连接点(Join Point)是在应用执行过程中能够插入切面的点,通常是方法的调用或异常的抛出等。

二、demo样例

1.实体类

a.新增订单

@Data
public class SaveOrder {
    //订单ID
    private String id;
    //订单名称
    private String name;
}

b.更新订单

@Data
public class UpdateOrder {
    //订单ID
    private String orderId;
    //订单名称
    private String name;
}

b.日志实体类

@Data
public class OperateLogDO {
    //订单ID
    private String orderId;
    //描述
    private String desc ;
    //结果
    private String  result ;
}

2.实现相关

a.类型转换接口类

//参数类型定义为泛型
public interface Convert<PARAM> {

    OperateLogDO convert (PARAM param);

}

b.类型转换接口实现类

//新增订单对象转换
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;
    }
}

c.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RecordOperate {

    String desc() default "";

    Class<? extends Convert> convert();
}

d.切面配置

@Component
@Aspect
public class OperateAop {

   //定义线程池
    private ThreadPoolExecutor threadPoolExecutor =  new ThreadPoolExecutor(1,
            1,1, TimeUnit.SECONDS,new LinkedBlockingDeque<>(100));

    //匹配被 @RecordOperate 注解标记的方法作为切入点
    @Pointcut("@annotation(com.example.demo.aop.RecordOperate)")
    public void pointcut(){

    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint ) throws Throwable {
        Object rs = proceedingJoinPoint.proceed();
        threadPoolExecutor.execute(()->{
            try {
                //获取当前连接点的方法签名信息,并将其强制转换为 MethodSignature 类型
                MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
                //通过 signature.getMethod() 获取方法对象,然后调用 getAnnotation() 方法
                //传入 RecordOperate.class 参数,从而获取该方法上标记的 RecordOperate 注解
                //对象
                RecordOperate annotation = signature.getMethod().getAnnotation(RecordOperate.class);
                 //通过获取到的 RecordOperate 注解对象,调用 convert() 方法获取注解中
                 //指定的转换类的 Class 对象
                Class<? extends Convert> convert = annotation.convert();
                //实例化对象
                Convert logConvert  = convert.newInstance();
                //获取参数,因上述方法只有一个参数,故取下标为0的值
                Object arg = proceedingJoinPoint.getArgs()[0];
                //调用转换方法
                OperateLogDO operateLogDO =  logConvert.convert(arg);
                //设置结果
                operateLogDO.setDesc(annotation.desc());
                operateLogDO.setResult(rs.toString());
                System.out.println("operateLogDO = " + operateLogDO);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        });
        return rs;
    }
}

e.运行

    //在main类中实现CommandLineRunner接口进行测试
    @Override
    public void run(String... args) {

        SaveOrder saveOrder = new SaveOrder();

        saveOrder.setId("1");

        saveOrder.setName("save");

        orderService.saveOrder(saveOrder);

        UpdateOrder updateOrder = new UpdateOrder();

        updateOrder.setOrderId("2");

        updateOrder.setName("update");

        orderService.updateOrder(updateOrder);

    }

三、结果示例

在这里插入图片描述
实现了不同的字段转换为同一字段。

四、其他

  1. 主业务发生了异常,切面逻辑不能回滚,导致记录异常;
  2. 实际项目中应该采用模版类方法,把公共属性抽到一个父类,更方便写统一的aop。
  3. AOP 的核心概念包括以下几种通知类型:
    前置通知(Before advice):在连接点之前执行,常用于执行一些预处理操作。
    后置通知(After returning advice):在连接点正常执行后执行,常用于执行一些清理操作。
    环绕通知(Around advice):包围连接点执行,可以在方法调用前后进行一些额外的处理。
    异常通知(After throwing advice):在连接点抛出异常后执行,用于处理异常情况。
    最终通知(After finally advice):无论连接点是否正常执行完成,最终都会执行的通知。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出前端本地储存

引言 2021 年&#xff0c;如果你的前端应用&#xff0c;需要在浏览器上保存数据&#xff0c;有三个主流方案&#xff1a; CookieWeb Storage (LocalStorage)IndexedDB 这些方案就是如今应用最广、浏览器兼容性最高的三种前端储存方案 今天这篇文章就聊一聊这三种方案的历史…

Python学习:列表

Python 列表概念 在Python中&#xff0c;列表&#xff08;List&#xff09;是一种有序、可变、允许重复元素的数据结构。列表使用方括号 ​[]​来表示&#xff0c;可以包含任意类型的元素&#xff0c;如整数、字符串、列表等。 Python 访问列表中的值 在Python中&#xff0…

BI(商业智能):开启数据驱动的未来

在当今信息时代&#xff0c;企业和组织面临着大量的数据和信息。这些数据包含了各种各样的信息&#xff0c;从市场趋势和消费者行为到销售数据和供应链信息。对于企业而言&#xff0c;利用这些数据来做出明智的决策&#xff0c;提高效率和竞争力变得尤为重要。而商业智能&#…

Learn OpenGL 22 高级光照与Gamma校正

高级光照 Blinn-Phong 冯氏光照不仅对真实光照有很好的近似&#xff0c;而且性能也很高。但是它的镜面反射会在一些情况下出现问题&#xff0c;特别是物体反光度很低时&#xff0c;会导致大片&#xff08;粗糙的&#xff09;高光区域。下面这张图展示了当反光度为1.0时地板会…

JS+CSS3点击粒子烟花动画js特效

JSCSS3点击粒子烟花动画js特效 JSCSS3点击粒子烟花动画js特效

docker harbor.v2.9.2搭建镜像无法下载问题解决

在通过部署docker harbor时&#xff0c;采用的是离线包的方式&#xff0c;当解压压缩包后&#xff0c;执行prepare脚本步骤中有一步是要获取prepare:v2.9.2版本镜像 结果执行脚本时报如下错误&#xff1a; Unable to find image goharbor/prepare:v2.9.2 locally 这时候我们就…

若依ruoyi-vue中的文件上传和下载

文章目录 文件上传后端实现前端实现 文件下载后端实现前端实现 在若依&#xff08;Ruoyi&#xff09;框架中&#xff0c;结合 Vue 前端框架&#xff0c;文件的上传和下载通常使用以下方法实现&#xff1a; 文件上传 若依现成的功能里面没有文件上传&#xff0c;但是集成了文件…

探索智慧农业项目方案,开启农业智能化新篇章

1. 背景 随着科技的飞速发展和全球人口的不断增长&#xff0c;传统农业模式已难以满足日益增长的粮食和农产品需求。同时&#xff0c;气候变化、资源短缺等环境问题也对农业生产带来了巨大挑战。因此&#xff0c;智慧农业作为一种集成了现代信息技术和农业生产的创新模式&#…

位图与布隆过滤器

目录 一、位图 1、问题用位图来解决&#xff1a; 二、 布隆过滤器 1、将哈希与位图结合&#xff0c;即布隆过滤器 2.布隆过滤器的查找 3.布隆过滤器的删除 4.布隆过滤器优点 5、布隆过滤器缺陷 三、海量数据处理问题&#xff1a; 一、位图 问题1&#xff1a;给40亿个不…

【阅读论文】When Large Language Models Meet Vector Databases: A Survey

摘要 本调查探讨了大型语言模型&#xff08;LLM&#xff09;和向量数据库&#xff08;VecDB&#xff09;之间的协同潜力&#xff0c;这是一个新兴但迅速发展的研究领域。随着LLM的广泛应用&#xff0c;出现了许多挑战&#xff0c;包括产生虚构内容、知识过时、商业应用成本高昂…

day01_mysql_课后练习 - 参考答案

文章目录 day01_mysql_课后练习第1题第2题第3题第4题第5题 day01_mysql_课后练习 第1题 案例&#xff1a; 1、创建数据库day01_test01_library 2、创建表格books 字段名字段说明数据类型允许为空唯一b_id书编号int(11)否是b_name书名varchar&#xff08;50&#xff09;否否…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…

SAP SD模块影响MRP结果的几个因素

后台最近会收到小伙伴的私信说,我的销售订单已经下达了,但是MRP仍然没有跑出结果,没有跑出需求。遇到这种情况我们就需要一个个地方去进行分析,看哪里的数据存在问题,系统的配置存在问题导致的。接下来文章中将会分析SD销售模块哪些配置点会影响到MRP的运行。 1、首先遇到…

【Web】浅聊Hessian异常toString姿势学习复现

目录 前言 利用关键 调用分析 如何控制第一个字节 EXP 前言 Hessian CVE-2021-43297&#xff0c;本质是字符串和对象拼接导致隐式触发了该对象的 toString 方法&#xff0c;触发toString方法便可生万物&#xff0c;而后打法无穷也&#xff01; 这个CVE针对的是Hessian2I…

5G智能网关助力工业铸造设备监测升级

随着物联网技术的迅猛发展和工业4.0浪潮的推进&#xff0c;传统工业正面临着严峻的转型升级压力。在这一背景下&#xff0c;铸造行业——这一典型的传统重工业领域&#xff0c;也必须积极探索借助5G、物联网、边缘计算等技术提升生产经营效率的新路径。 本文就基于佰马合作伙伴…

C++初阶 | [九] list 及 其模拟实现

摘要&#xff1a;介绍 list 容器&#xff0c;list 模拟实现&#xff0c;list与vector的对比 list&#xff08;带头双向循环列表&#xff09; 导入&#xff1a;list 的成员函数基本上与 vector 类似&#xff0c;具体内容可以查看相关文档(cplusplus.com/reference/list/list/)&…

美食杂志制作秘籍:引领潮流,引领味蕾

美食杂志是一种介绍美食文化、烹饪技巧和美食体验的杂志&#xff0c;通过精美的图片和生动的文字&#xff0c;向读者展示各种美食的魅力。那么&#xff0c;如何制作一本既美观又实用的美食杂志呢&#xff1f; 首先&#xff0c;你需要选择一款适合你的制作软件。比如FLBOOK在线制…

网络电视盒子哪个品牌好?2024畅销电视盒子排行榜

电视盒子的品牌和产品非常多&#xff0c;让新手在选购时难度增大&#xff0c;大部分消费者在此时会选择参考销量排名情况&#xff0c;小编这次结合各个电商平台的销量和用户评价整理了电视盒子排行榜&#xff0c;想买电视盒子不知道网络电视盒子哪个品牌好可以收藏。 TOP 1.泰捷…

Model-Free Optimal Tracking Control via Critic-Only Q-Learning

Model-Free Optimal Tracking Control via Critic-Only Q-Learning Biao Luo, Member, IEEE, 2016&#xff0c;Derong Liu, Fellow, IEEE, Tingwen Huang, and Ding Wang, Member, IEEE 对非仿射非线性离散时间系统&#xff0c;提出model-free最优跟踪控制问题。仅有评价网络的…

算法刷题Day14 | 二叉树理论、递归遍历、迭代遍历、统一迭代

目录 0 引言1 递归遍历1.1 前序遍历1.2 后序遍历1.3 中序遍历 2 迭代遍历2.1 前序和后序2.2 中序 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题&#xff1a;算法刷题Day14 | 二叉树理论、递归遍历、迭代遍历、统一迭…