BeanCopy工具类

代码

package com.gdpu.util;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.core.Converter;
import org.apache.commons.lang3.ClassUtils;

/**
 * @author mojiazhu
 * @date 2022/12/11 21:52
 */
public class BeanCopyUtil {

    /**
     * beancopier map,缓存已创建的beancopier,避免重复创建,使用ConcurrentMap,保证线程安全 final对象非基本类型时,引用恒定不变,不可修改,但对象本身可被修改
     */
    private final static ConcurrentMap<String, BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<>();

    /**
     * NestedObjectConverter map,缓存已创建的NestedObjectConverter,避免重复创建
     */
    private final static ConcurrentMap<String, NestedObjectConverter> NESTED_OBJECT_CONVERTER_CONCURRENT_MAP
            = new ConcurrentHashMap<>();

    /**
     * 集合copy,将输入集合拷贝至输出集合
     *
     * @param srcColl  输入集合
     * @param dstColl  输出集合
     * @param dstClazz 输出集合中的对象类型
     * @return 输出集合
     */
    public static <T1 extends Collection<?>, T2 extends Collection<T3>, T3> T2 copyList(
            T1 srcColl, T2 dstColl, Class<T3> dstClazz) {
        if (srcColl == null || dstColl == null || dstClazz == null) {
            throw new NullPointerException("Param cannot be null!");
        }

        try {
            for (Object srcObj : srcColl) {
                T3 dstObj = dstClazz.newInstance();
                dstColl.add(copy(srcObj, dstObj));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return dstColl;
    }

    /**
     * 集合深copy,将输入集合拷贝至输出集合
     *
     * @param srcColl  输入集合
     * @param dstColl  输出集合
     * @param dstClazz 输出集合中的对象类型
     * @return 输出集合
     */
    @SuppressWarnings("unchecked")
    private static Collection deepCopyColl(Collection srcColl, Collection dstColl, Class dstClazz)
            throws NullPointerException, InstantiationException, IllegalAccessException {
        if (srcColl == null || dstColl == null || dstClazz == null) {
            throw new NullPointerException("Param cannot be null!");
        }

        for (Object srcObj : srcColl) {
            Object dstObj;
            if (!ClassUtils.isPrimitiveOrWrapper(dstClazz)) {
                dstObj = dstClazz.newInstance();
                NestedObjectConverter nestedObjectConverter = getNestedObjectConverter(dstObj.getClass());
                copyWithConverter(srcObj, dstObj, nestedObjectConverter);
            } else {
                dstObj = srcObj;
            }

            dstColl.add(dstObj);
        }

        return dstColl;
    }

    /**
     * 对象Copy
     *
     * @param src 源对象
     * @param dst 目标对象
     * @return 目标对象
     */
    public static <T1, T2> T2 copy(T1 src, T2 dst) {
        BeanCopier beanCopier = getBeanCopier(src, dst, false);
        beanCopier.copy(src, dst, null);
        return dst;
    }

    /**
     * 深拷贝,支持类中嵌套有复杂对象的拷贝
     *
     * @param src 源对象
     * @param dst 目标对象
     * @return 目标对象
     */
    public static <T1, T2> T2 deepCopy(T1 src, T2 dst) {
        BeanCopier beanCopier = getBeanCopier(src, dst, true);
        NestedObjectConverter nestedObjectConverter = getNestedObjectConverter(dst.getClass());
        beanCopier.copy(src, dst, nestedObjectConverter);
        return dst;
    }

    /**
     * 带转换类的对象Copy
     *
     * @param src 源对象
     * @param dst 目标对象
     * @return 目标对象
     */
    private static <T1, T2> T2 copyWithConverter(T1 src, T2 dst, Converter converter) {
        BeanCopier beanCopier = getBeanCopier(src, dst, true);
        beanCopier.copy(src, dst, converter);
        return dst;
    }

    /**
     * 获取BeanCopier对象,不存在则创建
     *
     * @param src 源对象
     * @param dst 目标对象
     * @return BeanCopier对象
     */
    private static BeanCopier getBeanCopier(Object src, Object dst, boolean hasConverter) {
        if (src == null || dst == null) {
            throw new NullPointerException("Param cannot be null!");
        }

        String srcClassName = src.getClass().getName();
        String dstClassName = dst.getClass().getName();
        String key = srcClassName + "," + dstClassName + "," + String.valueOf(hasConverter);

        if (!BEAN_COPIERS.containsKey(key)) {
            BeanCopier beanCopier = BeanCopier.create(src.getClass(), dst.getClass(), hasConverter);
            BEAN_COPIERS.putIfAbsent(key, beanCopier);
        }

        return BEAN_COPIERS.get(key);
    }

    /**
     * 获取嵌套类转换器,不存在则创建
     *
     * @param enclosingClazz 外部类
     * @return 嵌套类转换器
     */
    private static NestedObjectConverter getNestedObjectConverter(Class enclosingClazz) {
        if (enclosingClazz == null) {
            throw new NullPointerException("Param cannot be null!");
        }

        if (!NESTED_OBJECT_CONVERTER_CONCURRENT_MAP.containsKey(enclosingClazz.getName())) {
            NestedObjectConverter nestedObjectConverter = new NestedObjectConverter(enclosingClazz);
            NESTED_OBJECT_CONVERTER_CONCURRENT_MAP.putIfAbsent(enclosingClazz.getName(), nestedObjectConverter);
        }

        return NESTED_OBJECT_CONVERTER_CONCURRENT_MAP.get(enclosingClazz.getName());
    }

    /**
     * 嵌套对象转换,支持原类和目标类中存在同名的非基础类型或基础类型包装类型的属性的转换 容器类型仅支持ArrayList类型属性的转换
     */
    private static class NestedObjectConverter implements Converter {

        private Class enclosingClass;

        NestedObjectConverter(Class enclosingClass) {
            this.enclosingClass = enclosingClass;
        }

        @Override
        public Object convert(Object o, Class aClass, Object o1) {
            if (o == null || ClassUtils.isPrimitiveOrWrapper(aClass) || o instanceof String) {
                return o;
            }

            // 如果源对象的类为数组类,执行集合拷贝
            try {
                if (Collection.class.isAssignableFrom(o.getClass())) {
                    Method[] methods = enclosingClass.getMethods();
                    for (Method m : methods) {
                        if (m.getName().equals(o1) && Collection.class.isAssignableFrom(m.getParameterTypes()[0])) {
                            Collection dstColl = (Collection) o.getClass().newInstance();
                            return deepCopyColl((Collection) o, dstColl, getGenericSetMethodParameterType(m));
                        }
                    }
                }
                // 非集合类执行普通拷贝
                else {
                    Object dst = aClass.newInstance();
                    return deepCopy(o, dst);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

            return null;
        }

        /**
         * 获得set方法参数的泛型类型
         *
         * @param setMethod set方法
         * @return 泛型类型
         */
        private Class getGenericSetMethodParameterType(Method setMethod) {
            Type genericParameterType = setMethod.getGenericParameterTypes()[0];

            if (genericParameterType instanceof ParameterizedType) {
                ParameterizedType type = (ParameterizedType) genericParameterType;
                return (Class) type.getActualTypeArguments()[0];
            }

            return null;
        }
    }
}

使用

复制对象
复制集合

依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.6</version>
</dependency>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚霞虽美不如你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值