The pit of Spring's BeanUtils.copyProperties

1. Problem background

When 源对象copying 目标对象, the attributes inherited from the parent class in the target object were not successfully copied.

2. Spring’s BeanUtils.copyProperties method

When using Spring's BeanUtils.copyPropertiesmethod to copy attributes, only the attributes defined in the source object will be copied, but the attributes inherited from the parent class in the target object will not be copied . Because BeanUtils.copyProperties()the method is implemented based on Java reflection, it can only access properties in the source object and cannot access properties inherited from the parent class in the target object.

If you need to copy attributes from the source object to the target object, including attributes inherited from the parent class in the target object, you can use other Java object mapping tools, such as Hutool's BeanUtil, Apache Commons BeanUtils and Dozer. These tools can be configured to decide whether to copy properties inherited from the parent class.

3. demo

BeanUtil.copyProperties()The following is a sample code for attribute copying using the method in Hutool :

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;

import java.util.*;

public class Example {
    
    
    public static void main(String[] args) {
    
    
        // 创建一个子类对象
        Child source = new Child();
        source.setPublicField("public field");
        source.setProtectedField("protected field");
        source.setPrivateField("private field");
        source.setDateField(DateUtil.parse("2023-05-22"));
        source.setStringList(CollUtil.newArrayList("a", "b", "c"));
        source.setStringMap(new HashMap<String, String>() {
    
    {
    
    
            put("key1", "value1");
            put("key2", "value2");
        }});

        // 创建一个父类对象
        Parent target = new Parent();

        // 将子类对象的属性拷贝到父类对象中
        BeanUtil.copyProperties(source, target);

        // 输出父类对象中的属性
        System.out.println("publicField: " + target.getPublicField());
        System.out.println("protectedField: " + target.getProtectedField());
        System.println("privateField: " + target.getPrivateField());
        System.out.println("dateField: " + target.getDateField());
        System.out.println("stringList: " + target.getStringList());
        System.out.println("stringMap: " + target.getStringMap());
    }
}

// 父类
class Parent {
    
    
    private String privateField;
    private Date dateField;
    private List<String> stringList;
    private Map<String, String> stringMap;

    public String getPrivateField() {
    
    
        return privateField;
    }

    public void setPrivateField(String privateField) {
    
    
        this.privateField = privateField;
    }

    public Date getDateField() {
    
    
        return dateField;
    }

    public void setDateField(Date dateField) {
    
    
        this.dateField = dateField;
    }

    public List<String> getStringList() {
    
    
        return stringList;
    }

    public void setStringList(List<String> stringList) {
    
    
        this.stringList = stringList;
    }

    public Map<String, String> getStringMap() {
    
    
        return stringMap;
    }

    public void setStringMap(Map<String, String> stringMap) {
    
    
        this.stringMap = stringMap;
    }
}

// 子类
class Child extends Parent {
    
    
    public String publicField;
    protected String protectedField;

    public String getPublicField() {
    
    
        return publicField;
    }

    public void setPublicField(String publicField) {
    
    
        this.publicfield = publicField;
    }

    public String getProtectedField() {
    
    
        return protectedField;
    }

    public void setProtectedField(String protectedField) {
    
    
        this.protectedField = protectedField;
    }

    private String privateField;

    public String getPrivateField() {
    
    
        return privateField;
    }

    public void setPrivateField(String privateField) {
    
    
        this.privateField = privateField;
    }
}

The output is:

publicField: public field
protectedField: protected field
privateField: private field
dateField: Mon May 22 00:00:00 CST 2023
stringList: [a, b, c]
stringMap: {key1=value1, key2=value2}

4. Supplement (the difference between Spring’s BeanUtils.copyProperties and hutool’s BeanUtil.copyProperties)

Both Spring's BeanUtils.copyProperties()and Hutool's BeanUtil.copyProperties()are tool methods for object property copying, but they have some differences in implementation details and usage:

1. The underlying implementation is different

Spring's BeanUtils.copyProperties()method is implemented based on Java reflection, which can copy properties in the source object to the target object, and supports type conversion and custom converters.

The method in Hutool BeanUtil.copyProperties()is implemented based on ASM bytecode operations. It can not only copy attributes in the source object to the target object, but also supports custom mapping rules, field filtering and type conversion.

2. Use it differently

Spring's BeanUtils.copyProperties()method is used as follows:

BeanUtils.copyProperties(source, target);

where sourceis the source object and targetis the target object.

BeanUtil.copyProperties()The method in Hutool is used as follows:

BeanUtil.copyProperties(source, target, ignoreNullValue);

Among them, sourceis the source object, targetis the target object, and ignoreNullValueis a Boolean value indicating whether to ignore the null attributes in the source object. If ignoreNullValueit is true, properties with null values ​​in the source object will be ignored and will not be copied to the target object; if it ignoreNullValueis false, properties with null values ​​in the source object will be copied to the target object.

3. Supported types are different

Spring's BeanUtils.copyProperties()methods support a wide range of types, including Java basic types, strings, dates, collections, arrays, etc.

The methods in Hutool BeanUtil.copyProperties()also support a wide range of types, including Java basic types, strings, dates, collections, arrays, etc., but it also supports some other types, such as enumerations, Maps, JSONObject, etc.

Guess you like

Origin blog.csdn.net/zhoqua697/article/details/130808454