3大对象复制框架性能对比

Apache common-utils的BeanUtils,Spring的BeanUtils,以及cglib的BeanCopier复制对象属性的性能对比。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.cglib.beans.BeanCopier;
import java.lang.reflect.InvocationTargetException;
**
* 测试apache BeanUtils和cglib的BeanCopier的性能对比。
* @author j.tommy
* @date 2016-09-13 15:20.
*/
public class BeanCopyTest {
public static void main(String[] args) {
Teacher t = new Teacher(1,"admin");
Teacher t2 = new Teacher();
testSpringBeanUtils(t);
testCommonUtils(t);
testCgLib(t);
}
public static void testSpringBeanUtils(Teacher teacher) {
Teacher t = new Teacher();
Long start = System.currentTimeMillis();
for (int i=0;i<100*10000;i++) {
org.springframework.beans.BeanUtils.copyProperties(t, teacher);
}
Long end = System.currentTimeMillis();
System.out.println("Spring time spend:" + (end - start));
}
public static void testCommonUtils(Teacher teacher) {
Teacher t = new Teacher();
Long start = System.currentTimeMillis();
for (int i=0;i<100*10000;i++) {
try {
BeanUtils.copyProperties(t,teacher);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
Long end = System.currentTimeMillis();
System.out.println("Common-utils time spend:" + (end - start));
}
public static void testCgLib(Teacher teacher) {
Teacher copy = new Teacher();
BeanCopier bc = BeanCopier.create(Teacher.class,Teacher.class,false);
Long start = System.currentTimeMillis();
for (int i=0;i<100*10000;i++) {
bc.copy(teacher,copy,null);
}
Long end = System.currentTimeMillis();
System.out.println("CGlib time spend:" + (end-start));
}
static class Teacher {
private int id;
private String name;
public Teacher() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher(int id, String name) {
this.id = id;
this.name = name;
}
}
}

可以看出,common-utils的BeanUtils复制对象属性是最差的,最好的是CGLIB,统计结果都是复制100万次属性。
所以,在大量复制对象属性的场合,最好使用cglib的BeanCopier来做。

使用BeanCopier需要注意的事项:
1)目标类的getter方法不能比setter方法多;
这个是cglib的一个bug,它是读取所有的getter方法,然后调用相关的setter方法去注入属性,所以会触发空指针异常。
这个是在使用BeanCopier的create方法时发生的。
bug可以参考:https://sourceforge.net/p/cglib/bugs/32/

2)使用时最好缓存BeanCopier,而不是每次使用的时候创建一个。具体类说就是使用一个静态的变量,而不是一个类成员变量。

Donny wechat
欢迎关注我的个人公众号
打赏,是超越赞的一种表达。
Show comments from Gitment