/**
* Bean操作工具类
*/
public class BeanUtils {
/**
* Bean复制,换用Spring的copyProperties方法,防止目标bean使用@Accessors(chain=true)后,CGLib的对象拷贝有问题
*
* @param srcBean 源bean对象
* @param targetBean 目标bean对象
*/
public static void copyBean(Object srcBean, Object targetBean) {
if (srcBean == null || targetBean == null) {
return;
}
org.springframework.beans.BeanUtils.copyProperties(srcBean, targetBean);
}
/**
* Bean复制,浅复制
*
* @param srcBean 源Bean对象
* @param targetClass 目标对象Class
* @param <T> 目标类型
* @return 目标Bean
*/
public static <T> T copyBean(Object srcBean, Class<T> targetClass) {
if (srcBean == null) {
return null;
}
try {
T targetBean = targetClass.newInstance();
copyBean(srcBean, targetBean);
return targetBean;
} catch (Exception e) {
throw new RuntimeException("对象拷贝异常", e);
}
}
/**
* List复制,属浅复制
*
* @param srcList 源List对象
* @param targetClass 目标列表Bean类
* @param <T> 列表Bean Type
* @return 目标列表
*/
public static <T> List<T> copyBeanList(List srcList, Class<T> targetClass) {
List<T> targetBeanList = new ArrayList<>();
if (srcList == null || srcList.isEmpty()) {
return targetBeanList;
}
try {
for (Object srcObj : srcList) {
T targetBean = targetClass.newInstance();
copyBean(srcObj, targetBean);
targetBeanList.add(targetBean);
}
} catch (Exception e) {
throw new RuntimeException("对象拷贝异常", e);
}
return targetBeanList;
}
/**
* Bean复制,深度复制
*
* @param srcBean 源Bean对象
* @param targetClass 目标对象Class
* @param <T> 目标类型
* @return 目标Bean
*/
public static <T> T deepCopyBean(Object srcBean, Class<T> targetClass) {
if (srcBean == null) {
return null;
}
try {
T targetBean = targetClass.newInstance();
deepCopyBean(srcBean, targetBean);
return targetBean;
} catch (Exception e) {
throw new RuntimeException("对象拷贝异常", e);
}
}
/**
* Bean复制,深度复制
*
* @param source 源Bean对象
* @param target 目标Bean对象
*/
public static void deepCopyBean(Object source, Object target) {
Class<?> actualEditable = target.getClass();
PropertyDescriptor[] targetPds = org.springframework.beans.BeanUtils.getPropertyDescriptors(actualEditable);
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null) {
PropertyDescriptor sourcePd = org.springframework.beans.BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null &&
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
//主要的核心在这里:针对Field的类型为Collection类型的处理
if (value instanceof Collection) {
Type writeType = writeMethod.getGenericParameterTypes()[0];
Type readType = readMethod.getGenericReturnType();
Type writeActualType;
//当 source 中 Collection类型的Field的泛型和target中的Field的泛型类型不一致的时候 需要进行深度拷贝
if (writeType instanceof ParameterizedType
&& readType instanceof ParameterizedType
&& (writeActualType = ((ParameterizedType) writeType).getActualTypeArguments()[0]) != ((ParameterizedType) readType).getActualTypeArguments()[0]) {
//这里只是简单的调用反射来实例化,因此原集合类型必须要有无参构造,比如Arrays.asList创建的集合则无法拷贝,会抛出异常
Collection sourceList = (Collection) value;
Collection actualValue;
//兼容Arrays.asList创建的集合,获取类名为java.util.Arrays$ArrayList,则直接设置actualValue为new ArrayList,避免因没有无参构造调用newInstance报错的问题
if (value.getClass().toString().equals("class java.util.Arrays$ArrayList") || value.getClass().toString().equals("class java.util.Collections$EmptyList")) {
actualValue = new ArrayList();
} else {
actualValue = (Collection) value.getClass().newInstance();
}
actualValue.clear();
for (Object subSource : sourceList) {
Object subTarget = ((Class) writeActualType).newInstance();
deepCopyBean(subSource, subTarget);
actualValue.add(subTarget);
}
value = actualValue;
}
}
writeMethod.invoke(target, value);
} catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
}
/**
* List复制,深度复制
*
* @param srcList 源List
* @param targetClass 目标List元素类
* @param <T> 目标元素类型
* @return 目标List
*/
public static <T> List<T> deepCopyBeanList(List srcList, Class<T> targetClass) {
return deepCopyBeanList(srcList, targetClass, null);
}
/**
* 深度克隆
*
* @param srcList 源List
* @param targetClass 目标Class
* @param cloneConsumer 克隆消费类,可处理自定义转换属性
* @param <T> 目标类型
* @param <R> 源类型
*/
public static <T, R> List<T> deepCopyBeanList(List<R> srcList, Class<T> targetClass, BiConsumer<R, T> cloneConsumer) {
List<T> targetBeanList = new ArrayList<>();
if (srcList == null || srcList.isEmpty()) {
return targetBeanList;
}
try {
for (R srcObj : srcList) {
T targetBean = targetClass.newInstance();
deepCopyBean(srcObj, targetBean);
if (cloneConsumer != null) {
cloneConsumer.accept(srcObj, targetBean);
}
targetBeanList.add(targetBean);
}
} catch (Exception e) {
throw new RuntimeException("对象拷贝异常", e);
}
return targetBeanList;
}