zoukankan      html  css  js  c++  java
  • SpringBoot 如何进行对象复制

    首先我们看看为什么需要对象复制?

    为什么需要对象复制

    image-20210906145134173

    如上,是我们平时开发中最常见的三层MVC架构模型,编辑操作时Controller层接收到前端传来的DTO对象,在Service层需要将DTO转换成DO,然后在数据库中保存。查询操作时Service层查询到DO对象后需要将DO对象转换成VO对象,然后通过Controller层返回给前端进行渲染。

    这中间会涉及到大量的对象转换,很明显我们不能直接使用getter/setter复制对象属性,这看上去太low了。想象一下你业务逻辑中充斥着大量的getter&setter,代码评审时老鸟们会如何笑话你?

    image-20210716084136689

    所以我们必须要找一个第三方工具来帮我们实现对象转换。

    看到这里有同学可能会问,为什么不能前后端都统一使用DO对象呢?这样就不存在对象转换呀?设想一下如果我们不想定义 DTO 和 VO,直接将 DO 用到数据访问层、服务层、控制层和外部访问接口上。此时该表删除或则修改一个字段,DO 必须同步修改,这种修改将会影响到各层,这并不符合高内聚低耦合的原则。通过定义不同的 DTO 可以控制对不同系统暴露不同的属性,通过属性映射还可以实现具体的字段名称的隐藏。不同业务使用不同的模型,当一个业务发生变更需要修改字段时,不需要考虑对其它业务的影响,如果使用同一个对象则可能因为 “不敢乱改” 而产生很多不优雅的兼容性行为。

    对象复制工具类推荐

    对象复制的类库工具有很多,除了常见的Apache的BeanUtils,Spring的BeanUtilsCglib BeanCopier,还有重量级组件MapStructOrikaDozerModelMapper等。

    如果没有特殊要求,这些工具类都可以直接使用,除了Apache的BeanUtils。原因在于Apache BeanUtils底层源码为了追求完美,加了过多的包装,使用了很多反射,做了很多校验,所以导致性能较差,并在阿里巴巴开发手册上强制规定避免使用 Apache BeanUtils。

    强制规定避免使用 Apache BeanUtils

    至于剩下的重量级组件,综合考虑其性能还有使用的易用性,我这里更推荐使用Orika。Orika底层采用了javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件,在速度上比使用反射进行赋值会快很多。

    国外大神 baeldung 已经对常见的组件性能进行过详细测试,大家可以通过 https://www.baeldung.com/java-performance-mapping-frameworks 查看。

    Orika基本使用

    要使用Orika很简单,只需要简单四步:

    1. 引入依赖
    <dependency>
      <groupId>ma.glasnost.orika</groupId>
      <artifactId>orika-core</artifactId>
      <version>1.5.4</version>
    </dependency>
    1. 构造一个MapperFactory
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();  
    1. 注册字段映射
    mapperFactory.classMap(SourceClass.class, TargetClass.class)  
       .field("firstName", "givenName")
       .field("lastName", "sirName")
       .byDefault()
       .register();
    

    当字段名在两个实体不一致时可以通过.field()方法进行映射,如果字段名都一样则可省略,byDefault()方法用于注册名称相同的属性,如果不希望某个字段参与映射,可以使用exclude方法。

    经过上面四步我们就完成了SourceClass到TargetClass的转换。至于Orika的其他使用方法大家可以参考 http://orika-mapper.github.io/orika-docs/index.html看到这里,肯定有粉丝会说:你这推荐的啥玩意呀,这个Orika使用也不简单呀,每次都要这先创建MapperFactory,建立字段映射关系,才能进行映射转换。

    别急,我这里给你准备了一个工具类OrikaUtils,你可以通过文末github仓库获取。

    它提供了五个公共方法:

    image-20210903151829872

    分别对应:

    1. 字段一致实体转换
    2. 字段不一致实体转换(需要字段映射)
    3. 字段一致集合转换
    4. 字段不一致集合转换(需要字段映射)
    5. 字段属性转换注册

    接下来我们通过单元测试案例重点介绍此工具类的使用。

    Orika工具类使用文档

    先准备两个基础实体类,Student,Teacher。

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
        private String id;
        private String name;
        private String email;
    }
    

    此时由于对字段做了映射,可以将email映射到emailAddress。注意这里的refMap中key放置的是源实体的属性,而value放置的是目标实体的属性,不要弄反了。

    小结

    在MVC架构中肯定少不了需要用到对象复制,属性转换的功能,借用Orika组件,可以很简单实现这些功能。本文在Orika的基础上封装了工具类,进一步简化了Orika的操作,希望对各位有所帮助。

  • 相关阅读:
    DS博客作业03--栈和队列
    DS博客作业02--线性表
    DS博客作业01--日期抽象数据类型设计与实现
    C语言博客作业06--结构体&文件
    DS博客作业08--课程总结
    DS博客作业07--查找
    DS博客作业06--图
    DS博客作业05--树
    DS博客大作业--树 (陈梓灿组)
    DS博客作业03--栈和队列
  • 原文地址:https://www.cnblogs.com/aishangJava/p/15333476.html
Copyright © 2011-2022 走看看