entitybuilder–一个简单的业务通用框架

关于业务通用框架的思考

业务系统是千差万别的,例如,保存、更新和删除订单,或者保存订单和保存客户,走的根本不是一个流程。但是,它们还是有共同点,它们的流程大致可以分成下面的几个部分:

entitybuilder--一个简单的业务通用框架
  1. 拿到增删改等操作所需的基础数据;
  2. 初始化基础数据;
  3. 对基础数据进行校验;
  4. 利用基础数据,构建出要进行增删改等操作的对象;
  5. 持久化或其他操作。

基于这一点,我试着抽取出一套适用于不同业务、不同用例、不同场景的通用业务框架。刚好,去年部门开始重构订单系统,我试着将自己的想法付诸行动。经过几次调整后,总算形成了一个简单的业务通用框架–entitybuilder。

当然, 我更多想表达的,是一种思想、一种规范,而非工具本身。如果真要说是框架,entitybuilder 就太简陋了。

entitybuilder 的结构

entitybuilder 包含三个主要部分,基础数据 base data、构建器 entity builder 和结果对象 result entity。我拿到了 base data,把它丢进 entity builder,entity builder 就会帮我构建出 result entity,拿到 result entity 后,我要持久化也行,直接返回给更上层调用者也行。

entity builder 构建 result entity 的过程被定义为:初始化->校验->构建。

entitybuilder--一个简单的业务通用框架

entitybuilder1.0–规范流程

基于上面的模型,也就有了 entitybuilder1.0,它的结构如下。

对调用者来说,只需要设置好基础数据,调用 build方法就能完成初始化、校验、构建,当然, EntityBuilder还支持仅作为校验器使用,因为有时我们并不需要结果对象,只需要校验基础数据就行。

对实现者来说,用户需要继承 AbstractEntityBuilder,并实现初始化、校验和构建方法。

entitybuilder--一个简单的业务通用框架

以订单保存为例,下面展示如何使用 entitybuilder。代码的调用非常简单,这里需要注意, EntityBuilder对象必须是多例的。

    public String save(DefaultOrderSaveCmd cmd) {
        // 获取构建器(多例的)
        EntityBuilder entityBuilder = getSaveEntityBuilder();

        // 设置基础数据
        entityBuilder.setBaseData(cmd);

        // 构建保存实体
        OrderSaveE entity = entityBuilder.build();

        // 持久化操作
        orderDao.save(entity);

        return entity.getId();
    }

entitybuilder2.0–多场景支持

entitybuilder1.0 只是规范了业务流程,在多场景方面还是存在问题。

一个业务用例可能会有不同的场景,例如,客户保存可能就不只一个入口,按照 entitybuilder1.0 的设计,我们需要将所有场景的逻辑都堆积到构建器中。显然,这是不合理的。

参考 spring 的 postprocessor,我在构建器中引入了校验器和处理器的支持。构建器中定义了用例的主流程,不同场景可以通过注册校验器和处理器来对主流程进行修饰。在 entitybuilder1.0 的基础上修改,得到以下结构:

entitybuilder--一个简单的业务通用框架

和 entitybuilder 1.0 相比,对调用者来说,可以通过注册验器和处理器来影响构建器的主流程,对构建器实现者来说,改为继承 AbstractFlexibleEntityBuilder

那么校验器和处理器如何影响主流程呢?下面通过一张图来说明。在 entitybuilder1.0 中,调用者无需知道构建器中的逻辑,现在却需要知道(有好有坏吧)。

entitybuilder--一个简单的业务通用框架

以订单保存为例,代码示例如下。

    public String save(DefaultOrderSaveCmd cmd) {
        // 获取构建器
        AbstractFlexibleEntityBuilder entityBuilder = getSaveEntityBuilder();

        // 设置基础数据
        entityBuilder.setBaseData(cmd);

        // 对构建器进行部分更改,例如注册处理器或检验器
        entityBuilder.registerValidator(myOrderSaveValidator);
        entityBuilder.registerEntityBuilderPostProcessor(myOrderSavePostProcessor);

        // 构建保存实体
        OrderSaveE entity = entityBuilder.build();

        // 持久化操作
        orderDao.save(entity);

        return entity.getId();
    }

基础数据的组成

entitybuilder 的可用性极大依赖于基础数据的规范。 在 entitybuilder 中,基础数据的成员属性应该包含两个部分:主体属性和关联对象。例如,订单的基础数据就包括了订单本身以及它的关联对象,如客户、操作人等。

entitybuilder--一个简单的业务通用框架

为什么要包含这两个部分呢?

构建器中包含了业务的大部分逻辑,我们需要调用各种通用方法,这些方法的入参对象无非就是主体属性或关联对象属性。基础数据对象将在 EntityBuilder 的整个生命周期中传递,通过它来传递关联对象,可以保证关联对象只需要初始化一次,从而减少重复 IO。

如果一开始放入构建器的基础数据对象中已经有关联对象了,那么,构建器也不会再去初始化它。这一点在批量构建时将非常有用。

事务控制

在 entitybuilder 的规范中,结果对象的持久化是在一个事务/方法中完成主体对象和关联对象的持久化,但是,在某个场景下,我们需要在事务中进行某些自定义操作,例如,订单保存完成后,向某个外部系统推送数据,推送失败,事务跟着回滚。

针对这种场景,也是可以支持的。事务中的自定义操作将作为函数的形式传递,在基础数据中设置好,持久化时就会执行它。

    @Override
    public String save(DefaultOrderSaveCmd cmd) {
        // 获取构建器
        AbstractFlexibleEntityBuilder entityBuilder = getSaveEntityBuilder();

        // 设置基础数据
        entityBuilder.setBaseData(cmd);

        // 对基础数据进行部分更改,例如设置保存事务中需要进行的操作
        cmd.addSaveConsumer(order -> {
            // 有的自定义操作需要放入保存事务,如果失败,订单数据也会回滚
            // 省略代码······
        });

        // 构建保存实体
        OrderSaveE entity = entityBuilder.build();

        // 持久化操作
        orderDao.save(entity);

        return entity.getId();
    }
    // @Transactional
    public String save(OrderSaveE entity) {
        // 保存订单
        // 省略代码······

        // 保存产品
        // 省略代码······

        // 保存附件
        // 省略代码······

        // 执行保存事务中的函数
        entity.getSaveConsumers().forEach(x -> x.accept(entity));

        return entity.getId();
    }

以上基本介绍完 entitybuilder。这里还是强调一点,我更多的是想表达一种思想、一种规范,因为作为工具,entitybuilder 还有很多需要改进的地方。

最后,感谢阅读。

参考资料

相关源码请移步:https://github.com/ZhangZiSheng001/zzs-code-thought/01-entitybuilder-demo

本文为原创文章,转载请附上原文出处链接:https://www.cnblogs.com/ZhangZiSheng001/p/14472782.html

Original: https://www.cnblogs.com/ZhangZiSheng001/p/14472782.html
Author: 子月生
Title: entitybuilder–一个简单的业务通用框架

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/575790/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 深入浅出的分析 Set集合

    作者:炸鸡可乐原文出处:www.pzblog.cn 一、摘要 关于 Set 接口,在实际开发中,其实很少用到,但是如果你出去面试,它可能依然是一个绕不开的话题。 言归正传,废话咱们…

    数据库 2023年6月14日
    086
  • 4_爬NMPA药监总局_动态加载_传ID

    http://scxk.nmpa.gov.cn:81/xk/ import requests url = ‘http://scxk.nmpa.gov.cn:81/xk/itowne…

    数据库 2023年6月11日
    090
  • CMU 15-445 Project 0 实现字典树

    原文链接:https://juejin.cn/post/7139572163371073543 项目准备 代码、手册 本文对应 2022 年的课程,Project 0 已经更新为实…

    数据库 2023年6月14日
    098
  • 内嵌h5调试神器-vConsole

    vConsole 一个轻量、可拓展、针对手机网页的前端开发者调试面板,可用于APP内嵌H5及其他调试H5的地方。 使用 方法一:cdn 方式引入 // 引入 // 初始化 var …

    数据库 2023年6月11日
    074
  • 图片防盗链

    如何避免别的网站直接通过本网站的url访问本网站资源 简单的防盗 我可以做到请求来的时候先看看当前请求是从哪个网站过来的如果是本网站那么正常访问如果是其他网站直接拒绝请求头里面有一…

    数据库 2023年6月14日
    079
  • django-ckeditor上传图片到七牛云OSS

    参考信息 django-ckeditor本地图片上传功能:https://www.jianshu.com/p/882cf85b604fdjango+ckeditor+七牛云,图片上…

    数据库 2023年6月9日
    085
  • 一文了解Cookie

    Cookie 什么是 Cookie? 先要了解HTTP是 无状态的Web服务器,什么是无状态呢?一次对话完成后下一次对话完全不知道上一次对话发生了什么。如果在Web服务器中只是用来…

    数据库 2023年6月11日
    097
  • MySQL数据库-数据表(中)

    分析:给 reader 表添加数据. INSERT INTO:插入数据,插入数据的时候会检查主键或者唯一索引,如果出现重复就会报错; 语法:INSERT INTO table_na…

    数据库 2023年6月11日
    0108
  • 【黄啊码】这种PHP验证码你值得拥有(注:支持中文)

    csharp;gutter:true; width = $width; $this->height = $height; $this->codeNum = $codeN…

    数据库 2023年6月16日
    094
  • 23种设计模式之分类总结

    关于设计模式的学习要告一段落了,学习的这一路上,也收到了不少小伙伴的留言,以及点赞给了我莫大的鼓励,我在这里谢谢大家的鼓励。。。 我会再接再厉,嘿嘿。。。 以上的话虽是真心话,但是…

    数据库 2023年6月6日
    0280
  • mysql事物

    MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些…

    数据库 2023年6月9日
    082
  • SpringMVC完整版详解

    1.回顾MVC 1.1什么是MVC MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。 是将业务逻辑、数据、显示分离的方法来组…

    数据库 2023年6月16日
    075
  • Redis学习

    Redis 因为没有指定配置文件 需配置 redis-server redis.windows.conf 之后自动启动 测试性能 redis-benchmark -p 6379 -…

    数据库 2023年6月16日
    077
  • MySQL提示sql_mode=only_full_group_by解决办法

    MySQL异常sql_mode=only_full_group_by 原因:在MySQL 5.7后MySQL默认开启了SQL_MODE严格模式,对数据进行严格校验。会报sql_mo…

    数据库 2023年6月14日
    090
  • Java面向对象(下)作业

    首先我把题目先列到这里,可以仔细看一下题。 (1)设计一个名为Geometric的几何图形的抽象类,该类包括: ①两个名为color、filled属性分别表示图形颜色和是否填充。 …

    数据库 2023年6月11日
    0141
  • SpringBoot整合WebService(实用版)

    SpringBoot整合WebService 简介 WebService就是一种跨编程语言和跨操作系统平台的远程调用技术 此处就不赘述WebService相关概念和原理了,可以参考…

    数据库 2023年6月16日
    0101
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球