BeanUtils的使用
业务系统中经常需要两个对象进行属性的拷贝,不能否认逐个的对象拷贝是最快速最安全的做法,但是当数据对象的属性字段数量超过程序员的容忍的程度,代码因此变得臃肿不堪,使用一些方便的对象拷贝工具类将是很好的选择。
常用的BeanUtils
1、Apache的两个版本:(反射机制)
org.apache.commons.beanutils.PropertyUtils.copyProperties(Object dest, Object orig)
org.apache.commons.beanutils.BeanUtils.copyProperties(Object dest, Object orig)
2、Spring版本:(反射机制)
org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable, String[] ignoreProperties)
3、 cglib版本:(使用动态代理,效率高)
net.sf.cglib.beans.BeanCopier.copy(Object paramObject1, Object paramObject2, Converter paramConverter)
测试用例
Pom 依赖
Apache Commons BeanUtils
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
cglib依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
Spring依赖网上找就行,,,
Spring包含了cglib的依赖,如果引入了spring可以直接使用cglib,org.springframework.cglib
实体类
public class People implements Serializable {
String name = "Jam";
double age = 12.2;
Date birDate = new Date();
}
测试用例
public class BeanUtilsTest {
People p = new People();
People p2 = new People();
int count = 1000000;
@Before
public void before () {
p.setName("Jam111");
p.setAge(66.6);
}
@Test
public void testComProperties () throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
for (int i = 0; i < count; i++) {
PropertyUtils.copyProperties(p2, p);
}
}
@Test
public void testCommons() throws InvocationTargetException, IllegalAccessException {
for (int i = 0; i < count; i++) {
org.apache.commons.beanutils.BeanUtils.copyProperties( p2, p);
}
}
@Test
public void testSpring () {
for (int i = 0; i < count; i++) {
BeanUtils.copyProperties(p, p2);
}
}
@Test
public void testCglib () {
for (int i = 0; i < count; i++) {
BeanCopier copier = BeanCopier.create(People.class, People.class, false);
copier.copy(p, p2, null);
}
}
}
测试结果
1百万次对象复制,假设cglib为基线,那么其他工具的耗时比例
工具 | 耗时 | 比例 |
---|---|---|
commons PropertyUtils | 1s224ms | 12.4 |
commons BeanUtils | 2s983ms | 30.44 |
Spring BeanUtils | 162ms | 1.65 |
cglib BeanCopier | 98ms | 1 |
从上面的数据可以看出apache的BeanUtils效率是非常低下的,而且使用测试的例子字段比较少,如果增加字段,这个差距会更加的明显,例如我增加了6个字段之后进行测试,cglib的时间只是增加了很少,而apache BeanUtils的时间翻了一倍多,到了7s。而且测试的时候cglib每次都初始化BeanCopier,如果不初始化,那么cglib工具还可以快10倍,和直接getset方法的耗时很接近。
apache的bean工具比较慢主要是处理的时候有大量的类型比较和转换,cglib直接操作字节码,速度最快。
结论
安装了阿里的代码检查工具,其实它就会提示让你不要使用apache的BeanUtils。
如果需要使用BeanUtils,那么尽量使用cglib或者Spring提供的工具
注意
1、参数顺序,apache工具的例子是要(target, source), 顺序是相反的,其他工具则是(source, target),如果想要更换工具,注意参数也要改变。
2、低版本的apacheBeanUtils工具在转换util.Date时可能会出错,需要自定义转换器,但是也会引入类型转换问题。
3、Spring 的拷贝,需要保证拷贝与被拷贝的对象都拥有对应属性的get 和set 方法
ref
https://blog.csdn.net/express_wind/article/details/7326350