網上學習了一番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會失敗而導致拷貝不成功。