BeanCopier

//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 -> List
 * ===============================================================
 * TODO:
 * - 添加类型转换,解决同名不同类型的属性复制的问题
 */
public abstract class BeanCopierUtil {
    private static final ConcurrentMap  bcCache    = new ConcurrentHashMap<>();
    private static final String                             keySplitor = "->";
    private static final int                                threshold  = 1 << 20;  //>=threshold use parallelstream
    private static final ConcurrentMap constCache = new ConcurrentHashMap<>();

    public static  void copy(S srcObject, D destObject) {
        BeanCopier bc = getBeanCopier(srcObject.getClass(), destObject.getClass());
        bc.copy(srcObject, destObject, null);
    }

    public static  D copy(S srcObject, Class destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class       srcClass    = srcObject.getClass();
        BeanCopier     bc          = getBeanCopier(srcClass, destClass);
        Constructor constructor = getConstructor(destClass);
        D              d           = constructor.newInstance();
        bc.copy(srcObject, d, null);
        return d;
    }

    public static  List copyList(List srcList, Class srcClass, Class destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List    destList = new ArrayList<>();
        BeanCopier bc       = getBeanCopier(srcClass, destClass);

//        FastClass  fastClass   = FastClass.create(destClass);
//        int        constructor = fastClass.getIndex(new Class[]{});
//        Object[]   args        = new Object[]{};
        Constructor 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  List asyncCopyList(List srcList, Class srcClass, Class destClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List    destList = new ArrayList<>();
        BeanCopier bc       = getBeanCopier(srcClass, destClass);

//        FastClass  fastClass   = FastClass.create(destClass);
//        int        constructor = fastClass.getIndex(new Class[]{});
//        Object[]   args        = new Object[]{};
        Constructor 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  void copyList(List srcList, List 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  Constructor getConstructor(Class 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)