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 BeanCopierTestObject 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的实现方法,由此提高效率。
    请dalao不吝赐教。
                    
                
                
            
        
浙公网安备 33010602011771号