最近的项目有用到
PropertyUtils.copyProperties(info, daoInfo);
便来总结一下。
阿里发布了阿里巴巴代码规约插件,果断将它集成起来。我最喜欢使用的Apache BeanUtils.copyProperties()方法后面打了个大大的红叉,提示"避免使用Apache的BeanUtils进行属性的copy"。
市面上的其他几种属性copy工具
- springframework的BeanUtils
- cglib的BeanCopier
- Apache BeanUtils包的PropertyUtils类
测试一下
结论:
-
PropertyUtils的copyProperties()方法几乎与BeanUtils.copyProperties()相同,主要的区别在于后者提供类型转换功能,
即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,PropertyUtils不支持这个功能,所以说BeanUtils速度会更快一些,
使用更普遍一点,犯错的风险更低一点。 -
Apache BeanUtils的性能最差,不建议使用。
-
Apache PropertyUtils100000次以内性能还能接受,到百万级别性能就比较差了,可酌情考虑。
-
spring BeanUtils和BeanCopier性能较好,如果对性能有特别要求,可使用BeanCopier,不然spring BeanUtils也是可取的。
Apache BeanUtils.copyProperties()性能分析
执行1000000次copy属性,然后通过jvisualvm查看方法耗时,如图:
发现最耗时的方法就是method.invoke(),但是spring的BeanUtils、PropertyUtils里也是采用反射来实现的,为什么效率相差这么大呢?
看来Abstract.convert()和getIntrospectionData()占用了很大一部分时间,
而且Apache BeanUtils中的日志输出也比较耗时。
Spring BeanUtils和PropertyUtils
PropertyUtils和Apache BeanUtils核心代码区别在图中标注的地方。Apache BeanUtils主要集中了各种丰富的功能(日志、转换、解析等等),导致性能变差。
而Spring BeanUtils则是直接通过反射来读取和写入,直抒胸臆,省去了其他繁杂的步骤,性能自然不差。
Cglib BeanCopier
cglib BeanCopier的主要耗时方法就在BeanCopier.create(),如果将该方法做成静态成员变量,则还可以大大缩小执行时间。BeanCopier是一种基于字节码的方式,其实就是通过字节码方式转换成性能最好的get、set方式,只需考虑创建BeanCopier的开销,如果我们将BeanCopier做成静态的,基本只需考虑get、set的开销,所以性能接近于get、set。