朵小喵儿|七种对象复制工具类,你最看好哪个?( 三 )


所以两者选择 , 还是推荐使用 Spring BeanUtils 。
Cglib BeanCopier上面两个是阿粉日常工作经常使用 , 而下面的这些都是阿粉最近才开始接触的 , 比如 Cglib BeanCopier 。 这个使用方法 , 可能比上面两个类稍微复杂一点 , 下面我们来看下具体用法:
首先我们引入 Cglib 依赖:
cglibcglib3.3.0画外音:如果你工程内还有 Spring-Core 的话 , 如果查找 BeanCopier 这个类 , 可以发现两个不同的包的同名类 。
一个属于 Cglib , 另一个属于 Spring-Core 。
其实 Spring-Core 内BeanCopier 实际就是引入了 Cglib 中的类 , 这么做的目的是为了了保证 Spring 使用长度 Cglib 相关类的稳定性 , 防止外部 Cglib 依赖不一致 , 导致 Spring 运行异常 。
转换代码如下:
// 省略赋值语句StudentDO studentDO = new StudentDO();BeanCopier beanCopier = BeanCopier.create(StudentDTO.class, StudentDO.class, false);beanCopier.copy(studentDTO, studentDO, null);使用方法相比 BeanUtils ,BeanCopier 稍微多了一步 。对比studentDO与 studentDTO对象:
朵小喵儿|七种对象复制工具类,你最看好哪个?从上面可以得到与 Spring Beanutils 基本一致的结论:

  • 字段名不一致 , 属性无法复制
  • 类型不一致 , 属性无法复制 。 不过有点不一样 , 如果类型为基本类型/基本类型的包装类型 , 这两者无法被拷贝 。
  • 嵌套对象字段 , 将会与源对象使用同一对象 , 即使用浅拷贝
上面我们使用 Beanutils , 遇到这种字段名 , 类型不一致的这种情况 , 我们没有什么好办法 , 只能手写硬编码 。
不过在 BeanCopier 下 , 我们可以引入转换器 , 进行类型转换 。
// 注意最后一个属性设置为 trueBeanCopier beanCopier = BeanCopier.create(StudentDTO.class, StudentDO.class, true);// 自定义转换器beanCopier.copy(studentDTO, studentDO, new Converter() {@Overridepublic Object convert(Object source, Class target, Object context) {if (source instanceof Integer) {Integer num = (Integer) source;return num.toString();}return null;}});不过吐槽一下这个转换器 , 一旦我们自己打开使用转换器 , 所有属性复制都需要我们自己来了 。 比如上面的例子中 , 我们只处理当源对象字段类型为 Integer , 这种情况 , 其它都没处理 。 我们得到 DO 对象将会只有 name 属性才能被复制 。
朵小喵儿|七种对象复制工具类,你最看好哪个?Cglib BeanCopier 的原理与上面两个 Beanutils 原理不太一样 , 其主要使用 字节码技术动态生成一个代理类 , 代理类实现get 和 set方法 。 生成代理类过程存在一定开销 , 但是一旦生成 , 我们可以缓存起来重复使用 , 所有 Cglib 性能相比以上两种 Beanutils 性能比较好 。
DozerDozer, 中文直译为挖土机, 这是一个「重量级」属性复制工具类 , 相比于上面介绍三个工具类 , Dozer 具有很多强大的功能 。
朵小喵儿|七种对象复制工具类,你最看好哪个?官网 logo
画外音:重量级/轻量级其实只是一个相对的说法 , 由于 Dozer 相对 BeanUtils 这类工具类来说 , 拥有许多高级功能 , 所以相对来说这是一个重量级工具类 。


推荐阅读