文章《用Spring的BeanUtils前,建议你先了解这几个坑》里面,做者最后获得了这几个结论:java
1.Spring得BeanUtils得CopyProperties方法须要对应得属性有getter和setter方法;
2.若是存在属性彻底相同得内部类,可是不是同一个内部类,即分别属于各自得内部类,则Spring会认为属性不一样,不会Copy;
3.泛型只在编译期起做用,不能依靠泛型来作运行期得限制;
4.最后,Spring和Apache得copy属性得方法源和目的参数得位置正好相反,因此导包和调用得时候须要注意如下。
在这里,咱们今天重点说的是第二点,第一点是由于用反射拿到set和get方法再去拿属性值和设置属性值的,不懂反射的人能够自行百度下。第三和第四点很简单了应该是不须要解释的。测试
首先,我把我本身的测试代码也贴出来:this
@Data
public class TestEntity{
private Integer age;
private String name;
private Inner inner;3d
@Data public static class Inner{ private Integer a; public Inner(Integer a){ this.a = a; } }
}code
@Data
public class TestVO{
private Integer age;
private String name;
private Inner inner;对象
@Data public static class Inner{ private Integer a; public Inner(Integer a){ this.a = a; } }
}blog
public class Main{
public static void main(String args[]){
TestEntity entity = new TestEntity();
entity.setAge(1);
entity.setName("hehe");
entity.setInner(new TestEntity.Inner(1));get
TestVO vo = new TestVO(); BeanUtils.copyProperties(entity,vo); System.out.println(vo.toString()); }
}
以上就是我得三个类,是否是超级简单,好比工做中将entity转vo,就有这种使用场景,运行main方法,测试结果和那个做者得出的第二点的结论是同样的,b对象里面的inner是null!虚拟机
可是这个是为何呢?这个是BUG吗?这个也是我今天要说的重点。it
咱们知道,java给咱们提供了内部类这样的东东,可是java的内部类,它其实只是java的一个语法糖而已(不知道什么是语法糖的请自行百度),那么咱们定义得两个JAVA类里面的Inner的真面目究竟是怎样的呢?
来到编译后的.class文件目录下,咱们能够看到编译后得.class文件:
哈哈,不知道读者到这里是否是能明白些什么了呢?为何通过BeanUtils.CopyProperties(entity,vo)以后,vo里面的inner仍是null,由于TestEntity.java和TestVO.java里面的Inner在编译以后的class名字都不同(表明加载到虚拟机以后的地址不一样),怎么可能拷贝成功呢?
那么问题来了哈,咱们怎样用才能让其拷贝成功呢?我稍微修改了下个人代码以下:
@Data
public class TestVO{
private Integer age;
private String name;
private TestEntity.Inner inner;
}
仅仅是把Inner变为了TestEntity.Inner,删掉了没引用得内部类Inner,Main.java不变,而后运行结果以下:
能够看到,b对象里面的inner被成功拷贝过来。
此时编译后得class文件也由5个变为了4个