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
