在日常开发中,经常会遇到需要Bean copy的情况,有好多copy的方法
克隆的分类
- 浅克隆(shallow clone),浅克隆是指拷贝对象时仅仅copy对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
- 深克隆(deep clone),不仅copy对象本身,而且copy对象包含的引用指向的所有对象。
克隆方法
传统的setter方法
手工来setter对象的每个属性,这种方法性能非常高,但是写法不优雅、繁琐
Object.clone()
实现
java.lang.Cloneable
接口
Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。重写(Override)Object的
clone()
方法,并声明为public
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Student implements Cloneable {
String name;
int age;
Student(String name,int age) {
this.name=name;
this.age=age;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}这只是浅克隆,如果需要深克隆的话则重写(Override)Object类的clone()方法,并且在方法内部调用持有对象的clone方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Student implements Cloneable {
String name;
Info info;
Student(String name,Info info) {
this.name=name;
this.info=info;
}
public Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.info = (Info) student.info.clone();
return student;
}
}这样就可以调用
Object.clone()
方法或调用org.apache.commons.lang3.ObjectUtils
的clone()方法来克隆对象了
序列化来实现深克隆
自定义类需要实现Serializable
接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,便可以重建对象
使用第三方工具
常见的第三方工具大概有这几种:
Apache 的 BeanUtils
Apache 的 PropertyUtils
Spring 的 BeanUtils
Cglib 的 BeanCopier
Apache 的 BeanUtils 和 PropertyUtils:
Apache的BeanUtils和PropertyUtils性能非常差,一般都不使用。
这个俩个类都是浅克隆,Apache还提供了 SerializationUtils.clone(T)
,T对象需要实现Serializable
接口,他属于深克隆。
Spring 的 BeanUtils
Spring的BeanUtils的BeanUtils.copyProperties()
方法相比Apache来说性能要好很多。
并且相比Cglib 的 BeanCopier来说,它是静态方法,直接使用即可,非常方便。而BeanCopier不是静态方法,使用前需要使用BeanCopier.create()
来初始化。
Cglib 的 BeanCopier
Cglib 的 BeanCopier相比来说性能是最高的,但是使用前需要通过BeanCopier.create()
来初始化。
1 | BeanCopier beanCopier = BeanCopier.create(srcClass, dstClass, false); |
其实BeanCopier主要花费的时间是调用create()方法,真正执行copy Bean花费的时间较少,所以我们可以进行优化,不是每次执行创建新BeanCopier,将BeanCopier.create()创建的BeanCopier进行缓存
1 |
|
加入缓存后和手工set的性能接近
建议不要使用Apache的工具,如果是偶尔使用为了方便可以使用Spring的BeanUtils,如果是频繁使用时还是推荐使用Cglib 的 BeanCopier