• BeanCopier类


    网上学习了一番BeanCopier类。

    cglib是一款比较底层的操作java字节码的框架。 

    下面通过拷贝bean对象来测试BeanCopier的特性:

    public class OrderEntity {  
        private int id;  
        private String name;  
        // Getters and setters are omitted  
    }
    public class OrderDto {  
        private int id;  
        private String name;  
        // Getters and setters are omitted  
    }
    public class PropWithDiffType {  
        private Integer id;  
        private String name;  
        // Getters and setters are omitted  
    } 
    public class LackOfSetter {  
        private int id;  
        private String name;  
      
        public LackOfSetter() {  
        }  
      
        public LackOfSetter(int id, String name) {  
            this.id = id;  
            this.name = name;  
        }  
        // Getters and setters are omitted  
        // public void setName(String name) {  
        //  this.name = name;  
        // }  
    }

    1. 属性名称、类型都相同: 

    @Test  
    public void normalCopyTest() {  
        OrderEntity entity = new OrderEntity();  
        entity.setId(1);  
        entity.setName("orderName");  
        final BeanCopier copier = BeanCopier.create(OrderEntity.class, OrderDto.class, false);  
        OrderDto dto = new OrderDto();  
        copier.copy(entity, dto, null);  
        Assert.assertEquals(1, dto.getId());  
        Assert.assertEquals("orderName", dto.getName());  
    } 

    结论:拷贝OK。 

    2. 属性名称相同、类型不同:

    @Test  
    public void sameNameDifferentTypeCopyTest() {  
        OrderEntity entity = new OrderEntity();  
        entity.setId(1);  
        entity.setName("orderName");  
        final BeanCopier copier = BeanCopier.create(OrderEntity.class, PropWithDiffType.class, false);  
        PropWithDiffType dto = new PropWithDiffType();  
        copier.copy(entity, dto, null);  
        Assert.assertEquals(null, dto.getId()); // OrderEntity的id为int类型,而PropWithDiffType的id为Integer类型,不拷贝  
        Assert.assertEquals("orderName", dto.getName());  
    } 

    结论:名称相同而类型不同的属性不会被拷贝。 

    注意:即使源类型是原始类型(int, short和char等),目标类型是其包装类型(Integer, Short和Character等),或反之:都不会被拷贝。 

    3. 源类和目标类有相同的属性(两者的getter都存在),但目标类的setter不存在

    @Test  
    public void targetLackOfSetterCopyTest() {  
        OrderEntity entity = new OrderEntity();  
        entity.setId(1);  
        entity.setName("orderName");  
        final BeanCopier copier = BeanCopier.create(OrderEntity.class, LackOfSetter.class, false);  // 抛NullPointerException  
        LackOfSetter dto = new LackOfSetter();  
        copier.copy(entity, dto, null);  
    } 

    结论:创建BeanCopier的时候抛异常。 

    导致异常的原因是BeanCopier类的第128~133行

    for (int i = 0; i < setters.length; i++) { // 遍历目标类的属性描述集  
        PropertyDescriptor setter = setters[i];  
        PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName()); // 从源类获取和目标类属性名称相同的属性描述  
        if (getter != null) {  
            MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod()); // 获取源类属性的getter方法  
            MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod()); // 获取目标类属性的setter方法。LackOfSetter类name属性的setter方法没有,所以报错

    4. 源类或目标类的setter比getter少

    @Test  
    public void sourceLackOfSetterCopyTest() {  
        LackOfSetter source = new LackOfSetter(1, "throne");  
        final BeanCopier copier = BeanCopier.create(LackOfSetter.class, OrderDto.class, false);  
        OrderDto dto = new OrderDto();  
        copier.copy(source, dto, null);  
        Assert.assertEquals(1, dto.getId());  
        Assert.assertEquals("throne", dto.getName());  
    }

    结论:拷贝OK。此时的setter多余,但不会报错。 

    总结: 

    1. BeanCopier只拷贝名称和类型都相同的属性。 其实,究其原因还是

    BeanCopier copier = BeanCopier.create(OrderEntity.class, PropWithDiffType.class, false);

    最后一个参数useConverter:false,就表示只拷贝同名同类型的属性。但是如果使用useConverter,就要自己根据converter中的规则来进行拷贝。

    引用他人的文章http://czj4451.iteye.com/blog/2044101


    2. 当目标类的setter数目比getter少时,创建BeanCopier会失败而导致拷贝不成功。

  • 相关阅读:
    迭代器实现斐波那契数列
    type 创建类,赋予类静态方法等
    使用types库修改函数
    使用property取代getter和setter方法
    pdb 进行调试
    nonlocal 访问变量
    timeit_list操作测试
    metaclass 拦截类的创建,并返回
    isinstance方法判断可迭代和迭代器
    苹果cms10 官方QQ微信防红防封代码
  • 原文地址:https://www.cnblogs.com/qiuhaojie/p/6856341.html
Copyright © 2020-2023  润新知