java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring BeanUtils.copyProperties属性复制避坑

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

作者:黄鸡黄鸡

这篇文章主要介绍了Spring的BeanUtils.copyProperties属性复制避坑指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Spring的BeanUtils.copyProperties属性复制避坑

项目场景:

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

问题描述

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

话不多说直接上demo代码

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 +
           '}';
   }
}
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 +
            '}';
    }
}
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是浅拷贝。

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

// 浅拷贝
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的拷贝是浅拷贝,对基本数据类型进行值传递的属性复制,改变原基本数据类型的值不会改变被复制的属性结果;

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

您可能感兴趣的文章:
阅读全文