Java Bean Copy

Java BeanCopy

后台开发中对象之间的属性复制是一种常见的场景,现在比较用的比较多的有:Apache BeanUtilsSpring BeanUtilsCglib BeanCopier几种。看了些文章说Apache BeanUtils的复制效率是最低的,并且阿里巴巴的开发手册上也特意提到了这一点,即【强制】避免使用Apache BeanUtils进行属性拷贝,这里记录下,加深印象。


1、maven依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <scope>compile</scope>
    </dependency>
    
    <!-- Apache BeanUtils -->
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.3</version>
    </dependency>
    
    <!-- cglib BeanCopier -->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
</dependencies>

2、Source和Target类

/**
 * 源类
 * @author Maverick
 * @Date 2021/9/28
 */
@Data
public class SourceUser {
    private Integer id;
    private String name;
    private Integer age;
    private String fundPassword;
    private String tradePassword;
}

/**
 * 目标类
 * @author Maverick
 * @Date 2021/9/28
 */
@Data
public class TargetUser {
    private Integer id;
    private String name;
    private Integer age;
    private String telephone;
}

3、三种拷贝方法

import net.sf.cglib.beans.BeanCopier;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Maverick
 * @Date 2021/9/29
 */
public class CopyMethods {

    private static final Map<String, BeanCopier> BEAN_COPIER_MAP = new HashMap<>();

    /**
     * Apache BeanUtils
     *
     * @param targetUser
     * @param count
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public static void copyByApacheBeanUtils(TargetUser targetUser, SourceUser sourceUser, int count)
            throws InvocationTargetException, IllegalAccessException {
        long start = System.currentTimeMillis();

        for (int i = 0; i < count; i++) {
            BeanUtils.copyProperties(targetUser, sourceUser);
        }

        long end = System.currentTimeMillis();
        System.out.println("Apache BeanUtils: " + (end - start) + "ms");
    }

    /**
     * Spring BeanUtils
     *
     * @param targetUser
     * @param count
     */
    public static void copyBySpringBeanUtils(TargetUser targetUser, SourceUser sourceUser, int count) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            org.springframework.beans.BeanUtils.copyProperties(targetUser, sourceUser);
        }
        long end = System.currentTimeMillis();
        System.out.println("Spring BeanUtils: " + (end - start) + "ms");
    }

    /**
     * Cglib BeanCopier
     * 注意Cglib的拷贝函数方向: Copy(src, target)
     * 入参(target, source)是为了和常见方式保持一致
     * 加入缓存, 方便提升多次拷贝时的使用效率
     *
     * @param target
     * @param source
     */
    public static void copyByCglibBeanCopier(Object target, Object source) {
        String beanCopierKey = genBeanCopierKey(source.getClass(), target.getClass());
        BeanCopier beanCopier;
        if (BEAN_COPIER_MAP.containsKey(beanCopierKey)) {
            beanCopier = BEAN_COPIER_MAP.get(beanCopierKey);
        } else {
            beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
            BEAN_COPIER_MAP.put(beanCopierKey, beanCopier);
        }
        beanCopier.copy(source, target, null);
    }

    /**
     * 根据src和targe生成组合Key
     *
     * @param srcClazz
     * @param destClazz
     * @return
     */
    private static String genBeanCopierKey(Class<?> srcClazz, Class<?> destClazz) {
        return srcClazz.getName() + destClazz.getName();
    }
}

4、Demo测试

import java.lang.reflect.InvocationTargetException;

/**
 * 测试类
 * @author Maverick
 * @Date 2021/9/28
 */
public class BeanDemo {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        
        SourceUser sourceUser = new SourceUser();
        sourceUser.setId(100);
        sourceUser.setName("张三");
        sourceUser.setAge(20);
        sourceUser.setFundPassword("fund_password");
        sourceUser.setTradePassword("trade_password");

        TargetUser targetUser = new TargetUser();

//        CopyMethods.copyByApacheBeanUtils(targetUser, sourceUser, 1);
//        CopyMethods.copyBySpringBeanUtils(targetUser, sourceUser, 1);
        CopyMethods.copyByCglibBeanCopier(targetUser, sourceUser);

        System.out.println(sourceUser);
        System.out.println(targetUser);
    }
}
posted @ 2022-03-13 22:46  Maverickos  阅读(290)  评论(0编辑  收藏  举报