文章插图
作者:Van_Fan
在做业务的时候 , 为了隔离变化 , 我们会将DAO查询出来的DO和对前端提供的DTO隔离开来 。大概90%的时候 , 它们的结构都是类似的;但是我们很不喜欢写很多冗长的b.setF1(a.getF1())这样的代码 , 于是我们需要简化对象拷贝方式 。
大多时候时候使用的是Apache或Spring``BeanUtils , 今天 , 我们来看一下一个更高效的属性拷贝方式:BeanCopier 。一、背景1.1 对象拷贝概念JAVA中 , 数据类型分为值类型(基本数据类型)和引用类型 , 值类型包括int、double、byte、boolean、char等简单数据类型 , 引用类型包括类、接口、数组等复杂类型 。
对象拷贝分为浅拷贝(浅克隆)与深拷贝(深克隆) 。
- 浅拷贝与深拷贝差异
文章插图
1.2 示例前准备
- 源对象属性类UserDO.class(以下示例 , 源对象都用这个)
@Datapublic class UserDO {private int id;private String userName;/*** 以下两个字段用户模拟自定义转换*/private LocalDateTime gmtBroth;private BigDecimal balance;public UserDO(Integer id, String userName, LocalDateTime gmtBroth, BigDecimal balance) {this.id = id;this.userName = userName;this.gmtBroth = gmtBroth;this.balance = balance;}}
- 造数据工具类DataUtil.class
public class DataUtil {/*** 模拟查询出一条数据* @return*/public static UserDO createData() {return new UserDO(1, "Van", LocalDateTime.now(),new BigDecimal(100L));}/*** 模拟查询出多条数据* @param num 数量* @return*/public static List<UserDO> createDataList(int num) {List<UserDO> userDOS = new ArrayList<>();for (int i = 0; i < num; i++) {UserDO userDO = new UserDO(i+1, "Van", LocalDateTime.now(),new BigDecimal(100L));userDOS.add(userDO);}return userDOS;}}
二、对象拷贝之BeanUtilsApache和Spring均有BeanUtils工具类 , Apache的BeanUtils稳定性与效率都不行;Spring的BeanUtils比较稳定 , 不会因为量大了 , 耗时明显增加 , 故一般都使用Spring的BeanUtils 。2.1 源码解读Spring中的BeanUtils , 其中实现的方式很简单 , 就是对两个对象中相同名字的属性进行简单get/set , 仅检查属性的可访问性 。
BeanUtils 源码
可以看到, 成员变量赋值是基于目标对象的成员列表, 并且会跳过ignore的以及在源对象中不存在的, 所以这个方法是安全的, 不会因为两个对象之间的结构差异导致错误, 但是必须保证同名的两个成员变量类型相同 。
2.2 示例
@Slf4jpublic class BeanUtilsDemo {public static void main(String[] args) {long start = System.currentTimeMillis();UserDO userDO = DataUtil.createData();log.info("拷贝前,userDO:{}", userDO);UserDTO userDTO = new UserDTO();BeanUtils.copyProperties(userDO,userDTO);log.info("拷贝后,userDO:{}", userDO);}}
- 结果
18:12:11.734 [main] INFO cn.van.parameter.bean.copy.demo.BeanUtilsDemo - 拷贝前,userDO:UserDO(id=1, userName=Van, gmtBroth=2019-11-02T18:12:11.730, balance=100)18:12:11.917 [main] INFO cn.van.parameter.bean.copy.demo.BeanUtilsDemo - 拷贝后,userDO:UserDO(id=1, userName=Van, gmtBroth=2019-11-02T18:12:11.730, balance=100)
三、对象拷贝之BeanCopierBeanCopier是用于在两个bean之间进行属性拷贝的 。BeanCopier支持两种方式:- 一种是不使用Converter的方式 , 仅对两个bean间属性名和类型完全相同的变量进行拷贝;
- 另一种则引入Converter , 可以对某些特定属性值进行特殊操作 。
- 依赖
<dependency><groupId>cglib</groupId><artifactId>cglib-nodep</artifactId><version>3.3.0</version></dependency>
**注意:**该依赖非必须 , 因为Spring中已经集成了cglib,博主使用的就是org.springframework.cglib.beans.BeanCopier 。3.1.1 属性名称、类型都相同
- 目标对象属性类
@Datapublic class UserDTO {private int id;private String userName;}
- 测试方法
/** * 属性名称、类型都相同(部分属性不拷贝) */private static void normalCopy() { // 模拟查询出数据UserDO userDO = DataUtil.createData();log.info("拷贝前:userDO:{}", userDO);// 第一个参数:源对象 , 第二个参数:目标对象 , 第三个参数:是否使用自定义转换器(下面会介绍) , 下同BeanCopier b = BeanCopier.create(UserDO.class, UserDTO.class, false);UserDTO userDTO = new UserDTO();b.copy(userDO, userDTO, null);log.info("拷贝后:userDTO:{}", userDTO);}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 在头条上怎么赚钱?告诉你五种方法,绝对干货
- 设计师 设计中应该怎么配色?本文带你成为好“色”之师
- 教你快速清除Excel工作表保护密码
- 世界上美人鱼存在还是不存在 人类变成美人鱼
- 油价|中石化回应油价“国际降你不降 你和国际不一样”:真是误解了
- 空腹有氧运动怎么做?
- 你还知道哪些中国古代神话的故事? 我国古代的神话故事你还知道哪些
- 日本|DVD光驱还没有绝迹:升级USBC接口、售价180多元
- 卫浴家居风水知识 教你赚钱的卫浴布局
- 你能成为大富翁吗?好家居风水为你创造更多财富