BeanUtils工具效率对比

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

https://blog.csdn.net/dadiyang/article/details/90695300

欢迎关注我的公众号

发表回复

您的电子邮箱地址不会被公开。

粤ICP备17041560号-2