总结关于BeanUtils拷贝对象遇到的坑

总结关于BeanUtils拷贝对象遇到的坑

​ 实际开发中经常会用到的BeanUtils的一些方法,比如copyProperties拷贝对象中的属性等,楼主在使用的过程中也遇到了一些坑,总结一下,这里我用到的是Spring的BeanUtils,后面会介绍几种BeanUtils的一些效率相关的问题。

​ 话不多说,首先创建两个对象:

@Getter
@Setter
@Accessors(chain = true)
public class Test1 {
    private Long id;
    private String name;
    private String sex;
}
public class Test2 {
    private Long id;
    private String name;
    private String sex;
}
public static void main(String[] args) {
    Test1 test1 = new Test1()
        .setId(1L)
        .setName("张三")
        .setSex("男");
    Test2 test2 = new Test2();
    BeanUtils.copyProperties(test1, test2);
    System.err.printf(JSON.toJSONString(test2));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tL8nnMMn-1597586805951)(C:\Users\weila\Desktop\image\4.png)]

​ 按道理说这样就可以将test1中的属性值拷贝到Test2中,但是并没有理所应当的拷贝成功,不服输的我立马点进源码看看调用copyProperties的时候到底做了什么。

private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
			@Nullable String... ignoreProperties) throws BeansException {

		Assert.notNull(source, "Source must not be null");
		Assert.notNull(target, "Target must not be null");

		Class<?> actualEditable = target.getClass();
		if (editable != null) {
			if (!editable.isInstance(target)) {
				throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
						"] not assignable to Editable class [" + editable.getName() + "]");
			}
			actualEditable = editable;
		}
		PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
		List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);

		for (PropertyDescriptor targetPd : targetPds) {
			Method writeMethod = targetPd.getWriteMethod();
			if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
				PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
				if (sourcePd != null) {
					Method readMethod = sourcePd.getReadMethod();
					if (readMethod != null &&
							ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
						try {
							if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
								readMethod.setAccessible(true);
							}
							Object value = readMethod.invoke(source);
							if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
								writeMethod.setAccessible(true);
							}
							writeMethod.invoke(target, value);
						}
						catch (Throwable ex) {
							throw new FatalBeanException(
									"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
						}
					}
				}
			}
		}
	}

​ 看完源码之后才发现当调用此方法时是调用了Test2中的Getter和Setter方法。于是我给Test2中加入了Getter和Setter方法。

@Getter
@Setter
public class Test2 {
    private Long id;
    private String name;
    private String sex;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gXLjmvhs-1597586805953)(C:\Users\weila\Desktop\image\5.png)]

​ 此时拷贝成功!

​ 再来介绍另一个坑,如果存在属性相同的内部类,但是属性不是在同一个类中,则调用copyProperties时不会拷贝属性值。

@Getter
@Setter
@Accessors(chain = true)
public class Test3 extends Test2 {
    private Long id;
    private String name;
    private String sex;
}

​ 还是以上述创建的Test1和Test2两个类为例,如果要拷贝Test3这样的一个类,因为上述创建Test2时候同样也有这三个字段,此时有三对重复的字段,这样在调用拷贝对象的方法是是不会拷贝的。

​ https://segmentfault.com/a/1190000022021450/分享这篇文章链接详细介绍了几种BeanUtils的性能问题,大家可以参考参考大牛的测试,包括现在属性拷贝的新工具MapStruct,使用了一次感觉很强大,后续写关于MapStruct的专栏。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值