//import net.sf.cglib.bean.BeanCopier; //v3.2.7 bug,v3.2.5 success
import com.ft.suse.core.exception.LambdaExceptionWrappers;
import org.springframework.cglib.beans.BeanCopier;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* NOTE:
* ===============================================================
* - 基于(同名属性)的复制
* - 属于浅复制
* - 同名不同类型的属性,不会复制(即使存在继承关系或是装拆箱类)e.g. int->Integer
* - 同集合类不同泛型,可以复制,后续取出元素时会报类型转换错误,如果后续只是做比如json序列化,不会影响 e.g. List<Double> -> List<BigDecimal>
* ===============================================================
* TODO:
* - 添加类型转换,解决同名不同类型的属性复制的问题
*/
public abstract class BeanCopierUtil {
private static final ConcurrentMap<String, BeanCopier> bcCache = new ConcurrentHashMap<>();
private static final String keySplitor = "->";
private static final int threshold = 1 << 20; //>=threshold use parallelstream
private static final ConcurrentMap<String, Constructor> constCache = new ConcurrentHashMap<>();
public static <S, D> void copy(S srcObject, D destObject) {
BeanCopier bc = getBeanCopier(srcObject.getClass(), destObject.getClass());
bc.copy(srcObject, destObject, null);
}
public static <S, D> D copy(S srcObject, Class<D> destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> srcClass = srcObject.getClass();
BeanCopier bc = getBeanCopier(srcClass, destClass);
Constructor<D> constructor = getConstructor(destClass);
D d = constructor.newInstance();
bc.copy(srcObject, d, null);
return d;
}
public static <S, D> List<D> copyList(List<S> srcList, Class<S> srcClass, Class<D> destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
List<D> destList = new ArrayList<>();
BeanCopier bc = getBeanCopier(srcClass, destClass);
// FastClass fastClass = FastClass.create(destClass);
// int constructor = fastClass.getIndex(new Class[]{});
// Object[] args = new Object[]{};
Constructor<D> constructor = getConstructor(destClass);
for (S s : srcList) {
// D d = (D) fastClass.newInstance(constructor, args);
D d = constructor.newInstance();
destList.add(d);
if (s == null || d == null) {
continue;
}
bc.copy(s, d, null);
}
return destList;
}
public static <S, D> List<D> asyncCopyList(List<S> srcList, Class<S> srcClass, Class<D> destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
List<D> destList = new ArrayList<>();
BeanCopier bc = getBeanCopier(srcClass, destClass);
// FastClass fastClass = FastClass.create(destClass);
// int constructor = fastClass.getIndex(new Class[]{});
// Object[] args = new Object[]{};
Constructor<D> constructor = getConstructor(destClass);
srcList.parallelStream().forEachOrdered(LambdaExceptionWrappers.uncheckedConsumerWrapper(s -> {
D d = null;
// d = (D) fastClass.newInstance(constructor, args);
d = constructor.newInstance();
destList.add(d);
if (s == null || d == null) {
return;
}
bc.copy(s, d, null);
}, null));
return destList;
}
public static <S, D> void copyList(List<S> srcList, List<D> destList, int srcOffset, int destOffset, int len) {
if (srcList == null || destList == null || srcList.isEmpty() || destList.isEmpty()) {
throw new IllegalArgumentException("srcList and destList required not empty.");
}
if (srcOffset < 0 || destOffset < 0) {
throw new IllegalArgumentException("srcOffset and destOffset required >=0.");
}
if (len < 1) {
throw new IllegalArgumentException("len required >0.");
}
int srcSize = srcList.size();
int destSize = destList.size();
if (srcSize < srcOffset + len || destSize < destOffset + len) {
throw new IllegalArgumentException("srcOffset+len and destOffset+len required not out of range.");
}
Class<?> srcClass = srcList.get(srcOffset).getClass();
Class<?> destClass = destList.get(destOffset).getClass();
BeanCopier bc = getBeanCopier(srcClass, destClass);
for (int i = 0; i < len; i++) {
bc.copy(srcList.get(srcOffset + i), destList.get(destOffset + i), null);
}
}
private static <D> Constructor<D> getConstructor(Class<D> destClass) {
return constCache.computeIfAbsent(destClass.getName(),
LambdaExceptionWrappers.uncheckedFunctionWrapper(key -> destClass.getConstructor(), null));
}
private static BeanCopier getBeanCopier(Class<?> srcClass, Class<?> destClass) {
String key = generateKey(srcClass, destClass);
BeanCopier bc = bcCache.computeIfAbsent(key, k -> {
return BeanCopier.create(srcClass, destClass, false);
});
return bc;
}
private static String generateKey(Class<?> srcClass, Class<?> destClass) {
StringBuilder sb = new StringBuilder("");
String srcClassName = srcClass.getName();
String destClassName = destClass.getName();
sb.append(srcClassName).append(keySplitor).append(destClassName);
return sb.toString();
}
}
BeanCopier
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...