package com.vci.starter.web.util;
|
|
import com.vci.starter.web.toolmodel.DateConverter;
|
import org.springframework.cglib.beans.BeanCopier;
|
import org.springframework.cglib.core.Converter;
|
|
import java.util.*;
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentMap;
|
|
/**
|
* 对象拷贝工具类
|
* 使用的cglib的beancopier,因为使用了转换器,所以性能比没有使用转换器的要低一些
|
* 会自动判断是否需要转换器,当有属性相同,类型不同,和有对象类型,map,list等集合类型时才需要转换器
|
* @author weidy
|
* @date 2019/11/23 9:22 AM
|
*/
|
public class BeanUtil {
|
|
|
/**
|
* 存放拷贝对象的缓存
|
*/
|
private static final ConcurrentMap<String,BeanCopier> beanCopierMap = new ConcurrentHashMap<>();
|
|
/**
|
* 获取类拷贝的对象
|
* @param source 源对象类
|
* @param target 目标对象类
|
* @param useConverter 是否使用转换器
|
* @return 拷贝对象
|
*/
|
public static BeanCopier getBeanCopier(Class<?> source, Class<?> target,boolean useConverter) {
|
String beanCopierKey = generateBeanKey(source, target);
|
if (beanCopierMap.containsKey(beanCopierKey)) {
|
return beanCopierMap.get(beanCopierKey);
|
} else {
|
BeanCopier beanCopier = BeanCopier.create(source, target, useConverter);
|
beanCopierMap.putIfAbsent(beanCopierKey, beanCopier);
|
}
|
return beanCopierMap.get(beanCopierKey);
|
}
|
|
/**
|
* 生成两个类的key,用于存放到缓存之中
|
* @param source 源对象类型
|
* @param target 目标对象类
|
* @return 两个类的名称连接到一起后的名字
|
*/
|
public static String generateBeanKey(Class<?> source, Class<?> target) {
|
return source.getName() + "@" + target.getName();
|
}
|
|
/**
|
* 两个对象之间转换
|
* @param source 源对象
|
* @param target 目标对象
|
* @param useConvert 是否使用默认的转换器,请在出现属性名称相同而类型不同,或者有对象类型,集合属性时才转换
|
*/
|
public static void convert(Object source,Object target,boolean useConvert){
|
if(source != null && target !=null){
|
BeanCopier beanCopier = getBeanCopier(source.getClass(),target.getClass(),useConvert);
|
beanCopier.copy(source,target,useConvert?new DeepCopyConverter(target):null);
|
}
|
}
|
|
/**
|
* 两个对象之间转换
|
* @param source 源对象
|
* @param target 目标对象
|
* @return 目标对象
|
*/
|
public static void convert(Object source,Object target){
|
convert(source,target,true);
|
}
|
|
/**
|
* 深度拷贝转换器
|
*/
|
public static class DeepCopyConverter implements Converter {
|
|
/**
|
* 目标对象
|
*/
|
private Object target;
|
|
/**
|
* 构造方法
|
* @param target 目标对象
|
*/
|
public DeepCopyConverter(Object target) {
|
this.target = target;
|
}
|
|
/**
|
* 执行拷贝
|
* @param value 源对象的属性的值
|
* @param targetClazz 目标对象的属性的类
|
* @param methodName set方法的名字
|
* @return 转换后的值
|
*/
|
@Override
|
public Object convert(Object value, Class targetClazz, Object methodName) {
|
if (value instanceof List) {
|
List values = (List) value;
|
List retList = new ArrayList<>(values.size());
|
copyForCollection(values,retList,methodName);
|
return retList;
|
} else if(value instanceof Set){
|
Set values = (Set) value;
|
Set retSet = new HashSet<>();
|
copyForCollection(values,retSet,methodName);
|
} else if(value instanceof Vector){
|
Vector values = (Vector)value;
|
Vector retVector = new Vector();
|
copyForCollection(values,retVector,methodName);
|
}else if (value instanceof Map) {
|
Map values = (Map)value;
|
Map retMap = new HashMap();
|
for (final Object key : values.keySet()) {
|
Object mapValue = values.get(key);
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try{
|
targetAttr = clazz.newInstance();
|
}catch (Throwable e){
|
//新的对象的属性初始化出错
|
}
|
BeanUtil.convert(mapValue, targetAttr);
|
retMap.put(key,targetAttr);
|
}
|
} else if (!ClassUtil.isPrimitive(targetClazz)) {
|
//这个是对象类型
|
Object targetAttr = null;
|
try{
|
targetAttr = targetClazz.newInstance();
|
}catch (Throwable e){
|
//新的对象属性初始化出错
|
}
|
BeanUtil.convert(value, targetAttr);
|
return targetAttr;
|
}
|
if(value instanceof Boolean && targetClazz.equals(String.class)){
|
//从boolean拷贝到string
|
return String.valueOf(value);
|
}
|
if(value instanceof String && (targetClazz.equals(Boolean.class)
|
|| targetClazz.equals(boolean.class))){
|
//从String拷贝到boolean
|
if("true".equalsIgnoreCase((String)value)){
|
return true;
|
}else{
|
return false;
|
}
|
}
|
if(value instanceof Date && targetClazz.equals(String.class)){
|
//时间格式
|
return VciDateUtil.date2Str((Date)value,VciDateUtil.DateTimeMillFormat);
|
}
|
if(value instanceof String && targetClazz.equals(Date.class)){
|
//转换
|
DateConverter dateConverter = new DateConverter();
|
dateConverter.setAsText((String)value);
|
return dateConverter.getValue();
|
}
|
return value;
|
}
|
|
/**
|
* 处理集合属性
|
* @param sourceCollection 源对象中集合属性的的值
|
* @param targetCollection 目标对象的集合属性的值
|
* @param methodName setter方法
|
*/
|
private void copyForCollection(Collection<?> sourceCollection,Collection targetCollection,Object methodName){
|
for (final Object source : sourceCollection) {
|
if(source instanceof Collection){
|
List<Object> targetValues = new ArrayList<>();
|
copyForCollection((Collection<?>)source,targetValues,methodName);
|
targetCollection.add(targetValues);
|
}else if(source instanceof Map){
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try {
|
targetAttr = clazz.newInstance();
|
} catch (Throwable e) {
|
//新的对象的属性初始化出错
|
}
|
Map map = (Map) source;
|
for(Object key : map.keySet()){
|
VciBaseUtil.setValueForField(key.toString(),targetAttr,VciBaseUtil.getStringValueFromObject(map.get(key)));
|
}
|
targetCollection.add(targetAttr);
|
}else {
|
String tempFieldName = methodName.toString().replace("set",
|
"");
|
String fieldName = tempFieldName.substring(0, 1)
|
.toLowerCase() + tempFieldName.substring(1);
|
Class clazz = ClassUtil.getElementType(target.getClass(), fieldName);
|
Object targetAttr = null;
|
try {
|
targetAttr = clazz.newInstance();
|
} catch (Throwable e) {
|
//新的对象的属性初始化出错
|
}
|
BeanUtil.convert(source, targetAttr);
|
targetCollection.add(targetAttr);
|
}
|
}
|
}
|
}
|
|
|
}
|