使用CGlib实现Bean拷贝(BeanCopier)
https://blog.csdn.net/zmx729618/article/details/78363191
二、自定义转换器
当源和目标类的属性类型不同时,不能拷贝该属性,此时我们可以通过实现Converter接口来自定义转换器
源类和目标类:
Java代码
- public class AccountEntity {
- private int id;
- private Timestamp createTime;
- private BigDecimal balance;
- // Getters and setters are omitted
- }
Java代码
- public class AccountDto {
- private int id;
- private String name;
- private String createTime;
- private String balance;
- // Getters and setters are omitted
- }
1. 不使用Converter
Java代码
-
public class BeanCopierConverterTest {
-
@Test
-
public void noConverterTest() {
-
AccountEntity po = new AccountEntity();
-
po.setId(1);
-
po.setCreateTime(new Timestamp(10043143243L));
-
po.setBalance(BigDecimal.valueOf(4000L));
-
BeanCopier copier = BeanCopier.create(AccountEntity.class, AccountDto.class, false);
-
AccountDto dto = new AccountDto();
-
copier.copy(po, dto, null);
-
Assert.assertNull(dto.getCreateTime()); // 类型不同,未拷贝
-
Assert.assertNull(dto.getBalance()); // 类型不同,未拷贝
-
}
-
}
2. 使用Converter
基于目标对象的属性出发,如果源对象有相同名称的属性,则调一次convert方法:
Java代码
-
package net.sf.cglib.core;
-
public interface Converter {
-
// value 源对象属性,target 目标对象属性类,context 目标对象setter方法名
-
Object convert(Object value, Class target, Object context);
-
}
Java代码
-
@Test
-
public void converterTest() {
-
AccountEntity po = new AccountEntity();
-
po.setId(1);
-
po.setCreateTime(Timestamp.valueOf("2014-04-12 16:16:15"));
-
po.setBalance(BigDecimal.valueOf(4000L));
-
BeanCopier copier = BeanCopier.create(AccountEntity.class, AccountDto.class, true);
-
AccountConverter converter = new AccountConverter();
-
AccountDto dto = new AccountDto();
-
copier.copy(po, dto, converter);
-
Assert.assertEquals("2014-04-12 16:16:15", dto.getCreateTime());
-
Assert.assertEquals("4000", dto.getBalance());
-
}
-
static class AccountConverter implements Converter {
-
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
@SuppressWarnings("rawtypes")
-
@Override
-
public Object convert(Object value, Class target, Object context) {
-
if (value instanceof Integer) {
-
return (Integer) value;
-
} else if (value instanceof Timestamp) {
-
Timestamp date = (Timestamp) value;
-
return sdf.format(date);
-
} else if (value instanceof BigDecimal) {
-
BigDecimal bd = (BigDecimal) value;
-
return bd.toPlainString();
-
}
-
return null;
-
}
-
}
注:一旦使用Converter,BeanCopier只使用Converter定义的规则去拷贝属性,所以在convert方法中要考虑所有的属性。
三、缓存BeanCopier提升性能
BeanCopier拷贝速度快,性能瓶颈出现在创建BeanCopier实例的过程中。 所以,把创建过的BeanCopier实例放到缓存中,下次可以直接获取,提升性能:
Java代码 (http://czj4451.iteye.com/blog/2044150# "复制代码") [图片上传失败...(image-b271-1573722556366)]
[图片上传失败...(image-593c8f-1573722556366)]
-
public class CachedBeanCopier {
-
static final Map<String, BeanCopier> BEAN_COPIERS = new HashMap<String, BeanCopier>();
-
public static void copy(Object srcObj, Object destObj) {
-
String key = genKey(srcObj.getClass(), destObj.getClass());
-
BeanCopier copier = null;
-
if (!BEAN_COPIERS.containsKey(key)) {
-
copier = BeanCopier.create(srcObj.getClass(), destObj.getClass(), false);
-
BEAN_COPIERS.put(key, copier);
-
} else {
-
copier = BEAN_COPIERS.get(key);
-
}
-
copier.copy(srcObj, destObj, null);
-
}
-
private static String genKey(Class<?> srcClazz, Class<?> destClazz) {
-
return srcClazz.getName() + destClazz.getName();
-
}
-
}