Spring的BeanUtils

简介: 本文通过实例分析了Spring的BeanUtils.copyProperties方法在属性拷贝中的“坑”。重点探讨了当源对象与目标对象包含相同名称但不同定义的内部类属性时,属性无法正确拷贝的原因。作者指出,这是由于Java内部类编译后生成不同的类名,导致Spring认为属性类型不匹配而未进行拷贝。通过修改代码使内部类一致后,问题得以解决。文章强调理解底层原理的重要性,帮助开发者避免类似误区。

在这篇文章里面,作者最后得到了这几个结论:

  1. Spring得BeanUtils得CopyProperties方法需要对应得属性有getter和setter方法;
  2. 如果存在属性完全相同得内部类,但是不是同一个内部类,即分别属于各自得内部类,则Spring会认为属性不同,不会Copy;
  3. 泛型只在编译期起作用,不能依靠泛型来做运行期得限制;
  4. 最后,Spring和Apache得copy属性得方法源和目的参数得位置正好相反,所以导包和调用得时候需要注意以下。

在这里,我们今天重点说的是第二点,第一点是因为用反射拿到set和get方法再去拿属性值和设置属性值的,不懂反射的人可以自行百度下。第三和第四点很简单了应该是不需要解释的。

验证

首先,我把我自己的测试代码贴出来:

体验AI代码助手

代码解读

复制代码

@Data
public class TestEntity{
    private Integer age;
    private String name;
    private Inner inner;
    
    @Data
    public static class Inner{
        private Integer a;
        public Inner(Integer a){
            this.a = a;
        }
    }
    
}

体验AI代码助手

代码解读

复制代码

@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;
        }
    }
}

体验AI代码助手

代码解读

复制代码


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));

        TestVO vo = new TestVO();
        BeanUtils.copyProperties(entity,vo);
        System.out.println(vo.toString());
        
    }
}

以上就是我得三个类,是不是超级简单,比如工作中将entity转vo,就有这种使用场景,运行main方法,测试结果如下

果然,和那个作者得出的第二点的结论是一样的,b对象里面的inner是null!

但是这个是为什么呢?这个是BUG吗?这个也是我今天要说的重点。

我们知道,java给我们提供了内部类这样的东东,但是java的内部类,它其实只是java的一个语法糖而已(不知道什么是语法糖的请自行百度),那么我们定义得两个JAVA类里面的Inner的真面目到底是怎样的呢?

来到编译后的.class文件目录下,我们可以看到编译后得.class文件:

哈哈,不知道读者到这里是不是能明白些什么了呢?为什么经过BeanUtils.CopyProperties(entity,vo)之后,vo里面的inner还是null,因为TestEntity.java和TestVO.java里面的Inner在编译之后的class名字都不一样(代表加载到虚拟机之后的地址不同),怎么可能拷贝成功呢?

那么问题来了哈,我们怎样用才能让其拷贝成功呢?我稍微修改了下我的代码如下:

体验AI代码助手

代码解读

复制代码

@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个

总结

所以说,其实人家Spring的BeanUtils.CopyProperties并没有这种坑,坑的只是我们自己没有掌握本质导致自己坑了自己而已。相信能看这种文章的小伙伴都是想搞懂spring或者是想提高自己开发能力的,我们在看一件事的时候,要看清楚它的本质是什么,最少工作原理是要搞明白的,尤其是我们开发用到的东西,否则怎么去面对一个很复杂的软件呢?


转载来源:https://juejin.cn/post/6844904194743205901

相关文章
|
Java Spring
解决Spring工具类BeanUtils copyProperties方法复制null的问题
解决Spring工具类BeanUtils copyProperties方法复制null的问题
1201 0
|
Java Apache Spring
Spring BeanUtils与Apache BeanUtils提供基本属性复制,适用于简单需求
【5月更文挑战第4天】Spring BeanUtils与Apache BeanUtils提供基本属性复制,适用于简单需求;Cglib BeanCopier用于转换为Cglib代理对象;Apache PropertyUtils处理属性操作;Dozer支持复杂对象映射。选择工具取决于具体需求,如需精细控制或对象映射,推荐Dozer或Apache PropertyUtils。Apache BeanUtils可能因潜在的封装性破坏被禁用。
140 3
|
Java Apache Spring
Spring BeanUtils 2、Cglib BeanCopier 3、Apache BeanUtils 4、Apache PropertyUtils 5、Dozer 那么,我们到底应该选择哪种工具类更加合适呢?为什么Java开发手册中提到禁止使用Apache BeanUtils呢
Spring BeanUtils 2、Cglib BeanCopier 3、Apache BeanUtils 4、Apache PropertyUtils 5、Dozer 那么,我们到底应该选择哪种工具类更加合适呢?为什么Java开发手册中提到禁止使用Apache BeanUtils呢
185 0
|
Java Apache 数据库
Spring的BeanUtils的copyProperties方法
项目中遇到的情况是: 文件解析完之后将文件放在一个pojo里面
219 0
|
Java Apache Spring
Spring的BeanUtils有坑?可能是你用错了!
Spring的BeanUtils有坑?可能是你用错了!
231 0
|
JSON Java Apache
最近,我在Spring的BeanUtils踩了不少坑~
最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。根据注释,对方的SDK中写好的Request类有一个无法序列化的bug,所以这边重新写了一个Request类,
|
JSON Java Apache
用Spring的BeanUtils前,建议你先了解这几个坑!
背景 最近项目中在和第三方进行联调一个接口,我们这边发送http请求给对方,然后接收对方的回应,代码都是老代码。根据注释,对方的SDK中写好的Request类有一个无法序列化的bug,所以这边重新写了一个Request类,基本属性都是相同的,但是重点是有一个属性是静态内部类,还有两个是list属性,类似于下面这样: private List<Order> orders; private AddRequest.Ticket ticket; private List<Payment> payments; 复制代码 AddRequest就是我们自己重写的请求类,他们SDK中的请求类是MixAddR
193 0
|
3月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
786 0
|
14天前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
137 3