Java对象拷贝备忘
基于面向对象和各种设计要求,一个分层的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对象拷贝备忘的更多相关文章
- 0. Java虚拟机系列备忘预览图
打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...
- JAVA 对象拷贝
1.java里的clone分为: A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍. Java中对 ...
- java基础知识备忘
1.java内存分配 a.寄存器cup -- 暂不涉及 b.本地方法栈 -- 虚拟机调用windows功能用的,比如创建文件夹 c.方法区 -- 存放 .class文件,负责存放方法 d.栈 -- ...
- java对象拷贝和复制
参考文章:http://blog.csdn.net/XIAXIA__/article/details/41652057 解决问题:深拷贝.浅拷贝 和普通的对象赋值有什么区别? 对象复制 例如:Pers ...
- Java输入输出流备忘
重要博客: http://blog.csdn.net/hguisu/article/details/7418161 File dir = new File("\\root"); ...
- Java Socket基础[备忘]
1.服务端----Server.java import javax.swing.*; import java.io.*; import java.net.*; import java.awt.*; i ...
- ruby正则表带式对象使用备忘
ruby对于正则表达式的使用是非常灵活的,提供了专门的正则表达式对象Regexp.其包括match实例方法,字符串也含有该方法.so可以这么做: /a/ =~ "a" " ...
- java集合框架备忘
List,Set,Map三者的区别? List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象 Set(注重独一无二的性质): 不允许重复的集合.不会有多 ...
- Java 对象拷贝方式
(1)BeanUtils.cloneBean()使用: http://www.cnblogs.com/fervour/archive/2009/12/18/1627868.html package c ...
随机推荐
- CSS-15-定位
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 光流法draw_flow()函数报错
光流法draw_flow()函数报错 import cv2 from scipy import * def draw_flow(im, flow, step=16): ""&quo ...
- k8s概述
k8s概述 概述 Kubernetes 使你在数以千计的电脑节点上运行软件时就像所有这些节点是单个大节点一样.它将底层基础设施抽象,这样做同时简化了应用的开发.部署, 以及对开发和运维团队的管理. K ...
- composer intall 报错
报错 [Composer\Exception\NoSslException] The openssl extension is required for SSL/TLS protection but ...
- mysql--->权限管理原理和设置
mysql 权限管理 mysql权限检查原理 权限检查两个阶段 你有没有权限链接上来 你有没有权限执行此操作 服务器如何判断用户用户有没有权限连接上来? 通过mysql库下的user表 查看:sele ...
- PMP——项目管理的价值观与方法论
关于项目管理的十个成语: 未雨绸缪(计划.风险):识别风险.做出计划.并指定负责人: 防微杜渐(监控.纠正):持续的实时的监控计划,监控和发现偏差,并进行纠正: 资源集成(整合.采购):把最专业的资源 ...
- Docker Swarm 从入门到放弃
准备工作 我本机是macOS,所以我直接安装了docker desktop,其中包含了docker-machine,不用单独安装. 安装docker主机驱动 我在网上很多人提到了使用virtualbo ...
- java获取本地IP地址集合包括虚拟机的ip
public static ArrayList<String> getLocalIpAddr() { ArrayList<String> ipList = new ArrayL ...
- 粗谈MySQL事务的特性和隔离级别
网上对于此类的文章已经十分饱和了,那还写的原因很简单--作为自己的理解笔记. 前言 此篇文章作为自己学习MySQL的一些个人理解,使用的引擎是InnoDb.首先先讲讲事务的概念,在<高性能 ...
- Unreal Engine 4 蓝图完全学习教程(二)—— 初步尝试
本篇尝试使用蓝图.蓝图是使用专门的编辑器进行编程. Ⅰ.3类蓝图 ①关卡蓝图:前面提到过,关卡是指在UE中制成的游戏场景.关卡蓝图是用于制作当前游戏场景的程序.在UE中进行编程就是在创建关卡蓝图. ② ...