1. 特性

https://segmentfault.com/a/1190000040106844

https://cloud.tencent.com/developer/article/1624695

Spring.BeanUtils:是浅拷贝,不支持深拷贝

Apache.BeanUtils:是浅拷贝,不支持深拷贝

BeanCopier:是浅拷贝,不支持深拷贝。BeanCopier 的实现原理跟 BeanUtils 截然不同,它不是利用反射对属性进行赋值,而是直接使用 cglib 来生成带有的 get/set 方法的 class 类,然后执行。由于是直接生成字节码执行,所以 BeanCopier 的性能接近手写

BeanUtils 和 BeanCopier 都是功能比较简单的,需要属性名称一样,甚至类型也要一样。

Dozer:是深拷贝。Dozer 的实现原理本质上还是用反射/Introspector 那套

Orika:是深拷贝。底层使用 Javassist 生成字节码

JMapper:未知

MapStruct:是浅拷贝,不支持深拷贝。MapStruct 是一个自动生成 bean mapper 类的代码生成器

ModelMapper:是浅拷贝,不支持深拷贝

1.1. 选择

http://18965050.github.io/work/orika

如果不需要深拷贝,就用 MapStruct

如果需要深拷贝,就用 Orika 或者用插件生成(如 coding-wizard)

2. 原理对比

目前常用的属性拷贝工具,包括 Apache 的 BeanUtils、Spring 的 BeanUtils、Cglib 的 BeanCopier、mapstruct。

2.1. Apache BeanUtils:BeanUtils

Apache commons 组件里面的成员,由 Apache 提供的一套开源 api,用于简化对 javaBean 的操作,能够对基本类型自动转换。

循环遍历源对象的每个属性,对于每个属性,拷贝流程为:

  • 校验来源类的字段是否可读 isReadable
  • 校验目标类的字段是否可写 isWriteable
  • 获取来源类的字段属性值 getSimpleProperty
  • 获取目标类字段的类型 type,并进行类型转换
  • 设置目标类字段的值

由于单字段拷贝时每个阶段都会调用 PropertyUtilsBean.getPropertyDescriptor 获取属性配置,而该方法通过 for 循环获取类的字段属性,严重影响拷贝效率

2.2. Spring BeanUtils

BeanUtils 是 spring 框架下自带的工具,在 org.springframework.beans 包下, spring 项目可以直接使用。

2.3. Cglib BeanCopier

cglib(Code Generation Library)是一个强大的、高性能、高质量的代码生成类库,BeanCopier 依托于 cglib 的字节码增强能力,动态生成实现类,完成对象的拷贝。

2.4. mapstruct

mapstruct 是一个 Java 注释处理器,用于生成类型安全的 bean 映射类,在构建时,根据注解生成实现类,完成对象拷贝。

性能调优-进阶-2、系统调优案例♨️

3. 实战经验

4. 参考与感谢

https://www.51cto.com/article/741833.html

https://zhuanlan.zhihu.com/p/586539335

https://www.freebuf.com/news/350650.html