关于BeanCopy
在项目中发现在对一个对象进行拷贝赋值的时候都在使用BeanFactory
类的beanCopy()
方法,该方法可方便地复制属性值,节省了大量的get、set操作,其实现如下所示:
public class BeanFactory {
public static <T> T beanCopy(T t, Object orig){
try {
BeanUtils.copyProperties(t,orig);
}catch (Exception e){
throw new RuntimeException("复制对象属性出错",e);
}
return t;
}
}
而copyProperties()
方法在apache
提供的一个工具类BeanUtils
中定义。
但是,IDE提示说该方法效率低下,推荐使用其他的方法,提示如下:
避免用
Apache Beanutils
进行属性的copy 说明:Apache BeanUtils
性能较差 ,可以使用其他方案比如Spring BeanUtils
,Cglib BeanCopier
TestObject a = new TestObject(); TestObject b = new TestObject(); a.setX(b.getX()); a.setY(b.getY());
为此,分别使用Apache BeanUtils
,Spring BeanUtils
,cglib BeanCopier
,以及JSON
的方式进行beancopy
操作,对其效率作对比,其拷贝方式如下:
public class BeanFactory {
//Apache copy
public static <T> T beanCopy(T t, Object orig){
try {
BeanUtils.copyProperties(t,orig);
}catch (Exception e){
throw new RuntimeException("Apache BeanUtils复制对象属性出错",e);
}
return t;
}
//Spring copy
public static <T> T copybean(T t, Object orig){
try{
org.springframework.beans.BeanUtils.copyProperties(orig,t);
}catch (Exception e){
throw new RuntimeException("Spring BeanUtils复制对象属性出错",e);
}
return t;
}
//cglib copy
public static <T> T cglibcopy(T t,Object orig,Class clazz){
try {
final BeanCopier beanCopier = BeanCopier.create(clazz,clazz,false);
beanCopier.copy(orig,t,null);
}catch (Exception e){
throw new RuntimeException("cglib BeanCopier复制对象属性出错",e);
}
return t;
}
//json copy
public static Object jsonCopy(Object orgi,Class clazz){
try{
String json = JSON.toJSONString(orgi);
return JSON.parseObject(json,clazz);
}catch (Exception e){
throw new RuntimeException("json parse复制对象属性出错",e);
}
}
}
首先进行10000次拷贝测试,其结果如下:
Apache | Spring | cglib | JSON | |
---|---|---|---|---|
1 | 1663 | 271 | 159 | 244 |
2 | 1696 | 130 | 186 | 243 |
3 | 1798 | 136 | 186 | 138 |
Avg | 1719 | 179 | 177 | 208.3 |
然后进行100次拷贝测试:
Apache | Spring | cglib | JSON | |
---|---|---|---|---|
1 | 227 | 77 | 84 | 137 |
2 | 270 | 83 | 83 | 142 |
3 | 257 | 99 | 84 | 150 |
Avg | 251.3 | 86.3 | 83.6 | 143 |
最后是10次拷贝测试:
Apache | Spring | cglib | JSON | |
---|---|---|---|---|
1 | 186 | 69 | 81 | 137 |
2 | 184 | 70 | 86 | 131 |
3 | 183 | 71 | 84 | 119 |
Avg | 184.3 | 70 | 83.6 | 129 |
可以看出,不论拷贝次数的多少,Apache
的效率总是最差的,而Spring
与cglib
(不使用缓存)效率相当,JSON
的效率比Apache
稍好,但是与Spring
和cglib
还有一定的差距。整体而言,效率由高到低的排序为:
在使用cglib
进行测试的的时候,遇到java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method visit.(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
的报错信息,其原因是asm
高版本的jar包与cglib:2.2
的jar包存在冲突,将asm
版本降级到3.x可解决该问题。
结合项目中asm
高版本的jar包使用较多的实际情况,建议以后使用 Spring BeanUtils 方法作为BeanCopy的实现方法,由此提高效率。