12种Bean转换

来源:再见 BeanUtils!性能真拉跨!

  • 一、前言

  • 二、性能测试对比

  • 三、12种转换案例

    • 1. get\set

    • 2. json2Json

    • 3. Apache copyProperties

    • 4. Spring copyProperties

    • 5. Bean Mapping

    • 6. Bean Mapping ASM

    • 7. BeanCopier

    • 8. Orika

    • 9. Dozer

    • 10. ModelMapper

    • 11. JMapper

    • 12. MapStruct

  • 四、总结

  • 五、系列推荐

一、前言

为哈么,你的代码也就仅仅是能用而已?

没有技术深度、短缺知识储备、匮乏经验积累的前提下,怎么写代码?百度呀,遇到问题这搜一点,那查一块,不管它是什么原理还是适合哪种场景,先粘贴到自己的工程里,看,能跑了,能跑就行。那这样的代码也就仅仅是能用程度的交付,根本没有一定的质量保证,也更别提数据结构、算法逻辑和设计模式了,那看的编程资料刷的LeetCode,全歇菜了。

当你感觉看了很多资料又不会用的时候,会说什么,真卷,都学到这样了。但其实我并不觉对技术的深度挖掘、梳理全套的知识体系,一点点耕耘一点点收获是在卷。反而把看技术视频当成看电影一样轻松,不写案例就以为书看会了的爽,没有意义的缺少脑力思考机械式体力重复,才是卷,甚至很卷。

就像让你用一个属性拷贝工具,把vo转成dto,你用了哪呢,是 Apache 的还是 Spring 的,还是其他的什么,哪个效率最高?接下来我们来用数据验证下,并提供出各种案例的使用对比

二、性能测试对比

在 Java 系统工程开发过程中,都会有各个层之间的对象转换,比如  VO、DTO、PO、VO 等,而如果都是手动get、set又太浪费时间,还可能操作错误,所以选择一个自动化工具会更加方便。

目前我整理出,用于对象属性转换有12种,包括:普通的getset、json2Json、Apache属性拷贝、Spring属性拷贝、bean-mapping、bean-mapping-asm、BeanCopier、Orika、Dozer、ModelMapper、JMapper、MapStruct 接下来我们分别测试这11种属性转换操作分别在一百次一千次一万次十万次一百万次时候的性能时间对比。

BeanUtils.copyProperties 是大家代码里最常出现的工具类,但只要你不把它用错成 Apache 包下的,而是使用 Spring 提供的,就基本还不会对性能造成多大影响。

  • 但如果说性能更好,可替代手动get、set的,还是 MapStruct 更好用,因为它本身就是在编译期生成get、set代码,和我们写get、set一样。

  • 其他一些组件包主要基于 AOPASMCGlib,的技术手段实现的,所以也会有相应的性能损耗。

三、12种转换案例

 

源码:https://github.com/fuzhengwei/guide-vo2dto

描述:在案例工程下创建 interfaces.assembler 包,定义 IAssembler<SOURCE, TARGET>#sourceToTarget(SOURCE var) 接口,提供不同方式的对象转换操作类实现,学习的过程中可以直接下载运行调试。

1. get\set

@Component
public class GetSetAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();userDTO.setUserId(var.getUserId());userDTO.setUserNickName(var.getUserNickName());userDTO.setCreateTime(var.getCreateTime());return userDTO;}
}
  • 推荐:★★★☆☆

  • 性能:★★★★★

  • 手段:手写

  • 点评:其实这种方式也是日常使用的最多的,性能肯定是杠杠的,就是操作起来有点麻烦。尤其是一大堆属性的 VO 对象转换为 DTO 对象时候。但其实也有一些快捷的操作方式,比如你可以通过 Shift+Alt 选中所有属性,Shift+Tab 归并到一列,接下来在使用 Alt 选中这一列,批量操作粘贴 userDTO.set 以及快捷键大写属性首字母,最后切换到结尾补充括号和分号,最终格式化一下就搞定了。

2. json2Json

@Component
public class Json2JsonAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {String strJson = JSON.toJSONString(var);return JSON.parseObject(strJson, UserDTO.class);}
}
  • 推荐:☆☆☆☆☆

  • 性能:★☆☆☆☆

  • 手段:把对象转JSON串,再把JSON转另外一个对象

  • 点评:这么写多半有点烧!

3. Apache copyProperties

@Component
public class ApacheCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();try {BeanUtils.copyProperties(userDTO, var);} catch (IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}return userDTO;}
}
  • 推荐:☆☆☆☆☆

  • 性能:★☆☆☆☆

  • 手段:Introspector 机制获取到类的属性来进行赋值操作

  • 点评:有坑,兼容性交差,不建议使用

4. Spring copyProperties

@Component
public class SpringCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();BeanUtils.copyProperties(var, userDTO);return userDTO;}
}
  • 推荐:★★★☆☆

  • 性能:★★★★☆

  • 手段:Introspector机制获取到类的属性来进行赋值操作

  • 点评:同样是反射的属性拷贝,Spring 提供的 copyProperties 要比 Apache 好用的多,只要你不用错,基本不会有啥问题。

5. Bean Mapping

@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();BeanUtil.copyProperties(var, userDTO);return userDTO;}
}
  • 推荐:★★☆☆☆

  • 性能:★★★☆☆

  • 手段:属性拷贝

  • 点评:性能一般

6. Bean Mapping ASM

@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();BeanUtil.copyProperties(var, userDTO);return userDTO;}
}
  • 推荐:★★★☆☆

  • 性能:★★★★☆

  • 手段:基于ASM字节码框架实现

  • 点评:与普通的 Bean Mapping 相比,性能有所提升,可以使用。

7. BeanCopier

@Component
public class BeanCopierAssembler implements IAssembler<UserVO, UserDTO> {@Overridepublic UserDTO sourceToTarget(UserVO var) {UserDTO userDTO = new UserDTO();BeanCopier beanCopier = BeanCopier.create(var.getClass(), userDTO.getClass(), false);beanCopier.copy(var, userDTO, null);return userDTO;}
}
  • 推荐:★★★☆☆

  • 性能:★★★★☆

  • 手段:基于CGlib字节码操作生成get、set方法

  • 点评:整体性能很不错,使用也不复杂,可以使用

8. Orika

@Component
public class OrikaAssembler implements IAssembler<UserVO, UserDTO> {/*** 构造一个MapperFactory*/private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();static {mapperFactory.classMap(UserDTO.class, UserVO.class).field("userId", "userId")  // 字段不一致时可以指定.byDefault().register();}@Overridepublic UserDTO sourceToTarget(UserVO var) {return mapperFactory.getMapperFacade().map(var, UserDTO.class);}
}
  • 官网:https://orika-mapper.github.io/orika-docs/

  • 推荐:★★☆☆☆

  • 性能:★★★☆☆

  • 手段:基于字节码生成映射对象

  • 点评:测试性能不是太突出,如果使用的话需要把 MapperFactory 的构建优化成 Bean 对象

9. Dozer

@Component
public class DozerAssembler implements IAssembler<UserVO, UserDTO> {private static DozerBeanMapper mapper = new DozerBeanMapper();@Overridepublic UserDTO sourceToTarget(UserVO var) {return mapper.map(var, UserDTO.class);}
}
  • 官网:http://dozer.sourceforge.net/documentation/gettingstarted.html

  • 推荐:★☆☆☆☆

  • 性能:★★☆☆☆

  • 手段:属性映射框架,递归的方式复制对象

  • 点评:性能有点差,不建议使用

10. ModelMapper

@Component
public class ModelMapperAssembler implements IAssembler<UserVO, UserDTO> {private static ModelMapper modelMapper = new ModelMapper();static {modelMapper.addMappings(new PropertyMap<UserVO, UserDTO>() {@Overrideprotected void configure() {// 属性值不一样可以自己操作map().setUserId(source.getUserId());}});}@Overridepublic UserDTO sourceToTarget(UserVO var) {return modelMapper.map(var, UserDTO.class);}
}
  • 官网:http://modelmapper.org

  • 推荐:★★★☆☆

  • 性能:★★★☆☆

  • 手段:基于ASM字节码实现

  • 点评:转换对象数量较少时性能不错,如果同时大批量转换对象,性能有所下降

11. JMapper

JMapper<UserDTO, UserVO> jMapper = new JMapper<>(UserDTO.class, UserVO.class, new JMapperAPI().add(JMapperAPI.mappedClass(UserDTO.class).add(JMapperAPI.attribute("userId").value("userId")).add(JMapperAPI.attribute("userNickName").value("userNickName")).add(JMapperAPI.attribute("createTime").value("createTime"))));
  • 官网:https://github.com/jmapper-framework/jmapper-core/wiki

  • 推荐:★★★★☆

  • 性能:★★★★★

  • 手段:Elegance, high performance and robustness all in one java bean mapper

  • 点评:速度真心可以,不过结合 SpringBoot 感觉有的一点点麻烦,可能姿势不对

12. MapStruct

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface UserDTOMapping extends IMapping<UserVO, UserDTO> {/** 用于测试的单例 */IMapping<UserVO, UserDTO> INSTANCE = Mappers.getMapper(UserDTOMapping.class);@Mapping(target = "userId", source = "userId")@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")@OverrideUserDTO sourceToTarget(UserVO var1);@Mapping(target = "userId", source = "userId")@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")@OverrideUserVO targetToSource(UserDTO var1);}
  • 官网:https://github.com/mapstruct/mapstruct

  • 推荐:★★★★★

  • 性能:★★★★★

  • 手段:直接在编译期生成对应的get、set,像手写的代码一样

  • 点评:速度很快,不需要到运行期处理,结合到框架中使用方便

四、总结

  • 其实对象属性转换的操作无非是基于反射、AOP、CGlib、ASM、Javassist 在编译时和运行期进行处理,再有好的思路就是在编译前生成出对应的get、set,就像手写出来的一样。

  • 所以我更推荐我喜欢的 MapStruct,这货用起来还是比较舒服的,一种是来自于功能上的拓展性,易用性和兼容性。

  • 无论哪种使用,都要做一下完整的测试和验证,不要上来就复制粘贴,否则你可能早早的就把挖好坑了,当然不一定是哪个兄弟来填坑了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上海人工智能再出重磅!寒武纪科技发布新一代云端AI芯片,联想、曙光、科大讯飞发布相关应用...

来源&#xff1a;文汇网 作者&#xff1a;许琦敏、郭超豪峰值功耗不超过110瓦&#xff0c;等效理论峰值速度可达每秒166.4万亿次定点运算。寒武纪科技在上海发布了中国第一款云端智能芯片——Cambricon MLU100芯片和板卡产品、寒武纪1M终端智能处理器IP产品。联想、曙光和科大…

OD 快捷键使用大全。非常详细( 游戏逆向分析必看 )+ OD 断点 使用大全

From&#xff1a;https://www.cnblogs.com/YiShen/p/9742872.html OllyDBG 快捷键 OllyDbg 窗口通用快捷键 快捷键    功能      Ctrl F2重启程序&#xff0c;即重新启动被调试程序&#xff08; 重新载入程序 &#xff09;。如果当前没有调试的程序&#xff0c;Oll…

电子发票中数字签名的提取解析

前言 随着电子信息技术的发展与成熟&#xff0c;加上国家的大力推广&#xff0c;电子发票已经开始慢慢取代纸质发票。相比传统的纸质发票&#xff0c;电子发票除了绿色环保&#xff0c;节约成本之外&#xff0c;更重要的是电子发票采取电子签章实现发票签名、电子盖章&#xff…

无人车、超级高铁、智慧城市......这是一份来自未来的出行报告

来源&#xff1a;机器之能 作者&#xff1a;Charles McLellan 编译&#xff1a;王宇欣在新兴技术的驱动下&#xff0c;运输业即将迎来第二春。虽然个中细节还需打磨&#xff0c;但未来的运输系统必然会实现数据驱动、彼此相关联、高度自动化。有关技术与运输业未来的文章比比皆…

在 VC++ 中使用 内联汇编

From&#xff1a;https://blog.csdn.net/root19881111/article/details/8450266 VC内联汇编(MSDN相关内容完整翻译)&#xff1a;http://www.cppblog.com/xingkongyun/archive/2008/12/21/70003.html 调 call 和 偷功能 时&#xff0c;VC中内联汇编容易产生的错误&#xff1a;…

OFD 版式技术解析系列(一):开篇

在版式电子文件领域&#xff0c;大家比较熟悉的就是 PDF(Portable Document Format)格式&#xff0c;该格式由 Adobe 公司在 1992 年发布&#xff0c;迄今已经有 28 个年头&#xff0c;2008 年 7 月 1 日&#xff0c;IS 组织正式发布 PDF 的国际标准&#xff0c;PDF 成为了独立…

无人驾驶急需解决:规划控制和传感器价格高两大问题

来源&#xff1a;AI科技大本营 作者 &#xff1a;Mavis2017 年百度 AI 开发者大会上&#xff0c;现场视频连线了正乘坐无人驾驶汽车行驶在五环上朝会场赶来的李彦宏&#xff0c;他坐在副驾驶上解说&#xff0c;身边司机的双手并没有触碰方向盘&#xff0c;也正是因为这句话&am…

CString 与 LPCWSTR、LPSTR、char*、LPWSTR 等类型的转换

From&#xff1a;https://www.cnblogs.com/leanee/articles/2940088.html char [] 到 LPWSTR转换的一个具体应用&#xff1a;http://www.cppblog.com/lateCpp/articles/153358.html CString详细讲解&#xff1a;https://blog.csdn.net/qq_41786318/article/details/81989217 …

ofd电子文档内容分析工具(分析文档、签章和证书)

前言 ofd是国家文档标准&#xff0c;其对标的文档格式是pdf。ofd文档是容器格式文件&#xff0c;ofd其实就是压缩包。将ofd文件后缀改为.zip&#xff0c;解压后可看到文件包含的内容。 加入QQ交流群&#xff1a;618168615。获取下载程序。 ofd文件解压后&#xff0c;可以看到…

关于信任

[caption id"attachment_349" align"alignnone" width"374" caption"Trust is the most important thing to the team!"][/caption] 偶然间看到一张截图&#xff0c;是杭州小马哥不知何年何月何地做的show&#xff0c;这句话从他嘴里讲…

ES的安装和RestClient的操作

目录 初识elasticsearch 什么是elasticsearch elasticsearch的发展 Lucene的优缺点 elasticsearch的优势 倒排索引 es与mysql的概念对比 文档 索引 概念对比 架构 安装es 安装kibana 安装ik分词器 分词器 安装ik分词器 ik分词器的拓展和停用词典 操作索引库…

深度 | 智慧•城市,基于国际视野下的思考

来源&#xff1a;智慧城市决策参考智慧城市的兴起&#xff0c;得益于ICT技术的迅猛发展。经过这些年国内外诸多城市的探索和实践&#xff0c;智慧城市已经从最初的营销概念&#xff0c;逐渐发展成为一种支持城市发展的新理念。然而在实际应用中&#xff0c;智慧城市的内涵仍然是…

__cdecl、__stdcall、__fastcall 与 __pascal 浅析

X86调用约定 calling convention&#xff1a;https://www.cnblogs.com/shangdawei/p/3323252.html__cdecl、__stdcall、__fastcall 与 __pascal 浅析&#xff1a;https://www.cnblogs.com/yenyuloong/p/9626658.html王爽 汇编语言第三版 第9章 转移指令的原理&#xff1a;https…

全文详解:「深度学习」如何协助处理医疗中的「数据难题」

原文来源&#xff1a;WordPress作者&#xff1a;Luke Oakden-Rayner「雷克世界」编译&#xff1a;嗯~是阿童木呀、KABUDA、EVA医疗数据很难处理。在医学成像中&#xff0c;数据存储&#xff08;档案&#xff09;是基于临床假设进行操作的。不幸的是&#xff0c;这意味着当你想提…

Android应用程序变量

Android应用程序开发中&#xff0c;有的时候我们在应用程序的任何一个地方都需要访问一个全局变量&#xff0c;也就是在任何一个Activity中都可以访问的变量。它不会因为Activity的生命周期结束而消失。要实现应用程序级的变量&#xff0c;我们可以通过Application这个类来实现…

百度谷歌等联合推出机器学习基准 加速AI软硬件发展

来源&#xff1a;中国新闻网5月2日&#xff0c;由包括百度、谷歌、斯坦福大学、哈佛大学在内的多家企业和高校联合发布了一套用于测量和提高机器学习软硬件性能的国际基准MLPerf。其巨大的学术和产业价值获业界肯定&#xff0c;被认为不仅将加速推进机器学习硬件软件相关技术创…

王爽 汇编语言第三版 第10章 call 和 ret 指令 以及 子程序设计

第10章 call 和 ret 指令 10.1 ret 和 reft 指令 call 和 ret 指令都是转移指令&#xff0c;他们都修改 IP&#xff0c;或同事修改 CS 和 IP 。他们经常被共同来实现子程序的设计。 10.2 call 指令 和 根据位移 转移的call指令 段间转移 的 call 指令 转移地址 在 寄存器 中 的…

org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0

一、错误现象&#xff1a; 当改变了jdk版本时&#xff0c;在编译java时&#xff0c;会遇到Unsupported major.minor version错误。 jdk版本和stanford parser对应关系 JDK版本和Java编译器内部的版本号 J2SE 8 52, J2SE 7 51, J2SE 6.0 50, J2SE 5.0 49, JDK 1.4 48, J…

ip, tcp, udp, icmp header

Figure 1. IPv4 header Figure 2. TCP header Figure 3. UDP header Figure 4. ICMP header reference:TCP/IP Reference转载于:https://www.cnblogs.com/lbsx/archive/2010/11/30/1891814.html

人民日报三问人工智能,给法律制度带来哪些挑战?

来源&#xff1a;亿欧网 作者&#xff1a;倪弋摘要&#xff1a;人工智能生成物是否具有知识产权&#xff1f;人工智能可以替代司法者吗&#xff1f;人工智能侵权责任如何认定&#xff1f;人工智能的出现会给现行的法律制度带来了不少挑战&#xff0c;只有在法律研究上未雨绸缪…