hello大家好,相信大家对这个工具类的使用一定很频繁吧,特别是在写接口的时候进行拷贝DTO对象的时候。最近写项目的时候发现这个spring中这个BeanUtils.copyProperties()中的一些小坑。这里想分享给分大家。下面我写了一个案例大家可以参考一下。
Person类,并且使用了依赖lombook.
Stundent类,并且使用了依赖lombook.
可以看到上面两个类中拥有同样的属性name,并且两者的数据类型是一致的,但是sex属性在Person和Student中的数据类型不一致,这里我们要验证如果数据类型不一致的话是否可以将Person里面的sex属性拷贝给Student属性呢。话不多说,直接测试。可以发现下面的这个实际上是并没有进行拷贝成功的。我查了一下这个实际上底层用的是发射技术实现的拷贝,
1.首先会获取source对象的getter()方法,也就是这里的Person对象的getSex()
2.然后获取到Target对象的setter()方法,也就是这里的Student对象的setSex()
3.然后将掉用source对象的getSex()方法作为参数传递给目标对象的setSex(String sex)方法,但是不要忽略了一点源对象的返回值是char类型,但是目标对象的参数是String类型,因此是不会进行拷贝的。这个工具会认为这两个属性并不相同。实际上也确实不相同,因为数据类型不相同,如何进行拷贝呢。因此sex属性拷贝失败,反观name属性,属性名和数据类型都一样,确实也注入成功了。
还有一个很好玩的点是:
如果name的属性名两者并不一样的话,那么还能拷贝成功吗。直接上代码。
这里我修改了Person里面的属性名。而Student的属性名不变。
经过测试发现,其实也是拷贝不成功的。
这就应证了是通过反射技术来查看得到两者其实不是一个同一个变量,具体的流程就是查看源对象的getNAme(),然后推断出属性名是nAme,返回类型是String.紧接着查看目标对象setName(String name)方法,得到属性为name,参数为String ,最终判断两者的属性名并不相同。无法拷贝。
还有一种特殊的情况就是把源对象的name属性改为Name,而目标对象仍然为name,这样也是可以拷贝成功的。因为是通过方法名进行推断的两者的属性名是否相同,而Javabean类的setter和getter默认都是驼峰命名的,因此是可以进行拷贝的,大家也可以试试哦。感谢大家观看,有歧义的地方在请及时指出。