BeanUtils.copyProperties知多少
事出有因
近期在读《阿里巴巴开发手册》的时候发现:阿里强制避免使用BeanUtils进行属性的拷贝,但是不得不承认的是,在我自己的项目中确实使用过Apache的Beanutils进行属性拷贝,在读了开发手册后,感觉项目中的代码可以优化一下,基于不同包下的BeanUtils性能和特性有所不同,当然用法也不尽相同,所以,可以你可能会跳入因为导错包导致对象拷贝为null的坑。
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。(类似a对象的指针指到了b)
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。
比物连类
目前已有其他大佬对Apache、Spring的工具类进行了数据对比:详细请看:
借用大佬的数据说明下结果:
工具名称 | 执行1000次耗时 | 10000次 | 100000次 | 1000000次 |
---|---|---|---|---|
Apache BeanUtils | 390ms | 854ms | 1763ms | 8408ms |
Apache PropertyUtils | 26ms | 221ms | 352ms | 2663ms |
spring BeanUtils | 39ms | 315ms | 373ms | 949ms |
Cglib BeanCopier | 64ms | 144ms | 171ms | 309ms |
Apache的BeanUtils去拷贝属性时,性能是最慢的,数据拷贝皆使用Java的反射实现,Apache比较慢的原因是:
- 进行大量参数校验
- 使用解析类型转换
spring中的BeanUtils去拷贝属性时就是对两个对象中相同名字的属性进行简单get/set,仅检查属性的可访问性。实现的方式没有太复杂的逻辑,代码执行较快。
物尽其用
在使用BeanUtils时,会先引用对应的包,如果包引用不对的话,就可能会跳入开头的大坑中,具体如下:
包org.apache.commons.beanutils.BeanUtils
BeanUtils.copyProperties(a,b);
b的值赋值a
包org.springframework.beans.BeanUtils
BeanUtils.copyProperties(a,b);
a的值赋给b
归根结蒂
正如上文的测试数据,如果不是阿里级别的并发量、数据量,其实三种工具类的性能差距是感知力不强的,倒不如去优化SQL对性能来的实在,但是既然有了更好的选择,仅仅是导入不同的包,参数位置的不同而已,如果属性值比较少,没必要使用属性拷贝,直接手动get/set即可。所以,代码中我们尽量使用性能较高且可行的方案。重要的是对于代码的责任心和负责度,正如雷军先生说过的那样:我们要像写诗一样写代码,尽量使代码更加优雅。所以,我推荐MapStruct
ps:请MapStruct把我的广告费结一下
别开生面
分布式项目中,不同的应用与应用之间,还有单独的应用细分模块之后,DO 一般不会让外部依赖,这时候需要在提供对外接口的模块里放 DTO 用于对象传输,也即是 DO 对象对内,DTO对象对外,DTO 可以根据业务需要变更,并不需要映射 DO 的全部属性。这种 对象与对象之间的互相转换,就需要有一个专门用来解决转换问题的工具,毕竟每一个字段都 get/set 会很麻烦。我在跟前阿里员工合作的时候,属性转换使用的是MapStruct,只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。
本文地址:https://blog.csdn.net/weixin_42313773/article/details/110456401