最近项目中在对原有项目的spring版本进行升级(Spring boot 2.1 升级至2.7.*)。因为copyProperties的新变动导致踩了一坑,在此和大家分享。
相关链接:github issue
- Spring 5.3前copyProperties的实现:
将给定源 bean 的属性值复制到目标 bean。
注意:源类和目标类不必匹配,甚至不必相互派生,只要属性匹配即可。源bean暴露但目标 bean未暴露的任何bean 属性都将被静默忽略。
这只是一种方便的方法。对于更复杂的传输需求,请考虑使用完整的 BeanWrapper。
- Spring 5.3后copyProperties的实现:
将给定源 bean 的属性值复制到目标 bean。
注意:源类和目标类不必匹配,甚至不必相互派生,只要属性匹配即可。源bean暴露但目标 bean未暴露的任何bean 属性都将被静默忽略。
这只是一种方便的方法。对于更复杂的传输需求,请考虑使用完整的 BeanWrapper。
从 Spring Framework 5.3 开始,**此方法在匹配源对象和目标对象中的属性时遵循泛型类型信息**。
下表提供了一组可复制的源和目标属性类型以及无法复制的源和目标属性类型的非详尽示例。
| source property type | target property type | copy supported |
|---|---|---|
| Integer | Integer | yes |
| Integer | Number | yes |
| List<Integer> | List<Integer> | yes |
| List<?> | List<?> | yes |
| List<Integer> | List<?> | yes |
| List<Integer> | List<? extends Number> | yes |
| String | Integer | no |
| Number | Integer | no |
| List<Integer> | List<Long> | no |
| List<Integer> | List<Number> | no |
List<DataModel> -> List<DataModelVo>
package cn.goofwoof.test;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import java.util.List;
public class Test {
public static void main(String[] args) {
ModelB modelB = new ModelB();
modelB.setId(0);
modelB.setName("ModelB");
DataModel dataModel = new DataModel();
dataModel.setId(1);
dataModel.setName("DataModel");
dataModel.setModelBs(List.of(modelB));
DataModelVo dataModelVo = new DataModelVo();
BeanUtils.copyProperties(dataModel,dataModelVo);
}
@Data
static class DataModel {
private Integer id;
private Integer ids;
private String name;
private List<ModelB> modelBs;
}
@Data
static class DataModelVo {
private Integer id;
private Integer ids;
private String name;
private List<ModelBVo> modelBs;
}
@Data
static class ModelB {
private Integer id;
private String name;
}
@Data
static class ModelBVo {
private Integer id;
private String name;
}
}
-
Spring 5.3前
-
Spring 5.3后
从结果上看,对于类型不一致的情况需要慎重考虑,尤其在版本迁移过程中。