如果有两个 Java Bean,有多个相同类型和命名的属性,可以使用 Spring 的 BeanUtils.copyProperties 快速将一个 Java Bean 对象的属性复制到另外一个 Java Bean 对象中。
Java Bean (什么是 Java Bean )定义中要求实现序列化接口,BeanUtils.copyProperties 不强制这一条。只要属性有 getter、setter 方法即可。
BeanUtils 类的全路径是:
org.springframework.beans.BeanUtils
属于 spring-beans 项目, gradle 中引入 spring-beans 即可:
compile group: 'org.springframework', name: 'spring-beans', version: '5.0.6.RELEASE'
也可以只引入 spring-context, spring-beans 是它的一个依赖:
compile group: 'org.springframework', name: 'spring-context', version: '5.0.6.RELEASE'
使用示例
定义 3 个 Java Bean
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Address {
private String city;
public Address() {
}
public Address(String city) {
this.city = city;
}
}
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Student {
private String name;
private int age;
private Address address;
public Student() {
}
public Student(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
}
示例: 从 Person 到 Person
Person person1 = new Person("letian", 18);
System.out.println(person1);
Person person2 = new Person();
BeanUtils.copyProperties(person1, person2);
System.out.println(person2);
运行结果:
Person(name=letian, age=18)
Person(name=letian, age=18)
示例: 从 Person 到 Student
Person person = new Person("letian", 18);
Student student = new Student();
BeanUtils.copyProperties(person, student);
System.out.println(student);
运行结果:
Student(name=letian, age=18, address=null)
Person 比 Student 少了一个 address 属性,所以 Student 的 address 是 null。
示例: 从 Student 到 Person
Student student = new Student("letian", 18, new Address("某城市A"));
Person person = new Person();
BeanUtils.copyProperties(student, person);
System.out.println(person);
运行结果:
Person(name=letian, age=18)
示例: 从 Student 到 Student
上面的示例,其实已经够用了,但我们要注意一下,BeanUtils.copyProperties 是浅复制。
Student stu01 = new Student("letian", 18, new Address("某城市A"));
Student stu02 = new Student();
BeanUtils.copyProperties(stu01, stu02);
System.out.println("stu02: " + stu02);
// 修改 stu01 address 属性的 city 值,会导致 stu02 中对应的值也发生变化
stu01.getAddress().setCity("某城市B");
System.out.println("修改后:");
System.out.println("stu01: " + stu01);
System.out.println("stu02: " + stu02);
运行结果:
stu02: Student(name=letian, age=18, address=Address(city=某城市A))
修改后:
stu01: Student(name=letian, age=18, address=Address(city=某城市B))
stu02: Student(name=letian, age=18, address=Address(city=某城市B))
错误的使用示例
没有 setter、getter 方法的类,使用 BeanUtils.copyProperties 是没有效果的。
@ToString
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Person person1 = new Person("letian", 18);
System.out.println(person1);
Person person2 = new Person();
BeanUtils.copyProperties(person1, person2);
System.out.println(person2);
运行结果:
Person(name=letian, age=18)
Person(name=null, age=0)
可以看到 person2 的name 和 age 都是默认值,复制没有效果。
类似的,下面的这些用法也是错误的:
// 错误用法
String source = "你好";
String target = "Hi";
BeanUtils.copyProperties(source, target);
System.out.println(target); // Hi
// 错误用法
List<String> source = Arrays.asList("A", "B");
List<String> target = Arrays.asList();
BeanUtils.copyProperties(source, target);
System.out.println(target.size()); // 0