当前位置: 首页 > 科技观察

12种vo2dto方法,BeanUtils.copyProperties最受压力测试

时间:2023-03-16 13:48:14 科技观察

1.前言为什么你的代码能用?没有技术深度,没有知识储备,没有经验积累,怎么写代码?百度一下,遇到问题稍微搜一下,然后查一段,不管它的原理是什么,适合什么样的场景,先贴到自己的项目里,看,能运行,就可以了能跑。那么这样的代码只是一个可用的交付,根本没有一定的质量保证,更谈不上数据结构、算法逻辑和设计模式,那么看编程资料的LeetCode就全没了。当你觉得自己看了很多资料不知道怎么用的时候,你会说什么,真正的卷,你已经学会了。但其实,我并不认为深挖技术,梳理出一套完整的知识体系,收获一点点努力,就是在量。相反,观看技术视频就像看电影一样简单。如果你不写案例,你会认为这本书很好读。脑力思考的无意义缺失和机械的物理重复是体积,甚至是体积。就好比让你用一个属性拷贝工具把vo转dto,你用哪个,Apache的还是Spring的,还是别的,哪个效率最高?接下来我们用数据来验证一下,并提供各种案例的使用对比。2、性能测试对比在Java系统工程开发过程中,会存在各层之间的对象转换,如VO、DTO、PO、VO等,手动get和set太浪费时间,也可能是操作不当,选择自动化工具会更方便。目前我整理了12种对象属性转换类型,包括:普通getset、json2Json、Apache属性拷贝、Spring属性拷贝、bean-mapping、bean-mapping-asm、BeanCopier、Orika、Dozer、ModelMapper、JMapper、MapStruct接下来我们分别测试了这11种属性转换操作在100、1000、10000、100000、100万次时的性能和时间比较。BeanUtils.copyProperties是大家代码中最常用的工具类,但是只要不是在Apache包下误用,而是使用Spring提供的,对性能基本不会有太大影响。但是如果性能更好的话,可以替代手动get和set,或者MapStruct更好用,因为它本身在编译时生成get和set代码,就像我们写get和set一样。其他一些组件包主要是基于AOP、ASM、CGlib技术手段实现的,因此会有相应的性能损失。3、12个转换案例源码:https://git***.com/fuzhengwei/guide-vo2dto说明:在案例工程下创建interfaces.assembler包,定义IAssembler#sourceToTarget(SOURCEvar)接口,提供不同方法的对象转换操作类实现,学习过程中可以直接下载运行调试。1.get\set@ComponentpublicclassGetSetAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();userDTO.setUserId(var.getUserId());userDTO.setUserNickName(var.getUserNickName());userDTO.setCreateTime(var.getCreateTime());返回用户DTO;}}推荐度:★★★☆☆性能:★★★★★手法:手写点评:其实这个方法也是日常用的最重要的是,性能肯定不错,就是操作起来有点麻烦。尤其是大量带有属性的VO对象转为DTO对象时。但其实也有一些快捷的操作方法。例如,您可以通过Shift+Alt选择所有属性,然后通过Shift+Tab将它们合并为一列。然后用Alt选中这一列,粘贴userDTO。最后切换到最后加上括号和分号,最后格式化一下就大功告成了。2.json2Json@ComponentpublicclassJson2JsonAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){StringstrJson=JSON.toJSONString(var);返回JSON.parseObject(strJson,UserDTO.class);}}推荐:☆☆☆☆☆性能:★☆☆☆☆手段:将对象转为JSON字符串,再将JSON转为另一个对象。3.ApachecopyProperties@ComponentpublicclassApacheCopyPropertiesAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();}尝试{BeanUtils.copyProperties(userDTO,ExllegalAccess);}cInvocationTargetExceptione){e.printStackTrace();}返回userDTO;}}推荐:☆☆☆☆☆性能:★☆☆☆☆方法:Introspector机制获取类的属性进行赋值操作点评:陷阱,兼容性4.SpringcopyProperties@ComponentpublicclassSpringCopyPropertiesAssemblerimplementsIAssembler{@Override发布icUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();BeanUtils.copyProperties(var,userDTO);返回用户DTO;}}推荐度:★★★☆☆性能:★★★★☆含义:Introspector机制获取Class属性进行赋值操作点评:同样是反射属性拷贝,Spring提供的copyProperties比Apache好用多了,只要不出错,基本不会有问题5.BeanMapping@ComponentpublicclassBeanMappingAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();BeanUtil.copyProperties(var,userDTO);返回用户DTO;}}推荐:★★☆☆☆性能:★★★☆☆方式:属性复制评语:性能一般6.BeanMappingASM@ComponentpublicclassBeanMappingAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();BeanUtil.copyProperties(var,userDTO);返回用户DTO;}}推荐度:★★★☆☆性能:★★★★☆测评:基于ASM字节码框架点评:与普通BeanMapping相比,性能有所提升,可以使用。7.BeanCopier@ComponentpublicclassBeanCopierAssemblerimplementsIAssembler{@OverridepublicUserDTOsourceToTarget(UserVOvar){UserDTOuserDTO=newUserDTO();BeanCopierbeanCopier=BeanCopier.create(var.getClass(),userDTO.getClass(),false);beanCopier.copy(var,userDTO,null);返回用户DTO;}}推荐度:★★★☆☆性能:★★★★★方法:基于CGlib字节码操作生成get和set方法点评:整体性能很好,使用也不复杂。可以使用8.Orika@ComponentpublicclassOrikaAssemblerimplementsIAssembler{/***构造一个MapperFactory*/privatestaticMapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();static{mapperFactory.classMap(UserDTO.class,UserVO.class).field("userId","userId")//可以指定.byDefault().register();}@OverridepublicUserDTOsourceToTarget(UserVOvar){返回mapperFactory。getMapperFacade()。地图(变种,我们erDTO.class);官网:https://orika-mapper.git***.io/orika-docs/推荐度:★★☆☆☆性能:★★★☆☆手段:根据字节码生成映射对象注释:测试性能为不太突出。如果使用它,需要优化将MapperFactory构造成Bean对象。9.Dozer@ComponentpublicclassDozerAssemblerimplementsIAssembler{privatestaticDozerBeanMappermapper=newDozerBeanMapper();}UserVOvar){returnmapper.map(var,UserDTO.class);}}官网:http://dozer.sourceforge.net/documentation/gettingstarted.html推荐度:☆☆☆☆性能:★★☆☆☆含义:属性映射框架,递归复制对象点评:性能有点差,不推荐10.ModelMapper@ComponentpublicclassModelMapperAssemblerimplementsIAssembler{privatestaticModelMappermodelMapper=newModelMapper();static{modelMapper.addMappings(newPropertyMap(){@Overrideprotectedvoidconfigure(){//可以操作map().setUserId(source.getUserId());}});}@OverridepublicUserDTOsourceToTarget(UserVOvar){returnmodelMapper.map(var,UserDTO.class);}}官网:http://modelmapper.org推荐度:★★★☆☆性能:★★★☆☆方法:基于ASM字节码实现点评:转换对象数量少时性能较好。如果同时转换大量对象,性能会下降。11.JMapperJMapperjMapper=newJMapper<>(UserDTO.class,UserVO.class,newJMapperAPI().add(JMapperAPI.mappedClass(UserDTO.class).add(JMapperAPI.attribute("userId").value("userId")).add(JMapperAPI.attribute("userNickName").value("userNickName")).add(JMapperAPI.attribute("createTime").value("createTime"))));官网:https://git***.com/jmapper-framework/jmapper-core/wiki推荐度:★★★★☆性能:★★★★★含义:优雅、高性能和健壮性集于一身的javabeanmapper评论:速度确实不错,但是感觉和SpringBoot结合起来有点麻烦,可能姿势不对12.MapStruct@Mapper(componentModel="spring",unmappedTargetPolicy=ReportingPolicy.IGNORE,unmappedSourcePolicy=ReportingPolicy.IGNORE)publicinterfaceUserDTOMappingextendsIMapping{/**用于测试的单例*/IMappingINSTANCE=Mappers.getMapper(UserDTOMapping.class);@Mapping(target="userId",source="userId")@Mapping(target="createTime",dateFormat="yyyy-MM-ddHH:mm:ss")@OverrideUserDTOsourceToTarget(UserVOvar1);@Mapping(target="userId",source="userId")@Mapping(target="createTime",dateFormat="yyyy-MM-ddHH:mm:ss")@OverrideUserVOtargetToSource(UserDTOvar1);}官方网址:https://git***.com/mapstruct/mapstruct推荐度:★★★★★性能:★★★★★意思:编译时直接生成对应的get和set,像手写代码点评:非常快,不需要运行Periodic处理,结合框架使用方便4.总结其实对象属性转换的操作无非就是反射,AOP,CGlib,ASM,Javassist在编译时和运行时的处理,以及一个更好的思路是在编译前生成对应的get和set,就像手写的一样,所以推荐我最喜欢的MapStruct,用起来更舒服,其中之一来自于功能的扩展性、易用性和兼容性。不管是哪种用途,一定要做好完整的测试和验证,不要一上来就复制粘贴,否则可能早挖坑了,当然也不一定是会填坑的兄弟。