Java Bean Copy
Java BeanCopy
后台开发中对象之间的属性复制是一种常见的场景,现在比较用的比较多的有:Apache BeanUtils
、Spring BeanUtils
和Cglib 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);
}
}