思路
- 递归复制
测试代码
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ReflectUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.*;
public class DeepCopyPropertiesTest {
public static void main(String[] args) {
List<BeanA> beanAList = CollUtil.newArrayList();
for (int i = 0; i < 3; i++) {
BeanA beanA = new BeanA("beanA" + i, i);
beanAList.add(beanA);
}
BeanA beanA = new BeanA("beanAOutSideTheList", 30);
Map<String, BeanA> map = new HashMap<>();
map.put("aa", beanA);
BeanB beanB = new BeanB("beanB", beanAList, beanA, map);
BeanB copyBeanB = new BeanB();
BeanUtil.deepCopyProperties(beanB, copyBeanB);
Console.log(beanB.getBeanA() == copyBeanB.getBeanA());
Console.log(beanB.getBeanAList().get(1) == copyBeanB.getBeanAList().get(1));
Console.log(beanB.getMap().get("aa") == copyBeanB.getMap().get("aa"));
Console.log(beanB);
Console.log(copyBeanB);
}
}
BeanA
public class BeanA {
private String name = "beanA";
private int age = 20;
public BeanA() {
}
public BeanA(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "BeanA{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
BeanB
public class BeanB {
private String name = "beanB";
@DeepCopy
private List<BeanA> beanAList;
@DeepCopy
private BeanA beanA;
@DeepCopy
private Map<String, BeanA> map;
public BeanB() {
}
public BeanB(String name, List<BeanA> beanAList, BeanA beanA, Map<String, BeanA> map) {
this.name = name;
this.beanAList = beanAList;
this.beanA = beanA;
this.map = map;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<BeanA> getBeanAList() {
return beanAList;
}
public void setBeanAList(List<BeanA> beanAList) {
this.beanAList = beanAList;
}
public BeanA getBeanA() {
return beanA;
}
public void setBeanA(BeanA beanA) {
this.beanA = beanA;
}
public Map<String, BeanA> getMap() {
return map;
}
public void setMap(Map<String, BeanA> map) {
this.map = map;
}
@Override
public String toString() {
return "BeanB{" +
"name='" + name + '\'' +
", beanAList=" + beanAList +
", beanA=" + beanA +
", map=" + map +
'}';
}
}
@DeepCopy
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DeepCopy {
}
/**
* 深度复制,所有带有@{@link DeepCopy}的属性都会被深度复制,支持复制list和map,如果对象不包含无参构造方法或者以自身作为参数的单参数构造方法,需要自行将新的实例放入newInstanceMap中,要忽略的属性放在ignorePropertiesMap中,顶级的key是root,其余的是属性的名称
*
* @param source 源对象
* @param target 目标对象
* @param newInstanceMap 新实例
* @param ignorePropertiesMap 复制时忽略属性
*/
public static void deepCopyProperties(Object source, Object target, Map<Type, Object> newInstanceMap, Map<String, String[]> ignorePropertiesMap) {
String[] ignoreProperties = null;
if (ignorePropertiesMap != null) {
ignoreProperties = ignorePropertiesMap.get("root");
}
BeanUtil.copyProperties(source, target, ignoreProperties);
recursion(source, target, newInstanceMap, ignorePropertiesMap);
}
@SuppressWarnings("unused")
public static void deepCopyProperties(Object source, Object target) {
deepCopyProperties(source, target, null, null);
}
@SuppressWarnings("unused")
public static void deepCopyProperties(Object source, Object target, Map<Type, Object> newInstanceMap) {
deepCopyProperties(source, target, newInstanceMap, null);
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static void recursion(Object source, Object target, Map<Type, Object> newInstanceMap, Map<String, String[]> ignorePropertiesMap) {
if (source instanceof Collection) {
copyCollection((Collection<Object>) source, (Collection<Object>) target, newInstanceMap, ignorePropertiesMap);
return;
}
Field[] fields = ReflectUtil.getFields(source.getClass());
for (Field field : fields) {
Class<?> fieldType = field.getType();
String fieldName = field.getName();
if (fieldType.isPrimitive()) {
continue;
}
Object fieldValue = ReflectUtil.getFieldValue(source, field);
if (fieldValue == null) {
continue;
}
boolean noAnnotation = field.getAnnotation(DeepCopy.class) == null;
if (noAnnotation) {
continue;
}
if (fieldValue instanceof Collection) {
Object newInstance = getInstance(fieldValue, fieldType, newInstanceMap);
copyCollection((Collection) fieldValue, (Collection) newInstance, newInstanceMap, ignorePropertiesMap);
ReflectUtil.setFieldValue(target, fieldName, newInstance);
continue;
}
if (fieldValue instanceof Map) {
Object newInstance = getInstance(fieldValue, fieldType, newInstanceMap);
copyMap((Map) fieldValue, (Map) newInstance, newInstanceMap, ignorePropertiesMap);
ReflectUtil.setFieldValue(target, fieldName, newInstance);
continue;
}
Object newInstance = getInstance(fieldValue, fieldType, newInstanceMap);
String[] ips = null;
if (CollUtil.isNotEmpty(ignorePropertiesMap)) {
ips = ignorePropertiesMap.get(fieldName);
}
BeanUtil.copyProperties(fieldValue, newInstance, ips);
ReflectUtil.setFieldValue(target, fieldName, newInstance);
recursion(fieldValue, newInstance, newInstanceMap, ignorePropertiesMap);
}
}
@SuppressWarnings({"unchecked"})
private static <T> T getInstance(Object fieldValue, Class<T> fieldType, Map<Type, Object> newInstanceMap) {
Object o = null;
if (CollUtil.isNotEmpty(newInstanceMap)) {
o = newInstanceMap.get(fieldType);
}
if (o != null) {
return (T) o;
}
Constructor<?>[] constructors = ReflectUtil.getConstructors(fieldType);
for (Constructor<?> constructor : constructors) {
try {
o = constructor.newInstance(fieldValue);
} catch (Exception ignored) {
}
}
if (o != null) {
return (T) o;
}
try {
o = ReflectUtil.newInstance(fieldType);
} catch (UtilException ignored) {
}
if (o != null) {
return (T) o;
}
if (fieldValue instanceof List) {
o = new ArrayList<>();
}
if (o != null) {
return (T) o;
}
if (fieldValue instanceof Set) {
o = new HashSet<>();
}
if (o != null) {
return (T) o;
}
if (fieldValue instanceof Map) {
o = new HashMap<>();
}
if (o != null) {
return (T) o;
}
throw new UtilException("Instance class [{}] failure!", fieldType);
}
@SuppressWarnings({"unused"})
private static void copyCollection(Collection<Object> source, Collection<Object> target, Map<Type, Object> newInstanceMap, Map<String, String[]> ignorePropertiesMap) {
if (source == null || target == null) {
return;
}
target.clear();
for (Object next : source) {
Object instance = getInstance(next, next.getClass(), newInstanceMap);
target.add(instance);
deepCopyProperties(next, instance, newInstanceMap, ignorePropertiesMap);
}
}
@SuppressWarnings({"unchecked", "rawtypes", "SameParameterValue"})
private static void copyMap(Map source, Map target, Map<Type, Object> newInstanceMap, Map<String, String[]> ignorePropertiesMap) {
if (source == null || target == null) {
return;
}
target.clear();
Set<Map.Entry> sourceEntrySet = source.entrySet();
for (Map.Entry sourceEntry : sourceEntrySet) {
Object key = sourceEntry.getKey();
Object value = sourceEntry.getValue();
Object keyInstance = getInstance(key, key.getClass(), newInstanceMap);
Object valueInstance = getInstance(value, value.getClass(), newInstanceMap);
deepCopyProperties(key, keyInstance, newInstanceMap, ignorePropertiesMap);
deepCopyProperties(value, valueInstance, newInstanceMap, ignorePropertiesMap);
target.put(keyInstance, valueInstance);
}
}
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.4</version>
</dependency>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73813.html