Bean复制的几种方式比较

开发中经常用到bean的复制,常用的有Apache BeanUtils、PropertyUtils,Spring BeanUtils,Cglib BeanCopier和直接set,下面对这几种简单进行性能测试

FromBean ToBean

@Data
public class FromBean {

  private String name;
  private int age;
  private String address;
  private String idNo;
  private BigDecimal money;
}

@Data
public class ToBean extends FromBean {

}

BenchmarkTest

public class BenchmarkTest {

  private int count;

  public BenchmarkTest(int count) {
    this.count = count;
    System.out.println("性能测试" + this.count + "==================");
  }

  public void benchmark(MethodCallBack m, FromBean frombean) {
    try {
      long begin = System.currentTimeMillis();
      ToBean tobean = null;
      for (int i = 0; i < count; i++) {

        tobean = m.callMethod(frombean);

      }
      System.out.println(String.format("%-60s 耗时:%sms", m.getMethodName(),
          System.currentTimeMillis() - begin));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

MethodCallBack

public interface MethodCallBack {

  String getMethodName();

  ToBean callMethod(FromBean frombean) throws Exception;
}

TestMain

public class TestMain {

  public static void main(String[] args) {
    FromBean fb = new FromBean();
    fb.setAddress("北京市朝阳区大屯路");
    fb.setAge(20);
    fb.setMoney(new BigDecimal(30000.111));
    fb.setIdNo("110330219879208733");
    fb.setName("测试");

    MethodCallBack beanutilCB = new MethodCallBack() {

      @Override
      public String getMethodName() {
        return "org.apache.commons.beanutils.BeanUtils.copyProperties";
      }

      @Override
      public ToBean callMethod(FromBean frombean) throws Exception {

        ToBean toBean = new ToBean();
        BeanUtils.copyProperties(toBean, frombean);
        return toBean;
      }
    };

    MethodCallBack propertyCB = new MethodCallBack() {

      @Override
      public String getMethodName() {
        return "org.apache.commons.beanutils.PropertyUtils.copyProperties";
      }

      @Override
      public ToBean callMethod(FromBean frombean) throws Exception {
        ToBean toBean = new ToBean();
        PropertyUtils.copyProperties(toBean, frombean);
        return toBean;
      }
    };

    MethodCallBack springCB = new MethodCallBack() {

      @Override
      public String getMethodName() {
        return "org.springframework.beans.BeanUtils.copyProperties";
      }

      @Override
      public ToBean callMethod(FromBean frombean) throws Exception {
        ToBean toBean = new ToBean();
        org.springframework.beans.BeanUtils.copyProperties(frombean,
            toBean);
        return toBean;
      }
    };

    MethodCallBack cglibCB = new MethodCallBack() {
      BeanCopier bc = BeanCopier.create(FromBean.class, ToBean.class,
          false);

      @Override
      public String getMethodName() {
        return "org.springframework.cglib.beans.BeanCopier.create";
      }

      @Override
      public ToBean callMethod(FromBean frombean) throws Exception {
        ToBean toBean = new ToBean();
        bc.copy(frombean, toBean, null);
        return toBean;
      }
    };

    MethodCallBack setCB = new MethodCallBack() {

      @Override
      public String getMethodName() {
        return "set method";
      }

      @Override
      public ToBean callMethod(FromBean frombean) throws Exception {
        ToBean toBean = new ToBean();
        toBean.setAddress(frombean.getAddress());
        toBean.setAge(frombean.getAge());
        toBean.setIdNo(frombean.getIdNo());
        toBean.setMoney(frombean.getMoney());
        toBean.setName(frombean.getName());
        return toBean;
      }
    };

    // 数量较少的时候,测试性能
    BenchmarkTest bt = new BenchmarkTest(10);
    bt.benchmark(beanutilCB, fb);
    bt.benchmark(propertyCB, fb);
    bt.benchmark(springCB, fb);
    bt.benchmark(cglibCB, fb);
    bt.benchmark(setCB, fb);

    // 测试一千次性能测试
    BenchmarkTest bt1000 = new BenchmarkTest(1000);
    bt1000.benchmark(beanutilCB, fb);
    bt1000.benchmark(propertyCB, fb);
    bt1000.benchmark(springCB, fb);
    bt1000.benchmark(cglibCB, fb);
    bt1000.benchmark(setCB, fb);

    // 测试一万次性能测试
    BenchmarkTest bt10000 = new BenchmarkTest(10000);
    bt10000.benchmark(beanutilCB, fb);
    bt10000.benchmark(propertyCB, fb);
    bt10000.benchmark(springCB, fb);
    bt10000.benchmark(cglibCB, fb);
    bt10000.benchmark(setCB, fb);

    // 担心因为顺序问题影响测试结果
    BenchmarkTest bt1000R = new BenchmarkTest(10000);
    bt1000R.benchmark(setCB, fb);
    bt1000R.benchmark(cglibCB, fb);
    bt1000R.benchmark(springCB, fb);
    bt1000R.benchmark(propertyCB, fb);
    bt1000R.benchmark(beanutilCB, fb);

  }
}

测试结果:

第一次:
性能测试10==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:791ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:6ms
org.springframework.beans.BeanUtils.copyProperties           耗时:43ms
org.springframework.cglib.beans.BeanCopier.create            耗时:0ms
set method                                                   耗时:0ms
性能测试1000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:79ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:21ms
org.springframework.beans.BeanUtils.copyProperties           耗时:17ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
set method                                                   耗时:0ms
性能测试10000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:291ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:104ms
org.springframework.beans.BeanUtils.copyProperties           耗时:43ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
set method                                                   耗时:1ms
性能测试10000==================
set method                                                   耗时:0ms
org.springframework.cglib.beans.BeanCopier.create            耗时:0ms
org.springframework.beans.BeanUtils.copyProperties           耗时:27ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:56ms
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:94ms

第二次:
性能测试10==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:731ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:5ms
org.springframework.beans.BeanUtils.copyProperties           耗时:58ms
org.springframework.cglib.beans.BeanCopier.create            耗时:0ms
set method                                                   耗时:0ms
性能测试1000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:91ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:17ms
org.springframework.beans.BeanUtils.copyProperties           耗时:30ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
set method                                                   耗时:0ms
性能测试10000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:261ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:87ms
org.springframework.beans.BeanUtils.copyProperties           耗时:60ms
org.springframework.cglib.beans.BeanCopier.create            耗时:2ms
set method                                                   耗时:0ms
性能测试10000==================
set method                                                   耗时:1ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
org.springframework.beans.BeanUtils.copyProperties           耗时:33ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:43ms
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:80ms

第三次:
性能测试10==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:710ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:5ms
org.springframework.beans.BeanUtils.copyProperties           耗时:72ms
org.springframework.cglib.beans.BeanCopier.create            耗时:0ms
set method                                                   耗时:0ms
性能测试1000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:98ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:96ms
org.springframework.beans.BeanUtils.copyProperties           耗时:13ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
set method                                                   耗时:1ms
性能测试10000==================
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:268ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:80ms
org.springframework.beans.BeanUtils.copyProperties           耗时:73ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
set method                                                   耗时:0ms
性能测试10000==================
set method                                                   耗时:0ms
org.springframework.cglib.beans.BeanCopier.create            耗时:1ms
org.springframework.beans.BeanUtils.copyProperties           耗时:56ms
org.apache.commons.beanutils.PropertyUtils.copyProperties    耗时:43ms
org.apache.commons.beanutils.BeanUtils.copyProperties        耗时:99ms

结论:

    Apache BeanUtils 性能最差

    Apache PropertyUtils 基本是线性增长

    Spring BeanUtils 不稳定

    Cglib和直接set性能最好

原因分析:

    Apache BeanUtils、PropertyUtils、Spring BeanUtils采用反射

    Cglib采用动态代理

转载于:https://my.oschina.net/jzgycq/blog/2250197

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值