前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >cglib BeanCopier 使用

cglib BeanCopier 使用

作者头像
全栈程序员站长
发布2022-10-29 10:20:32
6360
发布2022-10-29 10:20:32
举报

大家好,又见面了,我是你们的朋友全栈君。

cglib是一款比较底层的操作java字节码的框架。 下面通过拷贝bean对象来测试BeanCopier的特性:

Java代码

  1. public class OrderEntity {
  2. private int id;
  3. private String name;
  4. // Getters and setters are omitted
  5. }

Java代码

  1. public class OrderDto {
  2. private int id;
  3. private String name;
  4. // Getters and setters are omitted
  5. }

Java代码

  1. public class PropWithDiffType {
  2. private Integer id;
  3. private String name;
  4. // Getters and setters are omitted
  5. }

Java代码

  1. public class LackOfSetter {
  2. private int id;
  3. private String name;
  4. public LackOfSetter() {
  5. }
  6. public LackOfSetter(int id, String name) {
  7. this.id = id;
  8. this.name = name;
  9. }
  10. // Getters and setters are omitted
  11. // public void setName(String name) {
  12. // this.name = name;
  13. // }
  14. }

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

Java代码

  1. @Test
  2. public void normalCopyTest() {
  3. OrderEntity entity = new OrderEntity();
  4. entity.setId(1);
  5. entity.setName(“orderName”);
  6. final BeanCopier copier = BeanCopier.create(OrderEntity.class, OrderDto.class, false);
  7. OrderDto dto = new OrderDto();
  8. copier.copy(entity, dto, null);
  9. Assert.assertEquals(1, dto.getId());
  10. Assert.assertEquals(“orderName”, dto.getName());
  11. }

结论:拷贝OK。 2. 属性名称相同、类型不同:

Java代码

  1. @Test
  2. public void sameNameDifferentTypeCopyTest() {
  3. OrderEntity entity = new OrderEntity();
  4. entity.setId(1);
  5. entity.setName(“orderName”);
  6. final BeanCopier copier = BeanCopier.create(OrderEntity.class, PropWithDiffType.class, false);
  7. PropWithDiffType dto = new PropWithDiffType();
  8. copier.copy(entity, dto, null);
  9. Assert.assertEquals(null, dto.getId()); // OrderEntity的id为int类型,而PropWithDiffType的id为Integer类型,不拷贝
  10. Assert.assertEquals(“orderName”, dto.getName());
  11. }

结论:名称相同而类型不同的属性不会被拷贝。 注意:即使源类型是 原始类型 (int, short和char等),目标类型是其 包装类型 (Integer, Short和Character等),或反之:都 不会被拷贝 。 3. 源类和目标类有相同的属性(两者的getter都存在),但目标类的setter不存在

Java代码

  1. @Test
  2. public void targetLackOfSetterCopyTest() {
  3. OrderEntity entity = new OrderEntity();
  4. entity.setId(1);
  5. entity.setName(“orderName”);
  6. final BeanCopier copier = BeanCopier.create(OrderEntity.class, LackOfSetter.class, false); // 抛NullPointerException
  7. LackOfSetter dto = new LackOfSetter();
  8. copier.copy(entity, dto, null);
  9. }

结论:创建BeanCopier的时候抛异常。 导致异常的原因是BeanCopier类的第128~133行

Java代码

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

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

Java代码

  1. @Test
  2. public void sourceLackOfSetterCopyTest() {
  3. LackOfSetter source = new LackOfSetter(1, “throne”);
  4. final BeanCopier copier = BeanCopier.create(LackOfSetter.class, OrderDto.class, false);
  5. OrderDto dto = new OrderDto();
  6. copier.copy(source, dto, null);
  7. Assert.assertEquals(1, dto.getId());
  8. Assert.assertEquals(“throne”, dto.getName());
  9. }

结论:拷贝OK。此时的setter多余,但不会报错。 总结: 1. BeanCopier只拷贝名称和类型都相同的属性。 2. 当目标类的setter数目比getter少时,创建BeanCopier会失败而导致拷贝不成功。

——————————–2222222222222222222222222222222————————————————————–

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

源类和目标类:

Java代码

  1. public class AccountEntity {
  2. private int id;
  3. private Timestamp createTime;
  4. private BigDecimal balance;
  5. // Getters and setters are omitted
  6. }

Java代码

  1. public class AccountDto {
  2. private int id;
  3. private String name;
  4. private String createTime;
  5. private String balance;
  6. // Getters and setters are omitted
  7. } 1. 不使用Converter

Java代码

  1. public class BeanCopierConverterTest {
  2. @Test
  3. public void noConverterTest() {
  4. AccountEntity po = new AccountEntity();
  5. po.setId(1);
  6. po.setCreateTime(new Timestamp(10043143243L));
  7. po.setBalance(BigDecimal.valueOf(4000L));
  8. BeanCopier copier = BeanCopier.create(AccountEntity.class, AccountDto.class, false);
  9. AccountDto dto = new AccountDto();
  10. copier.copy(po, dto, null);
  11. Assert.assertNull(dto.getCreateTime()); // 类型不同,未拷贝
  12. Assert.assertNull(dto.getBalance()); // 类型不同,未拷贝
  13. }
  14. } 2. 使用Converter 基于目标对象的属性出发,如果源对象有相同名称的属性,则调一次convert方法:

Java代码

  1. package net.sf.cglib.core;
  2. public interface Converter {
  3. // value 源对象属性,target 目标对象属性类,context 目标对象setter方法名
  4. Object convert(Object value, Class target, Object context);
  5. }

Java代码

  1. @Test
  2. public void converterTest() {
  3. AccountEntity po = new AccountEntity();
  4. po.setId(1);
  5. po.setCreateTime(Timestamp.valueOf(“2014-04-12 16:16:15”));
  6. po.setBalance(BigDecimal.valueOf(4000L));
  7. BeanCopier copier = BeanCopier.create(AccountEntity.class, AccountDto.class, true);
  8. AccountConverter converter = new AccountConverter();
  9. AccountDto dto = new AccountDto();
  10. copier.copy(po, dto, converter);
  11. Assert.assertEquals(“2014-04-12 16:16:15”, dto.getCreateTime());
  12. Assert.assertEquals(“4000”, dto.getBalance());
  13. }
  14. static class AccountConverter implements Converter {
  15. SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
  16. @SuppressWarnings(“rawtypes”)
  17. @Override
  18. public Object convert(Object value, Class target, Object context) {
  19. if (value instanceof Integer) {
  20. return (Integer) value;
  21. } else if (value instanceof Timestamp) {
  22. Timestamp date = (Timestamp) value;
  23. return sdf.format(date);
  24. } else if (value instanceof BigDecimal) {
  25. BigDecimal bd = (BigDecimal) value;
  26. return bd.toPlainString();
  27. }
  28. return null;
  29. }
  30. }

注:一旦使用Converter,BeanCopier只使用Converter定义的规则去拷贝属性,所以在convert方法中要考虑所有的属性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197132.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月5日 上,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档