Spring的BeanUtils.copyProperties属性复制避坑指南

 更新时间:2024年08月12日 17:01:19   作者:黄鸡黄鸡  
这篇文章主要介绍了Spring的BeanUtils.copyProperties属性复制避坑指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Spring的BeanUtils.copyProperties属性复制避坑

项目场景:

在分布式项目中,我进行我们的项目对外接口整合时,需要自己再定义对外的类来传参,就避免不了用BeanUtils.copyProperties工具来进行属性赋值。

问题描述

关于BeanUtils.copyProperties的属性复制规则

话不多说直接上demo代码

  • 类A
class A {
    int a;
    List<Integer> list = new ArrayList<>();
    List<B> bList = new ArrayList<>();
    B b;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

    public List<Integer> getList() {
        return list;
    }

    public void setList(List<Integer> list) {
        this.list = list;
    }

    public List<B> getbList() {
        return bList;
    }

    public void setbList(List<B> bList) {
        this.bList = bList;
    }

   @Override
   public String toString() {
       return "A{" +
           "a=" + a +
           ", list=" + list +
           ", bList=" + bList +
           ", b=" + b +
           '}';
   }
}
  • 类A1
class A1 {
    int a;
    List<Integer> list = new ArrayList<>();
    List<B> bList = new ArrayList<>();
    B b;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

    public List<Integer> getList() {
        return list;
    }

    public void setList(List<Integer> list) {
        this.list = list;
    }

    public List<B> getbList() {
        return bList;
    }

    public void setbList(List<B> bList) {
        this.bList = bList;
    }

    @Override
    public String toString() {
        return "A1{" +
            "a=" + a +
            ", list=" + list +
            ", bList=" + bList +
            ", b=" + b +
            '}';
    }
}
  • 类B
class B {
	String b;

    public String getB() {
      return b;
    }

	public void setB(String b) {
	  this.b = b;
	}

	@Override
	public String toString() {
	    return "B{" +
	        "b='" + b + '\'' +
	        '}';
	}
	
	public B() {
    }

    public B(String b) {
        this.b = b;
    }
}

测试main方法1

public static void main(String[] args) {
    A a = new A();

    B b = new B();
    b.setB("bbb");

    List<Integer> list = new ArrayList<>();
    list.add(100);
    list.add(200);

    List<B> bList = new ArrayList<>();
    bList.add(new B("dd"));
    bList.add(new B("cc"));
    bList.add(new B("ee"));

    a.setA(1);
    a.setB(b);
    a.setList(list);
    a.setbList(bList);

    A1 a1 = new A1();

    BeanUtils.copyProperties(a, a1);

    System.out.println(a1);
}

结果::A1{a=1, list=[100, 200], bList=[B{b=‘dd’}, B{b=‘cc’}, B{b=‘ee’}], b=B{b=‘bbb’}}

测试main方法2

public static void main(String[] args) {
   A a = new A();

    B b = new B();
    b.setB("bbb");

    List<Integer> list = new ArrayList<>();
    list.add(100);
    list.add(200);

    List<B> bList = new ArrayList<>();
    bList.add(new B("dd"));
    bList.add(new B("cc"));
    bList.add(new B("ee"));

    a.setA(1);
    a.setB(b);
    a.setList(list);
    a.setbList(bList);

    A1 a1 = new A1();

    BeanUtils.copyProperties(a, a1);

    b.setB("aaa");

    a.setA(2);

    list.clear();
    list.add(666);
    list.add(777);

    bList.clear();
    bList.add(new B("abc"));

    System.out.println(a1);
}

结果:A1{a=1, list=[666, 777], bList=[B{b=‘abc’}], b=B{b=‘aaa’}}

结果分析

从以上的例子和结果来看,BeanUtils.copyProperties是浅拷贝。

  • main方法1: 当A和A1中的属性名称相同时,使用BeanUtils.copyProperties会将所有属性进行复制。从结果上来看,不管是基本数据类型int a,还是剩余的三个引用数据类型,List<Integer> listList<B> bListB b,都进行了复制。
  • main方法2 :第二个main方法在第一个的基础上对要复制的A的属性进行了修改,从结果上发现,A1的属性中基本数据类型int a的值并没有因为修改而改变,但引用数据类型List<Integer> listList<B> bListB b的值会因为改变了A的属性而改变。

附带两种对象属性复制的方法

// 浅拷贝
a1 = JSONObject.parseObject(JSONObject.toJSONString(a), A1.class)

// 深拷贝,其中SerializerFeature.DisableCircularReferenceDetect是为了解决JSON的$ref 引用
a1 = JSONObject.parseObject(JSONObject.toJSONString(a, SerializerFeature.DisableCircularReferenceDetect), A1.class);

// 深拷贝
ObjectMapper objectMapper = new ObjectMapper();
a1 = objectMapper.readValue(JSONObject.toJSONString(a, SerializerFeature.DisableCircularReferenceDetect), A1.class);

结论

BeanUtils.copyProperties的拷贝是浅拷贝,对基本数据类型进行值传递的属性复制,改变原基本数据类型的值不会改变被复制的属性结果;

对引用数据类型进行引用传递的属性复制,只是复制了一个内存地址过去,指向的还是同一个对象,并没有新建对象,改变原对象的值,被复制的属性的值也会随着变化。

相关文章

  • jdk8 FunctionalInterface注解源码解读

    jdk8 FunctionalInterface注解源码解读

    这篇文章主要介绍了jdk8 FunctionalInterface注解源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • SpringFramework应用接入Apollo配置中心过程解析

    SpringFramework应用接入Apollo配置中心过程解析

    这篇文章主要介绍了SpringFramework应用接入Apollo配置中心过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • 使用springboot整合RateLimiter限流过程

    使用springboot整合RateLimiter限流过程

    这篇文章主要介绍了使用springboot整合RateLimiter限流过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • java file.renameTo返回false的原因及解决方案

    java file.renameTo返回false的原因及解决方案

    这篇文章主要介绍了java file.renameTo返回false的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java删除文件、目录及目录下所有文件的方法实例

    Java删除文件、目录及目录下所有文件的方法实例

    这篇文章主要给大家介绍了关于利用Java删除文件、目录及目录下所有文件的方法,文中给出了详细的示例代码与注解,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • 如何在Java中使用WebSocket协议

    如何在Java中使用WebSocket协议

    WebSocket是一种基于 TCP 协议的全双工通信协议,可以在浏览器和服务器之间建立实时、双向的数据通信,下面这篇文章主要给大家介绍了关于如何在Java中使用WebSocket协议的相关资料,需要的朋友可以参考下
    2024-02-02
  • java如何在项目中实现excel导入导出功能

    java如何在项目中实现excel导入导出功能

    这篇文章主要介绍了java如何在项目中实现excel导入导出功能的相关资料,EasyExcel是一个基于Apache POI开发的开源Java库,用于简化Excel文件的读写操作,文中将用法介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • SpringBoot中的@Conditional 注解的使用

    SpringBoot中的@Conditional 注解的使用

    @Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件的才给容器注册Bean,本文主要介绍了SpringBoot中的@Conditional 注解的使用
    2024-01-01
  • SpringBoot如何根据用户系统时区动态展示时间

    SpringBoot如何根据用户系统时区动态展示时间

    这篇文章主要介绍了SpringBoot如何根据用户系统时区动态展示时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • 23种设计模式(19)java责任链模式

    23种设计模式(19)java责任链模式

    这篇文章主要为大家详细介绍了23种设计模式之java责任链模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01

最新评论