BeanCopier

使用Converter

当源和目标类的属性类型不同时,不能拷贝该属性,此时我们可以通过实现Converter接口来自定义转换器:

源类和目标类:

    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  
    }  
  1. 不使用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()); // 类型不同,未拷贝  
        }  
    }  

  1. 使用Converter

基于目标对象的属性出发,如果源对象有相同名称的属性,则调一次convert方法:


    package net.sf.cglib.core;  
      
    public interface Converter {  
        // value 源对象属性的值,target 目标对象属性的类,context 目标对象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定义的规则去拷贝属性,所以在convert方法中要考虑所有的属性。

性能优化

BeanCopier拷贝速度快,性能瓶颈出现在创建BeanCopier实例的过程中。所以,把创建过的BeanCopier实例放到缓存中,下次可以直接获取,提升性能:

public class CachedBeanCopier {  
  
    static final Map BEAN_COPIERS = new HashMap();  
  
    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();  
    }  
}  

你可能感兴趣的:(BeanCopier)