使用Converter
當(dāng)源和目標(biāo)類的屬性類型不同時(shí),不能拷貝該屬性,此時(shí)我們可以通過實(shí)現(xiàn)Converter接口來自定義轉(zhuǎn)換器:
源類和目標(biāo)類:
public class AccountEntity {
private int id;
private Timestamp createTime;
private BigDecimal balance;
// Getters and setters are omitted
}
public class AccountDto {
private int id;
private String name;
private String createTime;
private String balance;
// Getters and setters are omitted
}
- 不使用Converter
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()); // 類型不同,未拷貝
}
}
- 使用Converter
基于目標(biāo)對象的屬性出發(fā),如果源對象有相同名稱的屬性,則調(diào)一次convert方法:
package net.sf.cglib.core;
public interface Converter {
// value 源對象屬性的值,target 目標(biāo)對象屬性的類,context 目標(biāo)對象setter方法名
Object convert(Object value, Class target, Object context);
}
@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定義的規(guī)則去拷貝屬性,所以在convert方法中要考慮所有的屬性。
性能優(yōu)化
BeanCopier拷貝速度快,性能瓶頸出現(xiàn)在創(chuàng)建BeanCopier實(shí)例的過程中。所以,把創(chuàng)建過的BeanCopier實(shí)例放到緩存中,下次可以直接獲取,提升性能:
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();
}
}