对象的拷贝,我们还可以这样

51 阅读1分钟
package com.lion.mybatis.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
 * @Author: lion
 * @Date: 2023/2/22
 * 基于 cglib 的对象拷贝工具
 */
public class BeanUtils {

    /**
     * 缓存 BeanCopier 对象,提升性能
     */
    private static final ConcurrentHashMap<String, org.springframework.cglib.beans.BeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>();

    /**
     * Bean 属性复制工具方法
     * @param sources 原始集合
     * @param supplier 目标类 :: new(eg: UserVO :: new)
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> cgLibCopyList(List<S> sources, Supplier<T> supplier) {
        List<T> list = new ArrayList<>(sources.size());
        org.springframework.cglib.beans.BeanCopier beanCopier = null;
        for (S source: sources) {
            T t = supplier.get();
            if(beanCopier == null){
                beanCopier = getBeanCopier(source.getClass(), t.getClass());
            }
            beanCopier.copy(source, t, null);
            list.add(t);
        }
        return list;
    }

    /**
     * Bean属性赋值工具方法
     * @param source 目标对象
     * @param supplier 目标类 :: new(eg: UserVO :: new)
     * @param <T>
     * @return
     */
    public static <T> T cgLibCopyBean(Object source, Supplier<T> supplier){
        T t = supplier.get();
        getBeanCopier(source.getClass(), t.getClass()).copy(source, t, null);
        return t;
    }

    /**
     * 获取 BeanCopier 对象,如果缓存中有,就从缓存中获取,如果缓存中没有,则创建新对象并加入缓存
     * @param sourceClass
     * @param targetClass
     * @return
     */
    private static org.springframework.cglib.beans.BeanCopier getBeanCopier(Class<?> sourceClass, Class<?> targetClass) {
        String key = getKey(sourceClass.getName(), targetClass.getName());
        org.springframework.cglib.beans.BeanCopier beanCopier;
        beanCopier = BEAN_COPIER_MAP.get(key);
        if(beanCopier == null){
            beanCopier = org.springframework.cglib.beans.BeanCopier.create(sourceClass, targetClass, false);
            BEAN_COPIER_MAP.put(key, beanCopier);
        }
        return beanCopier;
    }

    /**
     * 生成缓存key
     * @param sourceClassName
     * @param targetClassName
     * @return
     */
    private static String getKey(String sourceClassName, String  targetClassName){
        return sourceClassName + targetClassName;
    }
}