Apache、Spring、Cglib的beancopy效率对比

关于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 BeanUtilsSpring BeanUtilscglib 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的效率总是最差的,而Springcglib(不使用缓存)效率相当,JSON的效率比Apache稍好,但是与Springcglib还有一定的差距。整体而言,效率由高到低的排序为:
getter/setter > cglib > Spring > Apache

在使用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.2jar包存在冲突,将asm版本降级到3.x可解决该问题。

结合项目中asm高版本的jar包使用较多的实际情况,建议以后使用 Spring BeanUtils 方法作为BeanCopy的实现方法,由此提高效率。

posted on 2019-10-25 11:35  lie隼  阅读(1538)  评论(0编辑  收藏  举报