//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:
* ===============================================================
* - 基于(同名屬性)的復(fù)制
* - 屬于淺復(fù)制
* - 同名不同類型的屬性,不會復(fù)制(即使存在繼承關(guān)系或是裝拆箱類)e.g. int->Integer
* - 同集合類不同泛型,可以復(fù)制,后續(xù)取出元素時會報(bào)類型轉(zhuǎn)換錯誤,如果后續(xù)只是做比如json序列化,不會影響 e.g. List<Double> -> List<BigDecimal>
* ===============================================================
* TODO:
* - 添加類型轉(zhuǎn)換,解決同名不同類型的屬性復(fù)制的問題
*/
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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 精力管理、注意力管理、高效工作一直是人們關(guān)注的大問題,我曾經(jīng)閱讀過一些有關(guān)的知識,但是并沒有起到很好的效果,于是訂...
- 在edX.com上發(fā)現(xiàn)了一個不錯的課程叫『成為一個有韌性的人』,英文課程名稱是 Becoming a Resili...