锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

DDD防腐层的设计

时间:2023-07-04 10:37:00 mb264防腐液位变送器

防腐层是在DDD它起着非常重要的作用。具体分析见本文。这里就不细说了,但是在Java如何设计代码中的防腐层?目前比较好的有以下几种。

  • 通过cglib的BeanCopier。
  • 通过Spring的BeanUtils。
  • 通过mapstruct。
  • 硬编码。

下面通过例子看优缺点,最后做出选择。现在有两个对象,一个是OriginOrder,一个是TargetOrder,需要把OriginOrder转化为TargetOrder。

cglib的BeanCopier

代码如下:

public class CglibBeanCopierConvertor { 
             private static final BeanCopier copier = BeanCopier.create(OriginalOrder.class, TargetOrder.class, false);      public static TargetOrder convert(OriginalOrder originalOrder) { 
                 TargetOrder targetOrder = new TargetOrder();         copier.copy(originalOrder, targetOrder, null);         return targetOrder;     } } 

cglib实现原理见文章

Spring的BeanUtils

代码如下:

public class SpringBeanUtilConvertor { 
             public static TargetOrder convert(OriginalOrder originalOrder){ 
                 TargetOrder targetOrder = new TargetOrder();         BeanUtils.copyProperties(originalOrder, targetOrder);         return targetOrder;     } } 

原理如下: https://blog.csdn.net/sosozha/article/details/80710174

mapstruct

代码如下:

@Mapper public interface MapStructConvertor { 
        
    MapStructConvertor CONVERTOR = Mappers.getMapper(MapStructConvertor.class);
    @Mappings({ 
        })
    TargetOrder convert(OriginalOrder originalOrder);
}

原理如下: https://juejin.cn/post/6844904199755415559

硬编码的方式

public class HardCodeConvertor { 
        
    public static TargetOrder convert(OriginalOrder originOrder){ 
        
        if (originOrder == null){ 
        
            return null;
        }
        TargetOrder targetOrder = new TargetOrder();
        targetOrder.setCode(originOrder.getCode());
        targetOrder.setBatchCode(originOrder.getBatchCode());
        targetOrder.setType(originOrder.getType());
        targetOrder.setOrderUserId(originOrder.getOrderUserId());
        targetOrder.setOrderDate(originOrder.getOrderDate());
        targetOrder.setPurchaseDate(originOrder.getPurchaseDate());
        targetOrder.setOrderComment(originOrder.getOrderComment());
        targetOrder.setProjectId(originOrder.getProjectId());
        targetOrder.setProjectType(originOrder.getProjectType());
        targetOrder.setProjectPhase(originOrder.getProjectPhase());
        targetOrder.setProjectOperatorVersion(originOrder.getProjectOperatorVersion());
        targetOrder.setOrganizationId(originOrder.getOrganizationId());
        targetOrder.setSupplierId(originOrder.getSupplierId());
        targetOrder.setWarehouseId(originOrder.getWarehouseId());
        targetOrder.setWarehouseType(originOrder.getWarehouseType());
        targetOrder.setWarehousePickupCode(originOrder.getWarehousePickupCode());
        targetOrder.setAllowMultipleDelivery(originOrder.getAllowMultipleDelivery());
        targetOrder.setSkuAmount(originOrder.getSkuAmount());
        targetOrder.setOriginalTotalAmount(originOrder.getOriginalTotalAmount());
        targetOrder.setCompositeAmount(originOrder.getCompositeAmount());
        targetOrder.setOriginalCompositeAmount(originOrder.getOriginalCompositeAmount());
        targetOrder.setTotalAmount(originOrder.getTotalAmount());
        targetOrder.setAuditStatus(originOrder.getAuditStatus());
        targetOrder.setAuditDate(originOrder.getAuditDate());
        targetOrder.setAuditVersion(originOrder.getAuditVersion());
        targetOrder.setStatus(originOrder.getStatus());
        targetOrder.setDeliveryFlag(originOrder.getDeliveryFlag());
        targetOrder.setSupplierConfirmDate(originOrder.getSupplierConfirmDate());
        targetOrder.setSupplierComment(originOrder.getSupplierComment());
        targetOrder.setCompleteDate(originOrder.getCompleteDate());
        targetOrder.setInvalidUserId(originOrder.getInvalidUserId());
        targetOrder.setInvalidDate(originOrder.getInvalidDate());
        targetOrder.setInvalidReasonCode(originOrder.getInvalidReasonCode());
        targetOrder.setInvalidComment(originOrder.getInvalidComment());
        targetOrder.setCancelDate(originOrder.getCancelDate());
        targetOrder.setCancelReasonCode(originOrder.getCancelReasonCode());
        targetOrder.setCancelComment(originOrder.getCancelComment());
        targetOrder.setAbort(originOrder.getAbort());
        targetOrder.setAbortDate(originOrder.getAbortDate());
        targetOrder.setAbortComment(originOrder.getAbortComment());
        targetOrder.setFreezeStatus(originOrder.getFreezeStatus());
        targetOrder.setParentId(originOrder.getParentId());
        targetOrder.setSplited(originOrder.getSplited());
        targetOrder.setItemTagId(originOrder.getItemTagId());
        targetOrder.setItemTagName(originOrder.getItemTagName());
        targetOrder.setRegionId(originOrder.getRegionId());
        targetOrder.setOrderCategory(originOrder.getOrderCategory());
        targetOrder.setOldAuditStatus(originOrder.getOldAuditStatus());
        targetOrder.setBidding(originOrder.getBidding());
        targetOrder.setJcReceiving(originOrder.getJcReceiving());
        targetOrder.setDeliveryMethod(originOrder.getDeliveryMethod());
        targetOrder.setDealCorporation(originOrder.getDealCorporation());
        targetOrder.setEvaluateStatus(originOrder.getEvaluateStatus());
        targetOrder.setTenantId(originOrder.getTenantId());
        targetOrder.setTenantSettleType(originOrder.getTenantSettleType());
        targetOrder.setBizSource(originOrder.getBizSource());
        targetOrder.setFreightAmount(originOrder.getFreightAmount());
        targetOrder.setFreightDiscountAmount(originOrder.getFreightDiscountAmount());
        targetOrder.setVersion(originOrder.getVersion());
        targetOrder.setAcceptance(originOrder.getAcceptance());
        targetOrder.setAcceptanceQuantity(originOrder.getAcceptanceQuantity());
        targetOrder.setSubmitType(originOrder.getSubmitType());
        targetOrder.setChannel(originOrder.getChannel());
        return targetOrder;
    }

四种方式性能分析

少量调用次数下

1次调用下:

threadHardCode consume time: 3
threadMapStruct consume time: 4
threadCglib consume time: 95
threadSpringBean consume time: 94

10次调用下:

threadHardCode consume time: 6
threadMapStruct consume time: 6
threadCglib consume time: 96
threadSpringBean consume time: 95

10000次调用下:

threadMapStruct consume time: 125
threadHardCode consume time: 131
threadCglib consume time: 221
threadSpringBean consume time: 220

1000000次调用下:

threadMapStruct consume time: 424
threadHardCode consume time: 435
threadCglib consume time: 452
threadSpringBean consume time: 456

从耗时来看,调用次数少的情况下,硬编码和mapStruct很接近,而cglib和BeanUtils是耗时很长,原因是硬编码和mapStruct在运行期直接执行的赋值操作,而cglib和BeanUtils还需要通过反射生成Convetor的字节码,但是生成之后会缓存起来,所以在调用次数达到百万以上时,耗时是很接近的。

四种方式优缺点分析

方式 优点 缺点 解决缺点的方案
cglib的BeanCopier 简单好用。 1. 少量调用下性能低。 2. ide无法跟踪到调用链路。3. 不同类型的字段无法赋值 4.字面上无法搜索到关键词 暂无解法
Spring的BeanUtils 简单好用。 1. 少量调用下性能低。 2. ide无法跟踪到调用链路。3. 不同类型的字段无法赋值 4.字面上无法搜索到关键词 暂无解法
mapstruct 性能高,相对简单好用 1. 字面上无法搜索到关键词。2. 编译之前无法看到调用链路,编译之后ide可以跟踪到调用链路 需要看调用链路时编译一次,但是代码有问题时无法编译通过
硬编码 性能高 手动编写,效率低下 可以通过工具或者ide插件来生成

从优缺点来看,我推荐硬编码+代码生成器,理由如下:

  1. ide无法跟踪到调用链路这个是无法接受的,因为但凡出了问题,比如变量值不正确等,排查问题解决问题是最重要的。
  2. 不同类型的字段无法赋值,这个在高质量的系统里是无法容忍的,比如DO对象的属性是Byte,转化后的属性枚举,这个cglib的BeanCopier和Spring的BeanUtils是无法接受的。
  3. 硬编码的手动编写可以通过工具、脚本或者ide的插件来生成,只需要一次生成,后面只需要改造就行了。

https://blog.csdn.net/vbnetfun/article/details/118632844
https://blog.csdn.net/loushuiyifan/article/details/82461955

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章