BeanUtils.copyProperties在spring包和apache包中使用情况

发布于:2023-01-22 ⋅ 阅读:(14) ⋅ 点赞:(0) ⋅ 评论:(0)

 <!-- apache中BeanUtils的依赖 org.apache.commons.beanutils.BeanUtils.copyProperties -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>
   <!-- 创建springboot项目 org.springframework.beans.BeanUtils -->

说明:BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度

spring包中实践

BeanUtils.copyProperties()作用

官方解释:Copy the property values of the given source bean into the target bean
将给定源bean的属性值复制到目标bean中
A.java

package com.geekmice.onetomany.copyproperties;

import java.util.Date;

public class A {
    private String userName;
    private Integer age;
    private Date bornDate;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBornDate() {
        return bornDate;
    }

    public void setBornDate(Date bornDate) {
        this.bornDate = bornDate;
    }

    @Override
    public String toString() {
        return "Student{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                ", bornDate=" + bornDate +
                '}';
    }
}

B.java

package com.geekmice.onetomany.copyproperties;

import java.util.Date;

public class B {
    private String userName;
    private Integer age;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

单元测试

    /**
     * 拷贝前后同一类对象,也就是拷贝前后字段是一样
     */
    @Test
    void t1() {
        A student = new A();
        student.setAge(18);
        student.setBornDate(new Date());
        student.setUserName("小王");
        A tempStudent = new A();
        System.out.println("源对象:" + student);
        BeanUtils.copyProperties(student, tempStudent);
        System.out.println("目标对象:" + tempStudent);
    }
 // 源对象:Student{userName='小王', age=18, bornDate=Wed Aug 10 20:44:59 CST 2022}
 // 目标对象:Student{userName='小王', age=18, bornDate=Wed Aug 10 20:44:59 CST 2022}

在这里插入图片描述

 /**
     * 拷贝前后不是一类对象,也就是拷贝前后字段不太一样
     * 只有相同的字段才会拷贝过来
     */
    @Test
    void t2() {
        B b1 = new B();
        b1.setAge(99);
        b1.setUserName("小红");
        A a = new A();
        System.out.println("源对象:" + b1);
        BeanUtils.copyProperties(b1, a);
        System.out.println("目标对象:" + a);
        A a1 = new A();
        a1.setUserName("小李");
        a1.setAge(18);
        a1.setBornDate(new Date());
        B b2 = new B();
        b2.setAge(188);
        b2.setUserName("小李子");
        System.out.println("源对象:"+a1);
        BeanUtils.copyProperties(a1,b1);
        System.out.println("目标对象:"+b1);
    }
// 源对象:B{userName='小红', age=99}
// 目标对象:Student{userName='小红', age=99, bornDate=null}
// 源对象:Student{userName='小李', age=18, bornDate=Wed Aug 10 20:45:37 CST 2022}
// 目标对象:B{userName='小李', age=18}


在这里插入图片描述

apache包中实践

  /**
     * 1、BeanUtils.copyProperties(a,b) 这个方法源和目标参数相反,a是目标对象,b是源对象
     * 1.1 都是同一类的话,拷贝之后
     *
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @Test
    void t3() throws InvocationTargetException, IllegalAccessException {
        // 1.1
        System.out.println("1.1");
        A b1 = new A();
        b1.setAge(99);
        b1.setUserName("小红");
        A a = new A();
        a.setBornDate(new Date());
        a.setAge(18);
        a.setUserName("小红1");
        System.out.println("源对象:" + a);
        org.apache.commons.beanutils.BeanUtils.copyProperties(b1, a);
        System.out.println("目标对象:" + b1);
        System.out.println("1.2");
        // 1.2
        A a2 = new A();
        a2.setAge(99);
        a2.setUserName("小红");
        a2.setBornDate(new Date());
        B b = new B();
        b.setUserName("小红1");
        b.setAge(98);
        System.out.println("源对象:" + b);
        org.apache.commons.beanutils.BeanUtils.copyProperties(a2, b);
        System.out.println("目标对象:" + a2);
        // 1.3
        System.out.println("1.3");
        A a3 = new A();
        a3.setAge(99);
        a3.setUserName("小红");
        a3.setBornDate(new Date());
        B b2 = new B();
        b2.setUserName("小红1");
        b2.setAge(98);
        System.out.println("源对象:" + b2);
        org.apache.commons.beanutils.BeanUtils.copyProperties(b2, a3);
        System.out.println("目标对象:" + a3);
    }
    // 1.1
    // 源对象:Student{userName='小红1', age=18, bornDate=Wed Aug 10 20:46:41 CST 2022}
    // 目标对象:Student{userName='小红1', age=18, bornDate=Wed Aug 10 20:46:41 CST 2022}
    // 1.2
    // 源对象:B{userName='小红1', age=98}
    // 目标对象:Student{userName='小红1', age=98, bornDate=Wed Aug 10 20:46:41 CST 2022}
    // 1.3
    // 源对象:B{userName='小红1', age=98}
    // 目标对象:Student{userName='小红', age=99, bornDate=Wed Aug 10 20:46:41 CST 2022}
    //

在这里插入图片描述

两种情况对比

org.apache.commons.beanutils.BeanUtils.copyProperties org.springframework.beans.BeanUtils
方法 public static void copyProperties(Object dest, Object orig) public static void copyProperties(Object source, Object target)
参数说明 dest:目标对象 orig:源对象 source:源对象 target:目标对象

深拷贝和浅拷贝

浅拷贝

 @Test
    void t5() throws CloneNotSupportedException, ParseException {
        C c = new C();
        c.setAge(11);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmdd");
        Date parse = simpleDateFormat.parse("20220810");
        c.setBornDate(parse);
        c.setUserName(UUID.randomUUID().toString().replace("-",""));
        A a = new A();
        a.setUserName("小红前");
        c.setA(a);
        C c1 = (C) c.clone();
        System.out.println("+++++++++++++拷贝后+++++++++++++");
        System.out.println(c1.getAge());
        System.out.println(c1.getUserName());
        System.out.println(c1.getBornDate());
        System.out.println(c1.getA().getUserName());
        System.out.println("+++++++++++++修改引用数据后+++++++++++++++++++++");
        a.setUserName("小红后");
        System.out.println(c1.getA().getUserName());
        System.out.println(c.getA().getUserName());
        // 11
        // 4806df9d3068435fb64c8bcf0576de70
        // Mon Jan 10 00:08:00 CST 2022
        // 小红前
        // +++++++++++++修改引用数据后+++++++++++++++++++++
        // 小红前
        // 小红前
        //

    }

结论分析: 两个引用c和c1指向不同的两个对象,但是两个引用c和c1中的两个a引用指向的是同一个对象,所以说明是浅拷贝。
在这里插入图片描述
深拷贝
深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

    @Test
    void t6() throws CloneNotSupportedException, ParseException {
        C c = new C();
        c.setAge(11);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyymmdd");
        Date parse = simpleDateFormat.parse("20220810");
        c.setBornDate(parse);
        c.setUserName(UUID.randomUUID().toString().replace("-",""));
        A a = new A();
        a.setUserName("小红前");
        c.setA(a);
        C c1 = (C) c.clone();
        System.out.println("+++++++++++++拷贝后+++++++++++++");
        System.out.println(c1.getAge());
        System.out.println(c1.getUserName());
        System.out.println(c1.getBornDate());
        System.out.println(c1.getA().getUserName());
        System.out.println("+++++++++++++修改引用数据后+++++++++++++++++++++");
        a.setUserName("小红后");
        System.out.println(c1.getA().getUserName());
        System.out.println(c.getA().getUserName());
    }
     //         11
    // 4806df9d3068435fb64c8bcf0576de70
    // Mon Jan 10 00:08:00 CST 2022
    // 小红前
    // +++++++++++++修改引用数据后+++++++++++++++++++++
    // 小红前
    // 小红后
    //

结果分析:两个引用c和c1指向不同对象,两个引用c和c1中两个A对象指向的是两个对象,但是对A对象的修改只能影响c对象,故而深拷贝。
在这里插入图片描述

Java深入理解深拷贝和浅拷贝区别

BeanUtils工具类中的copyProperties方法的作用(两种)