法一:使用 BeanWrapper 获取目标对象的非 null 属性并忽略通过反射获取目标对象中非 null 的属性名称,然后将这些属性名称传递给 BeanUtils.copyProperties 的 ignoreProperties 参数,从而避免覆盖。以下是实现代码示例:```javaimport org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
public class BeanCopyUtils {
/**
* 获取目标对象中非 null 的属性名称
*/
public static String[] getNonNullPropertyNames(Object target) {
BeanWrapper beanWrapper = new BeanWrapperImpl(target);
PropertyDescriptor[] pds = beanWrapper.getPropertyDescriptors();
Set<String> nonNullPropertyNames = new HashSet<>();
for (PropertyDescriptor pd : pds) {
Object value = beanWrapper.getPropertyValue(pd.getName());
if (value != null) {
nonNullPropertyNames.add(pd.getName());
}
}
return nonNullPropertyNames.toArray(new String[0]);
}
/**
* 自定义拷贝方法,避免覆盖目标对象中已有的属性
*/
public static void copyPropertiesWithoutOverride(Object source, Object target) {
String[] ignoreProperties = getNonNullPropertyNames(target);
BeanUtils.copyProperties(source, target, ignoreProperties);
}
}
使用示例:javapublic class Example {
public static void main(String[] args) {
// 源对象
Source source = new Source();
source.setName("Alice");
source.setAge(25);
// 目标对象
Target target = new Target();
target.setName("Bob");
target.setAge(30);
// 自定义拷贝
BeanCopyUtils.copyPropertiesWithoutOverride(source, target);
// 输出结果
System.out.println("Target Name: " + target.getName()); // Bob,不会被覆盖
System.out.println("Target Age: " + target.getAge()); // 25,被覆盖
}
}
```
方法二
使用Hutool的BeanUtil 结合`CopyOptions`配置忽略空值
Hutool 提供了`CopyOptions`类,可以通过设置`setIgnoreNullValue(true)`来忽略源对象中的空值,从而避免覆盖目标对象中已有的非空属性。
示例代码:
```java
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
public class Example {
public static void main(String[] args) {
// 源对象
SourceBean source = new SourceBean();
source.setName("Alice");
source.setAge(null); // 源对象中的 age 为空
// 目标对象
TargetBean target = new TargetBean();
target.setName("Bob");
target.setAge(30); // 目标对象中的 age 已有值
// 配置 CopyOptions,忽略空值
CopyOptions options = CopyOptions.create().setIgnoreNullValue(true);
BeanUtil.copyProperties(source, target, options);
// 输出结果
System.out.println("Target Name: " + target.getName()); // 输出: Alice
System.out.println("Target Age: " + target.getAge()); // 输出: 30(未被覆盖)
}
}
class SourceBean {
private String name;
private Integer age;
// Getter 和 Setter 方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
class TargetBean {
private String name;
private Integer age;
// Getter 和 Setter 方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
```