• [性能] Bean拷贝工具类性能比较


    Bean拷贝工具类性能比较

    引言

    几年前做过一个项目,接入新的api接口。为了和api实现解耦,决定将api返回的实体类在本地也建一个。这样做有两个好处

    1. 可以在api变更字段的时候保持应用稳定性
    2. 可以对返回的实体的属性做处理,以提高可读性。例如接口返回long类型的时间戳,则将该字段在本地实体类中对应字段设置为date类型方便使用。

    大致是这样的一个应用场景。当时刚毕业,充斥的都是A.setName(B.getName)这种类型的代码。当字段非常多的时候看起来非常臃肿,最重要的给人感觉不优雅。

    再给我一次机会

    如果上天再给我一次机会,我会跟他说,我有四种工具类可以优雅的解决这个问题。
    分别是

    • org.apache.commons.beanutils.PropertyUtils.copyProperties
    • org.apache.commons.beanutils.BeanUtils.copyProperties
    • org.springframework.beans.BeanUtils.copyProperties
    • net.sf.cglib.beans.BeanCopier

    Talk is cheap, show me code

    定义SourceBean

    package com.zhaoyangwoo.model;
    
    /**
     * Created by john on 16/7/28.
     */
     
    public class SourceBean {
    
        private Integer age;
    
        private String title;
        
        private String source;
    
        private Boolean eat;
        
        public SourceBean(Integer i, String name, Boolean eat, String source) {
            this.age = i;
            this.title = name;
            this.eat = eat;
            this.source = source;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public Boolean getEat() {
            return eat;
        }
    
        public void setEat(Boolean eat) {
            this.eat = eat;
        }
    
        public String getSource() {
            return source;
        }
    
        public void setSource(String source) {
            this.source = source;
        }
    
        public Integer getAge() {
            return age;
        }
    
    }
    

    定义DesBean

    package com.zhaoyangwoo.model;
    
    /**
     * Created by john on 16/7/28.
     */
     
    public class DstBean {
    
        private Integer age;
    
        private String title;
    
        private Boolean eat;
    
        private String self;
    
        public String getSelf() {
            return self;
        }
    
        public void setSelf(String self) {
            this.self = self;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public Boolean getEat() {
            return eat;
        }
    
        public void setEat(Boolean eat) {
            this.eat = eat;
        }
    }
    

    测试函数

    package com.zhaoyangwoo.biz;
    
    import com.zhaoyangwoo.model.DstBean;
    import com.zhaoyangwoo.model.SourceBean;
    import net.sf.cglib.beans.BeanCopier;
    
    /**
     * Created by john on 16/7/28.
     */
    public class BeanCopyMain {
    
    private static BeanCopier beanCopier = BeanCopier.create(SourceBean.class, DstBean.class, false);
    
    
    	public static void main(String[] args) throws Exception {
    
            Integer[] times = {10000, 1000, 10};
    
            for (int i = 0; i < times.length; i++) {
    
                Integer time = times[i];
                doCopy(time, (x, y) -> org.apache.commons.beanutils.PropertyUtils.copyProperties(y, x), "org.apache.commons.beanutils.PropertyUtils.copyProperties");
                doCopy(time, (x, y) -> org.apache.commons.beanutils.BeanUtils.copyProperties(y, x), "org.apache.commons.beanutils.BeanUtils.copyProperties");
                doCopy(time, (x, y) -> org.springframework.beans.BeanUtils.copyProperties(y, x), "org.springframework.beans.BeanUtils.copyProperties");
                doCopy(time, (x, y) -> beanCopier.copy(x, y, null), "net.sf.cglib.beans.BeanCopier.copy");
                doCopy(time, (x, y) -> {
                    y.setEat(x.getEat());
                    y.setTitle(x.getTitle());
                    y.setAge(x.getAge());
                }, "getter/setter");
            }
        }
    
        static void doCopy(Integer time, BeanCopy beanCopy, String type) throws Exception {
            long startTime = System.currentTimeMillis();
            for (int j = 0; j < time; j++) {
                SourceBean sourceBean = new SourceBean(j, "source" + j, false, "abc");
                DstBean dstBean = new DstBean();
                beanCopy.copy(sourceBean, dstBean);
            }
            System.out.printf("执行%d次用时%dms---------%s%n", time, System.currentTimeMillis() - startTime, type);
        }
    
        interface BeanCopy {
            void copy(SourceBean from, DstBean to) throws Exception;
        }
    }
    

    执行结果如下

    结论

    根据上面的运行结果,我们可以得出以下结论

    • property少,写起来也不麻烦,就直接用传统的getter/setter,性能最好
    • property多,转换不频繁,那就省点事吧,使用org.apache.commons.beanutils.BeanUtils.copyProperties
    • property多,转换很频繁,为性能考虑,使用net.sf.cglib.beans.BeanCopier.BeanCopier,性能近乎getter/setter。但是BeanCopier的创建时消耗较大,所以不要频繁创建该实体,最好的处理方式是静态化或者缓存起来。
    作者: zhaoyanghoo
    出处: http://www.cnblogs.com/zhaoyanghoo/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    bug_ _ 常见的bug1
    键盘-App监听软键盘按键的三种方式
    listview--记录ListView滚动停止位置与设置显示位置
    android shape的使用
    转-android图片降低图片大小保持图片清晰的方法
    转-Android SHA1与Package获取方式
    Android listview中使用checkbox
    保存恢复临时信-Android 中使用onSaveInstanceState和onRestoreInstanceState
    转-Android客户端和服务端如何使用Token和Session
    转-Activity中使用orientation属性讲解及需注意的问题
  • 原文地址:https://www.cnblogs.com/zhaoyanghoo/p/5722113.html
Copyright © 2020-2023  润新知