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會失敗而導致拷貝不成功。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM