我们在项目当中,经常会遇到实体拷贝的情况,必须把DO拷贝到BO, BO拷贝到VO等等,这个时候,如果我们还是单纯的使用get/set 会发现,代码可能会变得非常的臃肿,但不可置疑的是get/set不会有太大的坑。 所以实体拷贝工具有时候就成了程序的标配。今天就给大家介绍汇总一下常用的实体拷贝工具,并使用非常简单的例子来测试一下他们的性能,由于没有大量场景的测试,所以测试结果不代表最终结果,仅供大家参考。 还有就是我这里面汇总的工具,不像很多其他文章那样,都是一些比较老的工具,毕竟2020年了,这里囊括了dozer ,easyMapper, modelMapper等比较新的工具介绍给大家。

代码说明: 在下面的工具介绍中,我们会使用每种工具,拷贝一个简单的对象实体,并测试执行时间。所以我们先准备两个类结构一致的对象,然后给其中的一个对象赋值,将其拷贝给另一个对象。

源对象:

@Data
public class Person {private int id;private String name;private Boolean vipFlag;private BigDecimal price;private Date createTime;private LocalDateTime updateTime;
}

目标对象

@Data
public class PersonVO {private int id;private String name;private Boolean vipFlag;private BigDecimal price;private Date createTime;private LocalDateTime updateTime;
}

给Person对象赋值,然后通过下面的工具类拷贝到PersonVO中

public class BeanCopyDemo {@Testpublic void test() throws  Exception{// 先设置一个有值的对象Person p = new Person();p.setId(1);p.setName("张三");p.setPrice(new BigDecimal("100"));p.setVipFlag(true);p.setCreateTime(new Date());p.setUpdateTime(LocalDateTime.now());System.out.println(p);// 各工具的拷贝方法......}
}

一. apache BeanUtils:

这款工具不用多介绍了,相信很多人最开始做拷贝的时候都会用过,我这里不详细讲了,也极度不推荐大家使用,因为在阿里巴巴的编程规范中也已经不推荐使用这个方法了,原因就是效率太差,所以也不推荐大家使用,如果大家非要用apache的话,可以使用PropertyUtils, 效率会比这个工具要高一些。

这个类的用法给大家截个图:

这时候可以看到这个方法的调用已经有红线了,原因就是我安装的阿里巴巴插件检测到了这个方法,直接不建议使用了。 另外他执行拷贝所消耗的时间确实很长

依赖:

<dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version>
</dependency>

二. 使用spring中的BeanUtils

说下这个BeanUtils,要注意的是,他的类名和上面说的那个类名是一模一样的,区别就是一个是apache的,一个是spring的, spring的这个只要你的项目中有spring就可以用,不需要单独导包。同时要注意他和上面那个类的用法十分相似,区别就是参数是相反的,另外这个类的执行效率也还不错,所以如果不想引入其他依赖的时候,可以使用这个类来替代上面的apache的方式。
        // 方式2: 使用springBeanUtilsstart = System.currentTimeMillis();p2 = new PersonVO();org.springframework.beans.BeanUtils.copyProperties(p, p2);// spring BeanUtils 耗时:56毫秒System.out.println("spring BeanUtils 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p2);System.out.println("----------------------------");

这段代码和上面的是接上的,由于两个类名相同,这里只能使用全类名进行调用,尤其zhuyi9参数顺序,有值的在前面,目标在后面。和上面的方法区分开。

三.  cglib BeanCopier

接下来介绍的是cglib中的BeanCopier类,这个是cglib的, cglib我想大家应该知道吧,不知道的是不是也有点耳熟,一般面试的时候经常会被问道,spring中的aop的实现原理,一种是使用java中的动态代理,还有是cglib,cglib是通过底层字节码的方式实现的。同理他里边的BeanCopier在拷贝类的时候也是通过字节码的方式实现的,所以效率很高。不夸张的说,这个类应该是众多实体拷贝的方式中综合成绩最高的,我参考的很多其他文章也都是这个类的效率第一。 所以如果对于效率要求比较高的情况下,建议选择这个类,同时要注意,这个类在使用的时候有一个初始化的过程,我们可以把初始化的对象缓存起来,网上有比较多的案例,大家可以参考,去掉初始化的时间,我用这个类拷贝的结果是 0毫秒,相当于瞬间完成。

         // 方式3: 使用BeanCopier 是cglib提供的p2 = new PersonVO();start = System.currentTimeMillis();// cglib BeanCopier 不算初始化耗时:0毫秒 算上初始化40毫秒BeanCopier beanCopier = BeanCopier.create(Person.class, PersonVO.class, false);// p 是源  p2 是目标beanCopier.copy(p, p2, null);System.out.println("cglib BeanCopier 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p2);System.out.println("----------------------------");

四. Dozer

dozer: 这是一个实体拷贝的框架,相当于是专门干这件事的,我相信应该有不少朋友用过,因为我们在实体拷贝的过程中一直存在一个痛点就是深拷贝。上面几种工具都是做的浅拷贝,相当于你的类中如果还嵌套了其他对象是拷贝不了的。而dozer是支持深拷贝的,并且支持不同字段名名字的映射。比如你想把address 拷贝到  addr 上这种场景也是支持的。同时dozer有一个问题,在这必须提一下,就是dozer本身不支持jdk8 中的LocalDateTime的,使用这个类型会报错。如果非要使用,我们可以在依赖一个dozer支持jdk8的插件,所以比较麻烦,另外dozer的效率确实不高,感觉有点太重量级了,也有点老了,整体实力和第一个差不多。

依赖:

<!-- dozer -->
<dependency><groupId>net.sf.dozer</groupId><artifactId>dozer</artifactId><version>5.4.0</version>
</dependency>
<dependency><groupId>io.craftsman</groupId><artifactId>dozer-jdk8-support</artifactId><version>1.0.6</version>
</dependency>

案例:

//方式4: dozer: 一个实体拷贝框架,支持深拷贝,可自定义映射(名称不同的字段间进行拷贝)// 需引入jar包,需兼容jdk8// 并且不支持localDateTimeDozerBeanMapper mapper = new DozerBeanMapper();mapper.setMappingFiles(Collections.singletonList("dozerJdk8Converters.xml"));start = System.currentTimeMillis();PersonVO p3 = mapper.map(p, PersonVO.class);// dozer 耗时:119毫秒System.out.println("dozer 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p3);

五. ModelMapper.

这也是一个实体拷贝类框架,需要引入依赖, 支持自定义映射, 支持List, Map拷贝,用法和dozer极为相似,在我的测试中效果表现很好,很快。比较推荐。

依赖:

<dependency><groupId>org.modelmapper</groupId><artifactId>modelmapper</artifactId><version>2.3.0</version>
</dependency>

用法:

        // 方式5: ModelMap// 需引入jar: org.modelmapper// 支持自定义映射,支持List mapstart = System.currentTimeMillis();ModelMapper modelMapper = new ModelMapper();PersonVO p4 = modelMapper.map(p, PersonVO.class);// modelMapper 耗时:37毫秒System.out.println("modelMapper 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p4);

拷贝集合用法演示:

List<EventDO> eventList = eventService.list(new LambdaQueryWrapper<EventDO>().in(EventDO::getEventCode, eventCodeArr));
ModelMapper modelMapper = new ModelMapper();
List<EvenVO>list = modelMapper.map(eventList, new TypeToken<List<EventVO>>() {}.getType());

六. EasyMapper用法:

easyMapper也是干这个活的,百度出品的,但是说实话效率没有ModeMapper快,比dozer快

详细用法:

http://neoremind.com/2016/08/easy-mapper-%E4%B8%80%E4%B8%AA%E7%81%B5%E6%B4%BB%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BDbean-mapping%E7%B1%BB%E5%BA%93/

引入依赖:

<dependency><groupId>com.baidu.unbiz</groupId><artifactId>easy-mapper</artifactId><version>1.0.4</version>
</dependency>

用法:

// 方式6: EasyMapper:// http://neoremind.com/2016/08/easy-mapper-%E4%B8%80%E4%B8%AA%E7%81%B5%E6%B4%BB%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BDbean-mapping%E7%B1%BB%E5%BA%93/start = System.currentTimeMillis();PersonVO p5 = MapperFactory.getCopyByRefMapper().mapClass(Person.class, PersonVO.class).registerAndMap(p, PersonVO.class);// easyMapper 耗时:88毫秒System.out.println("easyMapper 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p5);

七. orika: 表现也很一般。

引入依赖:

         <dependency><groupId>ma.glasnost.orika</groupId><artifactId>orika-core</artifactId><version>1.5.2</version><!-- or latest version --></dependency>

用法:

// 6. orika:125msstart = System.currentTimeMillis();DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();MapperFacade orikaMapper = mapperFactory.getMapperFacade();PersonVO p6 = orikaMapper.map(p, PersonVO.class);System.out.println("orika 耗时:" + (System.currentTimeMillis() - start) + "毫秒");System.out.println("拷贝之后结果:" + p6);

好了,目前比较主流的拷贝方法就大家介绍到这里。

如果追求速度,果断选择 cdlib,  并将初始化过程缓存起来,方便复用

如果追求实用方便,能深拷贝,自定义拷贝,拷贝集合,推荐选择ModelMapper.

本测试结果仅供参考, 未进行复杂多维度多条件多场景测试,不代表权威观点。

实体拷贝工具大汇总,你还在用BeanUtils? 赶紧来学一学吧相关推荐

  1. 免费H5页面制作工具大汇总

    营销代有手段出,各领风骚数百天.要说现在哪些营销方式最能传播,屡屡刷爆朋友圈的H5页面肯定就是首当其冲的,提到H5页面,就立马想到"围住神经猫",上线微信朋友圈3天的时间便创造了用 ...

  2. .NET开发常用工具大汇总

    1.Visual Studio Visual Studio Productivity Power tool:Visual Studio专业版(及以上)的扩展,具有丰富的功能,如快速查找,导航解决方案, ...

  3. IOS开发工具大汇总(一)

    1.crash分析工具 1.1  lldb+汇编分析: 最原生也是最强大的工具 1.2  Cycript: 参考文章:http://www.wildpointer.cn/ios-security-cy ...

  4. 年轻人不讲武德!200个网络渗透测试工具大汇总

    最近有粉丝私信我说能不能写一期资料整理的文章 那么....它来了! 以下工具适合渗透测试人员,安全研究人员. 可以通过以下命令检查所有的工具: git clone --recursive https: ...

  5. Java开源建站工具大汇总

    美国程序员Jon Scott Stevens,公布了他的创业公司所使用的开发工具清单.    他的语言平台是Java,开发项目是一个网站(还未上线).所用到的工具都是开源的, 可以免费得到.    在 ...

  6. 画出漂亮的神经网络图,神经网络可视化工具大汇总

    分享几款画神经网络图神器,喜欢欢迎点赞.关注.收藏. 1. draw_convnet 一个用于画卷积神经网络的Python脚本 https://github.com/gwding/draw_convn ...

  7. 视频虚拟主播怎们搞?体验报告全记录;一图掌握SD应用精髓;Chat效率工具大汇总;品牌营销进入AI时代 | ShowMeAI日报

  8. Windows中常用文件拷贝工具的评测和对比 1

    对于Windows用户,拷贝文件是再常用不过的功能.打开文件浏览器(FileExplorer),把一个盘符的一个文件夹拖拽到另一个盘符下面是非常简单的操作.这样的文件拖拽操作在两端都是本地盘的情况下速 ...

  9. 中文实体命名识别工具使用汇总:Stanza、LAC、Ltp、Hanlp、foolnltk、NLTK、BosonNLP

    实体命名识别 相关知识 Stanford CoreNLP 命名实体识别 一.简介: 二.java版本使用 三.python版本使用 NLTK 命名实体识别 一.简介: 二.搭建环境 三.nltk使用 ...

最新文章

  1. 路径名导致的异常:javax.imageio.IIOException: Can‘t read input file!
  2. ROS系统 创建工作空间与功能包
  3. 三步修改CodeBlocks主题
  4. 2.5.jieba分词工具、Jieba安装、全模式/精确模式、添加自定义词典、关键词抽取、词性标注、词云展示
  5. 使用WIM格式进行WES 7 (windows embedded standard )的安装
  6. XMind软件简易使用教程
  7. 2013Esri全球用户大会QA之Web GIS
  8. python实现登录抓取_[Python]网络爬虫(五):利用POST方式登录账号抓取
  9. OpenGL开启Gouraud明暗处理,减少马赫夫效应
  10. java 调用 yed 绘制 流程图_用 yEd Graph Editor 绘制流程图(2)
  11. Java程序员面试笔试宝典-数据库原理(三)
  12. 计算机无法设置双屏显示,win10无法设置双屏显示怎么办_win10系统设置双屏显示失败如何解决...
  13. AMC数学考试能用计算机吗,重大调整!今年美国数学竞赛AMC考试时间有变化!
  14. pandas用法小结
  15. 蓝桥杯java备赛Day3——跳马
  16. python中_x、__x、__xx__的区别
  17. Hibernate Criteria对象详解(条件查询)
  18. C++入门第一阶段——基础篇
  19. 【附源码】计算机毕业设计JAVA个性化推荐的扬州农业文化旅游管理平台
  20. C# SuperSocket 手把手教你入门 傻瓜教程---1(服务器单向接收客户端发送数据)

热门文章

  1. layui调用自定义方法提示未定义的解决办法
  2. 某知名IT公司最近的一道笔试编程题
  3. iphone 开发 窗口(UIWindow) 与视图(UIView)之间以及整个程序间的关系,深层解析
  4. 【天池学习赛】淘宝母婴购物数据可视化分析
  5. linux中top指令,Linux下top命令详解
  6. 苹果最新财报看点:中国区销量下滑
  7. echarts展示国内各省各市地图
  8. 推箱子经典游戏源码 附成品 易语言源码
  9. 【老生谈算法】matlab绘制三维等高线地形图——三维等高线
  10. PADS Layout VX.2.3 出Gerber文件时遇到一个奇怪的现象