/**
* 自定义属性赋值工具
* @author zxq
*/
public class CustomCopyUtil {
/**
* 属性复制方法,兼容自动映射和显式映射两种模式
*
* @param source 源对象
* @param target 目标对象
* @param fieldMapping 显式字段映射(可为 null)
*/
public static void copyProperties(Object source, Object target, Map<String, String> fieldMapping) {
if (source == null || target == null) {
throw new IllegalArgumentException("Source and target objects must not be null.");
}
if (fieldMapping == null) {
fieldMapping = new HashMap<>();
}
// 自动映射字段
autoMapFields(source.getClass(), target.getClass(), fieldMapping);
for (Map.Entry<String, String> entry : fieldMapping.entrySet()) {
String sourceFieldPath = entry.getKey();
String targetFieldPath = entry.getValue();
try {
Object sourceValue = getNestedFieldValue(source, sourceFieldPath);
if (sourceValue != null) {
setNestedFieldValue(target, targetFieldPath, sourceValue);
}
} catch (Exception e) {
System.err.println("Error copying field: " + sourceFieldPath + " -> " + targetFieldPath);
e.printStackTrace();
}
}
}
/**
* 自动匹配字段映射
*
* @param sourceClass 源类
* @param targetClass 目标类
* @param fieldMapping 字段映射
*/
private static void autoMapFields(Class<?> sourceClass, Class<?> targetClass, Map<String, String> fieldMapping) {
for (Field sourceField : sourceClass.getDeclaredFields()) {
String sourceFieldName = sourceField.getName();
// 如果显式映射中没有该字段,尝试自动匹配
if (!fieldMapping.containsKey(sourceFieldName)) {
try {
Field targetField = targetClass.getDeclaredField(sourceFieldName);
if (targetField != null) {
// 自动匹配字段
fieldMapping.putIfAbsent(sourceFieldName, sourceFieldName);
}
} catch (NoSuchFieldException ignored) {
// 如果目标类中不存在该字段,跳过
}
}
}
}
/**
* 获取嵌套字段的值
*/
private static Object getNestedFieldValue(Object obj, String fieldPath) throws Exception {
String[] fields = fieldPath.split("\\.");
Object currentObj = obj;
for (String fieldName : fields) {
if (currentObj == null) {
return null;
}
Field field = currentObj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
currentObj = field.get(currentObj);
}
return currentObj;
}
/**
* 设置嵌套字段的值
*/
private static void setNestedFieldValue(Object obj, String fieldPath, Object value) throws Exception {
String[] fields = fieldPath.split("\\.");
Object currentObj = obj;
for (int i = 0; i < fields.length - 1; i++) {
String fieldName = fields[i];
Field field = currentObj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object nextObj = field.get(currentObj);
if (nextObj == null) {
nextObj = field.getType().getDeclaredConstructor().newInstance();
field.set(currentObj, nextObj);
}
currentObj = nextObj;
}
String finalFieldName = fields[fields.length - 1];
Field finalField = currentObj.getClass().getDeclaredField(finalFieldName);
finalField.setAccessible(true);
finalField.set(currentObj, value);
}
}
使用方法:
public class User {
private String name;
private int age;
private Son son;
}
// Person.java
public class Person {
private String userName;
private String age;
private Son son;
}
// Son.java
public class Son {
private String name;
private int age;
}
public void test(){
User user = new User();
user.setName("Alice");
user.setAge(30);
Son son = new Son();
son.setName("Tom");
son.setAge(10);
user.setSon(son);
Person person = new Person();
CustomCopyUtil.copyProperties(user,person,reverse());
log.error("person:{}",person);
}
public Map<String, String> reverse(){
Map<String, String> fieldMapping = new HashMap<>();
fieldMapping.put("name", "userName");
fieldMapping.put("son.age", "son.age");
return fieldMapping;
}
如果两个实体的变量名是一致的,fieldMapping 可以传 null 或者 空串。变量名不一致的情况要指定映射规则,对象嵌套的场景也可是复制