解决BeanUtils和PropertyUtils的From对象里的null值会覆盖To对象里非空值的问题,提高复制效率和性能 如何高效率实现一个复制对象属性方法工具?

本文探讨了解决BeanUtils和PropertyUtils在复制对象时,null值覆盖非空值的问题,并提出提高复制效率和性能的方法。通过分析两者的工作原理,提出重写反射转换和使用高性能的ReflectASM库来实现更高效的对象属性复制。同时,针对BeanUtils和PropertyUtils存在的问题,提供了解决方案,确保非空值不被覆盖。

解决BeanUtils和PropertyUtils的From对象里的null值会覆盖To对象里非空值的问题,提高复制效率和性能 如何高效率实现一个复制对象属性方法工具?

 

背景:

在商业项目中所需要的业务非常多,所以我们的业务数据也会有很多种,这个时候就会有什么VO,DTO,PO等等这些,把业务和我们的基础数据进行分离转换。但是一直都没有什么好一点的转换类。后来用了一下BeanUtils.copyPropertie,和PropertyUtils.copyProperties()的方法,发现其效率非常低。这里也简单总结了一下他们的用法及原理以及自己实现的转换类;

用法:

BeanUtils.copyProperties("转换后的类", "要转换的类");

PropertyUtils.copyProperties("转换后的类", "要转换的类");

用法其实很简单,第一个参数是转换后的类,第二个参数是待转换的类;我们可以理解成为后转前;

原理:

其原理是通过JDK自带的反射机制动态的去get,set,从而去转换我们的类。但是要注意一点他们所支持的数据类型,还有一个就是假如一个类里面又写了一个类,例如这种:

public class Name{

}

class Name1{

}

一般叫做内部类,像这种类进行转换的时候,是不会成功的。因为在里面进行读写校验的时候不会通过;

 

PropertyDescriptor[] origDescriptors =

               getPropertyDescriptors(orig);

           for (int i = 0; i < origDescriptors.length; i++) {

               String name = origDescriptors[i].getName();

               if (isReadable(orig, name) && isWriteable(dest, name)) {

                   try {

                       Object value = getSimpleProperty(orig, name);

                       if (dest instanceof DynaBean) {

                           ((DynaBean) dest).set(name, value);

                       } else {

                               setSimpleProperty(dest, name, value);

                       }

                   } catch (NoSuchMethodException e) {

  
<think>我们参考用户提供的引用内容,特别是引用[3]中明确指出: “BeanUtils.copyProperties 会将源对象 (Payload) 中为 null属性覆盖目标对象 (Entity) 中对应的属性。如果目标对象属性有默认,这个默认就会被 null 覆盖。” 因此,答案是:是的,org.springframework.beans.BeanUtils.copyProperties方法会用源对象中的null覆盖目标对象中对应属性的原有(包括目标对象中已设置的默认)。 同时,引用[2]也提到了该方法的异常处理行为:它不会抛出异常,而是尝试复制可以复制属性。 为了更全面地回答,我们可以结合引用[3]引用[5]的内容: 1. 该方法通过反射机制复制属性。 2. 它会将源对象中所有与目标对象属性名相同的属性复制到目标对象,无论源对象属性是否为null。 因此,在使用时需要注意:如果源对象中某些字段为null,而目标对象中对应的字段原本有(例如默认),则目标对象的这些字段会被覆盖null解决方案(参考引用[3]): 1. 在Payload(源对象)层面使用@NotNull校验,确保某些字段不为null。 2. 在Service层手动判断源对象的字段是否为null,只复制null字段,或者使用其他工具(如BeanUtils.copyProperties的扩展或自定义工具)来避免null覆盖。 另外,引用[4]提到一个关于时间格式的问题,虽然与null覆盖无关,但说明BeanUtils.copyProperties在使用时还可能存在类型转换或格式丢失的问题,需要留意。 综上所述,回答用户的问题:org.springframework.beans.BeanUtils.copyProperties方法确实会用源对象中的null覆盖目标对象中的原有。 </think>根据引用内容,org.springframework.beans.BeanUtils.copyProperties()**会使用源对象中的null覆盖目标对象的原有**。以下是关键证据分析: ### 📌 核心结论 1. **null覆盖目标属性**(引用[3]明确说明) > "BeanUtils.copyProperties 会将源对象 (Payload) 中为 null属性覆盖目标对象 (Entity) 中对应的属性。如果目标对象属性有默认,这个默认就会被 null 覆盖。"[^3] 2. **覆盖机制原理** - 该方法通过反射复制**所有同名属性**,无论是否为null(引用[5]) - 不进行空值过滤,源对象null直接覆盖目标对象对应属性[^3][^5] ### 实际影响案例 1. **数据库字段报错** 目标实体字段有默认(如 `private Integer status = 1;`),但被源对象null覆盖后,保存时触发 `Column 'xxx' cannot be null` 数据库异常[^3] 2. **时间格式数据丢失** 源对象时间字段为 `2023-01-01 12:30:45`,目标对象覆盖后变成 `2023-01-01 00:00:00`(引用[4]) ### 🔧 解决方案(引用[3]) 1. **Payload校验** 在源对象字段添加 `@NotNull` 注解 ```java public class Payload { @NotNull private Integer status; } ``` 2. **自定义复制逻辑** ```java // 手动跳过null复制 if (source.getStatus() != null) { target.setStatus(source.getStatus()); } ``` 3. **使用安全工具替代** 如 Spring 的 `BeanWrapper` 或 MapStruct 等支持忽略null工具 ### 🌟 设计本质 - **无类型转换保护**:不会因类型不匹配抛出异常(引用[2]) - **反射级覆盖**:通过 `Method.invoke()` 直接赋,不保留目标对象原始(引用[5])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值