基于面向对象和各种设计要求,一个分层的Java系统中存在各种 VO、DTO、BO、PO 之类的对象,同一个实体的不同对象需要大量的属性复制,为了避免手动操作,需要一种便捷对象浅复制工具类,下面是各个常见工具对比。

列举

//cglib
net.sf.cglib.beans.BeanCopier.create
net.sf.cglib.beans.BeanCopier.copy
//spring-beans
org.springframework.beans.BeanUtils.copyProperties
//commons-beanutils
org.apache.commons.beanutils.BeanUtils.copyProperties
org.apache.commons.beanutils.PropertyUtils.copyProperties

原理

以上4种方式都是通过自动调用原对象的getter方法,再用目标对象的setter方法设置进去,区别在于BeanCopier先通过create创建了一个以BeanCopier派生的动态代理类,其创建的copy方法实现包含以上所有getter和setter的调用过程,调用copy可以达到原生代码方式的性能;而其他所有方式如spring-beans和commons-beanutils的实现都是通过反射逐个调用getter和setter,性能相比前者较差。

细节

细节 Apache-PropertyUtils Apache-BeanUtils Spring-BeanUtils Cglib-BeanCopier
相同属性名,不同类型转换Converter扩展 NO Yes Yes Yes,较难用,需要对每一种属性类型都做转换
相同属性名,Integer和int的处理 OK OK OK 不拷贝,忽略该属性
相同属性名,Long和Integer的处理 异常报错 OK,自动互转 不拷贝,忽略该属性 不拷贝,忽略该属性
对基本类型null值处理(Integer,Long等) OK 特殊,会将null转为0,用Converter后解决 OK OK
对source特殊属性的限制:(Date,BigDecimal等) OK NO,异常出错,必须用Converter才行 OK OK
Get和set方法不匹配的处理 OK,忽略该属性 OK,忽略该属性 OK,忽略该属性 创建异常(仅限source有get方法在target中找不到对应set方法)
调用异常处理 需处理异常 需处理异常 RuntimeException RuntimeException

需要兼容性的场景,优先spring-beans提供的BeanUtils,功能强大,兼容性最好。需要性能的场景,优先选择cglib提供的BeanCopier,性能最好(注意需要缓存create结果)。

还有一项需要注意的是所有拷贝都是浅拷贝,注意属性引用不变,避免新老对象同时读写引起问题,这需要通过场景约束。

结论

事实上,由于不同工具类实现不同,细节差异非常多,一个团队最好通过规范统一使用某一个,并对其熟悉和理解,不必追求万能的工具类。我在新项目中选择了BeanCopier,并通过场景和限制约定避免踩坑。

  • 场景约束:主要用于同模型的DO、DTO和VO等之间转换。
  • 限制约定:要求两者同名属性具有严格相同类型,且其getter和setter一一对应,不能包含特殊逻辑。

Java对象拷贝备忘的更多相关文章

  1. 0. Java虚拟机系列备忘预览图

    打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...

  2. JAVA 对象拷贝

    1.java里的clone分为:  A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象.  b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍.  Java中对 ...

  3. java基础知识备忘

    1.java内存分配 a.寄存器cup -- 暂不涉及 b.本地方法栈  -- 虚拟机调用windows功能用的,比如创建文件夹 c.方法区  -- 存放 .class文件,负责存放方法 d.栈 -- ...

  4. java对象拷贝和复制

    参考文章:http://blog.csdn.net/XIAXIA__/article/details/41652057 解决问题:深拷贝.浅拷贝 和普通的对象赋值有什么区别? 对象复制 例如:Pers ...

  5. Java输入输出流备忘

    重要博客: http://blog.csdn.net/hguisu/article/details/7418161 File dir = new File("\\root");   ...

  6. Java Socket基础[备忘]

    1.服务端----Server.java import javax.swing.*; import java.io.*; import java.net.*; import java.awt.*; i ...

  7. ruby正则表带式对象使用备忘

    ruby对于正则表达式的使用是非常灵活的,提供了专门的正则表达式对象Regexp.其包括match实例方法,字符串也含有该方法.so可以这么做: /a/ =~ "a" " ...

  8. java集合框架备忘

    List,Set,Map三者的区别? List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象 Set(注重独一无二的性质): 不允许重复的集合.不会有多 ...

  9. Java 对象拷贝方式

    (1)BeanUtils.cloneBean()使用: http://www.cnblogs.com/fervour/archive/2009/12/18/1627868.html package c ...

随机推荐

  1. ios启动流程

    1.创建UIApplication (1.打开网页,发短信,打电话 . 2.设置应用程序提醒数字 . 3.设置联网状态 . 4.设置状态栏) 2.创建AppDelegate代理对象,并且成为UIApp ...

  2. CAD制图系列之中心线画法

    我们将做个简单的笔记: CAD中心线怎么画 CAD中心线一般为点划线,画法很简单,首先先设置线型 一般步骤为: 1.首先,打开CAD,点击进入图层特性管理器 2.在图层特性管理器中点击线型进行设置 3 ...

  3. 隐马尔可夫(HMM)/感知机/条件随机场(CRF)----词性标注

    笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 7. 词性标注 7.1 词性标注概述 什么是词性 在语言学上,词性(Par-Of- ...

  4. 如何写出优雅的Python代码?

    有时候你会看到很Cool的Python代码,你惊讶于它的简洁,它的优雅,你不由自主地赞叹:竟然还能这样写.其实,这些优雅的代码都要归功于Python的特性,只要你能掌握这些Pythonic的技巧,你一 ...

  5. 纯JavaScript实现页面行为的录制

    在网上有个开源的rrweb项目,该项目采用TypeScript编写(不了解该语言的可参考之前的<TypeScript躬行记>),分为三大部分:rrweb-snapshot.rrweb和rr ...

  6. 工业狗转行AI的心路历程

    2020年2月16日,晴 昨晚下了一场雪,大概是晚上八九点的样子,细碎的雪花在无风的夜里直嗖嗖的往下掉,门前的轿车顶上覆了薄薄的一层.路灯下的小巷格外的寂静,裹着我的睡衣在昏黄的灯光下站了许久,冠状病 ...

  7. shellcode 反汇编,模拟运行以及调试方法

    onlinedisassembler https://onlinedisassembler.com 在线反汇编工具,类似于lda.功能比较单一. Any.run 等平台在线分析 将shellcode保 ...

  8. Go语言实现:【剑指offer】链表中环的入口结点

    ​该题目来源于牛客网<剑指offer>专题. 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. Go语言实现: /** * Definition for sing ...

  9. ubuntu docker中crontab任务不执行的问题

    problem of task of crontab in docker of ubuntu do not working! 由于各种原因,要在Ubuntu docker上部署crontab任务,如 ...

  10. 详解Java8的日期和时间API

    详解Java8的日期和时间API 在JDK1.0的时候,Java引入了java.util.Date来处理日期和时间:在JDK1.1的时候又引入了功能更强大的java.util.Calendar,但是C ...