Bean复制的几种框架对比,看完心酸

开发 架构
作为一个员工,最重要的不是编写代码,而是阅读代码,本博主在阅读代码的时候,发现几种实现两个不同类型的Bean的差异,本着研究的精神,仔细对比了Bean复制的性能差异。

[[375476]]

本文转载自微信公众号「小明菜市场」,作者小明菜市场 。转载本文请联系小明菜市场公众号。

正文

作为一个员工,最重要的不是编写代码,而是阅读代码,本博主在阅读代码的时候,发现几种实现两个不同类型的Bean的差异,本着研究的精神,仔细对比了Bean复制的性能差异。

比较的框架分别是Apache的BeanUtils,PropertyUtils,Spring的,BeanUtils,Cglib的BeanCopier。

做法是在idea新建了一个Project,专门用于专门测试几种代码的性能。具体的代码如下:一个FromBean和一个ToBean。

  1. public class FromBean { 
  2.     private String name
  3.     private int age; 
  4.     private String address; 
  5.     private String idno; 
  6.     private double money; 
  7.   
  8.     public double getMoney() { 
  9.         return money; 
  10.     } 
  11.   
  12.     public void setMoney(double money) { 
  13.         this.money = money; 
  14.     } 
  15.   
  16.     public String getName() { 
  17.         return name
  18.     } 
  19.   
  20.     public void setName(String name) { 
  21.         this.name = name
  22.     } 
  23.   
  24.     public int getAge() { 
  25.         return age; 
  26.     } 
  27.   
  28.     public void setAge(int age) { 
  29.         this.age = age; 
  30.     } 
  31.   
  32.     public String getAddress() { 
  33.         return address; 
  34.     } 
  35.   
  36.     public void setAddress(String address) { 
  37.         this.address = address; 
  38.     } 
  39.   
  40.     public String getIdno() { 
  41.         return idno; 
  42.     } 
  43.   
  44.     public void setIdno(String idno) { 
  45.         this.idno = idno; 
  46.     } 
  47.   

一个用于测试的BenchmarkTest类

  1. public class BenchmarkTest { 
  2.     private int count
  3.  
  4.     public BenchmarkTest(int count) { 
  5.         this.count = count
  6.         System.out.println("性能测试" + this.count + "=================="); 
  7.     } 
  8.  
  9.     public void benchmark(IMethodCallBack m, FromBean frombean) { 
  10.         try { 
  11.             long begin = new java.util.Date().getTime(); 
  12.             ToBean tobean = null
  13.             System.out.println(m.getMethodName() + "开始进行测试"); 
  14.             for (int i = 0; i < count; i++) { 
  15.  
  16.                 tobean = m.callMethod(frombean); 
  17.  
  18.             } 
  19.             long end = new java.util.Date().getTime(); 
  20.             System.out.println(m.getMethodName() + "耗时" + (end - begin)); 
  21.             System.out.println(tobean.getAddress()); 
  22.             System.out.println(tobean.getAge()); 
  23.             System.out.println(tobean.getIdno()); 
  24.             System.out.println(tobean.getMoney()); 
  25.             System.out.println(tobean.getName()); 
  26.             System.out.println("                                      "); 
  27.         } catch (Exception e) { 
  28.             e.printStackTrace(); 
  29.         } 
  30.     } 

对接口的声明

  1. public interface IMethodCallBack { 
  2.  
  3.     String getMethodName(); 
  4.  
  5.     ToBean callMethod(FromBean frombean)  throws Exception; 
  6.  
  7.     

使用的测试类

  1. public class TestMain { 
  2.  
  3.     /** 
  4.      * @param args 
  5.      */ 
  6.     public static void main(String[] args) { 
  7.         FromBean fb = new FromBean(); 
  8.         fb.setAddress("北京市朝阳区大屯路"); 
  9.         fb.setAge(20); 
  10.         fb.setMoney(30000.111); 
  11.         fb.setIdno("110330219879208733"); 
  12.         fb.setName("测试"); 
  13.  
  14.         IMethodCallBack beanutilCB = new IMethodCallBack() { 
  15.  
  16.             @Override 
  17.             public String getMethodName() { 
  18.                 return "BeanUtil.copyProperties"
  19.             } 
  20.  
  21.             @Override 
  22.             public ToBean callMethod(FromBean frombean) throws Exception { 
  23.  
  24.                 ToBean toBean = new ToBean(); 
  25.                 BeanUtils.copyProperties(toBean, frombean); 
  26.                 return toBean; 
  27.             } 
  28.         }; 
  29.  
  30.         IMethodCallBack propertyCB = new IMethodCallBack() { 
  31.  
  32.             @Override 
  33.             public String getMethodName() { 
  34.                 return "PropertyUtils.copyProperties"
  35.             } 
  36.  
  37.             @Override 
  38.             public ToBean callMethod(FromBean frombean) throws Exception { 
  39.                 ToBean toBean = new ToBean(); 
  40.                 PropertyUtils.copyProperties(toBean, frombean); 
  41.                 return toBean; 
  42.             } 
  43.         }; 
  44.  
  45.         IMethodCallBack springCB = new IMethodCallBack() { 
  46.  
  47.             @Override 
  48.             public String getMethodName() { 
  49.                 return "org.springframework.beans.BeanUtils.copyProperties"
  50.             } 
  51.  
  52.             @Override 
  53.             public ToBean callMethod(FromBean frombean) throws Exception { 
  54.                 ToBean toBean = new ToBean(); 
  55.                 org.springframework.beans.BeanUtils.copyProperties(frombean, 
  56.                         toBean); 
  57.                 return toBean; 
  58.             } 
  59.         }; 
  60.  
  61.         IMethodCallBack cglibCB = new IMethodCallBack() { 
  62.             BeanCopier bc = BeanCopier.create(FromBean.class, ToBean.class, 
  63.                     false); 
  64.  
  65.             @Override 
  66.             public String getMethodName() { 
  67.                 return "BeanCopier.create"
  68.             } 
  69.  
  70.             @Override 
  71.             public ToBean callMethod(FromBean frombean) throws Exception { 
  72.                 ToBean toBean = new ToBean(); 
  73.                 bc.copy(frombean, toBean, null); 
  74.                 return toBean; 
  75.             } 
  76.         }; 
  77.  
  78.         // 数量较少的时候,测试性能 
  79.         BenchmarkTest bt = new BenchmarkTest(10); 
  80.         bt.benchmark(beanutilCB, fb); 
  81.         bt.benchmark(propertyCB, fb); 
  82.         bt.benchmark(springCB, fb); 
  83.         bt.benchmark(cglibCB, fb); 
  84.  
  85.         // 测试一万次性能测试 
  86.         BenchmarkTest bt10000 = new BenchmarkTest(10000); 
  87.         bt10000.benchmark(beanutilCB, fb); 
  88.         bt10000.benchmark(propertyCB, fb); 
  89.         bt10000.benchmark(springCB, fb); 
  90.         bt10000.benchmark(cglibCB, fb); 
  91.  
  92.         // 担心因为顺序问题影响测试结果 
  93.         BenchmarkTest bt1000R = new BenchmarkTest(10000); 
  94.         bt1000R.benchmark(cglibCB, fb); 
  95.         bt1000R.benchmark(springCB, fb); 
  96.         bt1000R.benchmark(propertyCB, fb); 
  97.         bt1000R.benchmark(beanutilCB, fb); 
  98.  
  99.     } 
  100.  

测试的结果如下

不过需要注意的是,Cglib在测试的时候,先进行了实例的缓存,这个也是他性能较好的原因之一。如果把缓存去掉的话,性能就会出现了一些的差异,但是整体的性能还是很好, 从整体的表现来看,Cglib的BeanCopier的性能是最好的无论是数量较大的1万次的测试,还是数量较少10次,几乎都是趋近与零损耗,Spring是在次数增多的情况下,性能较好,在数据较少的时候,性能比PropertyUtils的性能差一些。PropertyUtils的性能相对稳定,表现是呈现线性增长的趋势。而Apache的BeanUtil的性能最差,无论是单次Copy还是大数量的多次Copy性能都不是很好。

 

责任编辑:武晓燕 来源: 小明菜市场
相关推荐

2021-01-11 14:16:19

Bean代码Java

2017-11-15 08:52:18

软件硬件复制

2022-05-27 08:25:55

容器Spring

2022-05-12 09:37:03

测试JUnit开发

2020-06-02 14:45:48

PostgreSQL架构分布式

2022-03-16 11:11:37

SpringBean项目

2019-12-25 09:53:01

虚拟机技术固态硬盘

2012-07-06 09:59:09

iOS 6Android 4.1

2017-07-14 14:50:00

架构框架前端

2019-08-23 10:10:58

Nginx反向代理防盗链

2017-06-27 14:02:09

前端框架Bootstrap

2019-03-06 09:55:54

Python 开发编程语言

2010-09-01 16:07:25

无线局域网

2023-02-17 18:06:33

微服务架构

2013-05-27 10:21:19

2011-06-16 08:22:04

JavaScriptjQuery

2017-09-27 16:44:23

前端

2009-02-01 09:29:44

2012-05-30 13:25:00

2009-07-03 14:46:42

JSP开发框架JSFTapestry
点赞
收藏

51CTO技术栈公众号