成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么阿里巴巴禁止使用Apache Beanutils進行屬性的Copy?

開發 開發工具
在日常開發中,我們經常需要給對象進行賦值,通常會調用其set/get方法,有些時候,如果我們要轉換的兩個對象之間屬性大致相同,會考慮使用屬性拷貝工具進行。

 在日常開發中,我們經常需要給對象進行賦值,通常會調用其set/get方法,有些時候,如果我們要轉換的兩個對象之間屬性大致相同,會考慮使用屬性拷貝工具進行。

[[335679]]

如我們經常在代碼中會對一個數據結構封裝成DO、SDO、DTO、VO等,而這些Bean中的大部分屬性都是一樣的,所以使用屬性拷貝類工具可以幫助我們節省大量的set和get操作。

市面上有很多類似的工具類,比較常用的有

1、Spring BeanUtils

2、Cglib BeanCopier

3、Apache BeanUtils

4、Apache PropertyUtils

5、Dozer

由于篇幅優先,關于這幾種工具類的用法及區別,還有到底是什么是淺拷貝和深拷貝不在本文的討論范圍內。本文主要聚焦于對比這幾個類庫的性能問題。

性能對比

No Data No BB,我們就來寫代碼來對比下這幾種框架的性能情況。代碼示例如下:首先定義一個PersonDO類:

  1. public class PersonDO { 
  2.  
  3.     private Integer id; 
  4.  
  5.     private String name
  6.  
  7.     private Integer age; 
  8.  
  9.     private Date birthday; 
  10.  
  11.     //省略setter/getter 
  12.  

再定義一個PersonDTO類:

  1. public class PersonDTO { 
  2.  
  3.     private String name
  4.  
  5.     private Integer age; 
  6.  
  7.     private Date birthday; 
  8.  

然后進行測試類的編寫:使用Spring BeanUtils進行屬性拷貝:

  1. private void mappingBySpringBeanUtils(PersonDO personDO, int times) { 
  2.  
  3.     StopWatch stopwatch = new StopWatch(); 
  4.  
  5.     stopwatch.start(); 
  6.  
  7.  
  8.     for (int i = 0; i < times; i++) { 
  9.  
  10.         PersonDTO personDTO = new PersonDTO(); 
  11.  
  12.         org.springframework.beans.BeanUtils.copyProperties(personDO, personDTO); 
  13.  
  14.     } 
  15.  
  16.     stopwatch.stop(); 
  17.  
  18.     System.out.println("mappingBySpringBeanUtils cost :" + stopwatch.getTotalTimeMillis()); 
  19.  

其中的StopWatch用于記錄代碼執行時間,方便進行對比。

使用Cglib BeanCopier進行屬性拷貝:

  1. private void mappingByCglibBeanCopier(PersonDO personDO, int times) { 
  2.  
  3.     StopWatch stopwatch = new StopWatch(); 
  4.  
  5.     stopwatch.start(); 
  6.  
  7.     for (int i = 0; i < times; i++) { 
  8.  
  9.         PersonDTO personDTO = new PersonDTO(); 
  10.  
  11.         BeanCopier copier = BeanCopier.create(PersonDO.class, PersonDTO.class, false); 
  12.  
  13.         copier.copy(personDO, personDTO, null); 
  14.  
  15.     } 
  16.  
  17.     stopwatch.stop(); 
  18.  
  19.     System.out.println("mappingByCglibBeanCopier cost :" + stopwatch.getTotalTimeMillis()); 
  20.  

使用Apache BeanUtils進行屬性拷貝:

  1. private void mappingByApacheBeanUtils(PersonDO personDO, int times) 
  2.  
  3.     throws InvocationTargetException, IllegalAccessException { 
  4.  
  5.     StopWatch stopwatch = new StopWatch(); 
  6.  
  7.     stopwatch.start(); 
  8.  
  9.     for (int i = 0; i < times; i++) { 
  10.  
  11.         PersonDTO personDTO = new PersonDTO(); 
  12.  
  13.         BeanUtils.copyProperties(personDTO, personDO); 
  14.  
  15.     } 
  16.  
  17.     stopwatch.stop(); 
  18.  
  19.     System.out.println("mappingByApacheBeanUtils cost :" + stopwatch.getTotalTimeMillis()); 
  20.  

使用Apache PropertyUtils進行屬性拷貝:

  1. private void mappingByApachePropertyUtils(PersonDO personDO, int times) 
  2.  
  3.     throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { 
  4.  
  5.     StopWatch stopwatch = new StopWatch(); 
  6.  
  7.     stopwatch.start(); 
  8.  
  9.     for (int i = 0; i < times; i++) { 
  10.  
  11.         PersonDTO personDTO = new PersonDTO(); 
  12.  
  13.         PropertyUtils.copyProperties(personDTO, personDO); 
  14.  
  15.     } 
  16.  
  17.     stopwatch.stop(); 
  18.  
  19.     System.out.println("mappingByApachePropertyUtils cost :" + stopwatch.getTotalTimeMillis()); 
  20.  

然后執行以下代碼:

  1. public static void main(String[] args) 
  2.  
  3.     throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { 
  4.  
  5.     PersonDO personDO = new PersonDO(); 
  6.  
  7.     personDO.setName("Hollis"); 
  8.  
  9.     personDO.setAge(26); 
  10.  
  11.     personDO.setBirthday(new Date()); 
  12.  
  13.     personDO.setId(1); 
  14.  
  15.  
  16.     MapperTest mapperTest = new MapperTest(); 
  17.  
  18.  
  19.     mapperTest.mappingBySpringBeanUtils(personDO, 100); 
  20.  
  21.     mapperTest.mappingBySpringBeanUtils(personDO, 1000); 
  22.  
  23.     mapperTest.mappingBySpringBeanUtils(personDO, 10000); 
  24.  
  25.     mapperTest.mappingBySpringBeanUtils(personDO, 100000); 
  26.  
  27.     mapperTest.mappingBySpringBeanUtils(personDO, 1000000); 
  28.  
  29.     mapperTest.mappingByCglibBeanCopier(personDO, 100); 
  30.  
  31.     mapperTest.mappingByCglibBeanCopier(personDO, 1000); 
  32.  
  33.     mapperTest.mappingByCglibBeanCopier(personDO, 10000); 
  34.  
  35.     mapperTest.mappingByCglibBeanCopier(personDO, 100000); 
  36.  
  37.     mapperTest.mappingByCglibBeanCopier(personDO, 1000000); 
  38.  
  39.     mapperTest.mappingByApachePropertyUtils(personDO, 100); 
  40.  
  41.     mapperTest.mappingByApachePropertyUtils(personDO, 1000); 
  42.  
  43.     mapperTest.mappingByApachePropertyUtils(personDO, 10000); 
  44.  
  45.     mapperTest.mappingByApachePropertyUtils(personDO, 100000); 
  46.  
  47.     mapperTest.mappingByApachePropertyUtils(personDO, 1000000); 
  48.  
  49.     mapperTest.mappingByApacheBeanUtils(personDO, 100); 
  50.  
  51.     mapperTest.mappingByApacheBeanUtils(personDO, 1000); 
  52.  
  53.     mapperTest.mappingByApacheBeanUtils(personDO, 10000); 
  54.  
  55.     mapperTest.mappingByApacheBeanUtils(personDO, 100000); 
  56.  
  57.     mapperTest.mappingByApacheBeanUtils(personDO, 1000000); 
  58.  

得到結果如下:

工具類 執行1000次耗時 執行10000次耗時 執行100000次耗時 執行1000000次耗時
Spring BeanUtils 5ms 10ms 45ms 169ms
Cglib BeanCopier 4ms 18ms 45ms 91ms
Apache PropertyUtils 60ms 265ms 1444ms 11492ms
Apache BeanUtils 138ms 816ms 4154ms 36938ms
Dozer 566ms 2254ms 11136ms 102965ms

畫了一張折線圖更方便大家進行對比

綜上,我們基本可以得出結論,在性能方面,Spring BeanUtils和Cglib BeanCopier表現比較不錯,而Apache PropertyUtils、Apache BeanUtils以及Dozer則表現的很不好。

所以,如果考慮性能情況的話,建議大家不要選擇Apache PropertyUtils、Apache BeanUtils以及Dozer等工具類。很多人會不理解,為什么大名鼎鼎的Apache開源出來的的類庫性能確不高呢?這不像是Apache的風格呀,這背后導致性能低下的原因又是什么呢?其實,是因為Apache BeanUtils力求做得完美, 在代碼中增加了非常多的校驗、兼容、日志打印等代碼,過度的包裝導致性能下降嚴重。

總結

本文通過對比幾種常見的屬性拷貝的類庫,分析得出了這些工具類的性能情況,最終也驗證了《阿里巴巴Java開發手冊》中提到的"Apache BeanUtils 效率低"的事實。

但是本文只是站在性能這一單一角度進行了對比,我們在選擇一個工具類的時候還會有其他方面的考慮,比如使用成本、理解難度、兼容性、可擴展性等,對于這種拷貝類工具類,我們還會考慮其功能是否完善等。

就像雖然Dozer性能比較差,但是他可以很好的和Spring結合,可以通過配置文件等進行屬性之間的映射等,也受到了很多開發者的喜愛。

 

本文用到的第三方類庫的maven依賴如下:

  1. <!--Apache PropertyUtils、Apache BeanUtils--> 
  2.  
  3. <dependency> 
  4.  
  5.     <groupId>commons-beanutils</groupId> 
  6.  
  7.     <artifactId>commons-beanutils</artifactId> 
  8.  
  9.     <version>1.9.4</version> 
  10.  
  11. </dependency> 
  12.  
  13.  
  14.  
  15. <dependency> 
  16.  
  17.     <groupId>commons-logging</groupId> 
  18.  
  19.     <artifactId>commons-logging</artifactId> 
  20.  
  21.     <version>1.1.2</version> 
  22.  
  23. </dependency> 
  24.  
  25.  
  26.  
  27. <!--Spring PropertyUtils--> 
  28.  
  29. <dependency> 
  30.  
  31.     <groupId>org.springframework</groupId> 
  32.  
  33.     <artifactId>org.springframework.beans</artifactId> 
  34.  
  35.     <version>3.1.1.RELEASE</version> 
  36.  
  37. </dependency> 
  38.  
  39.  
  40.  
  41. <!--cglib--> 
  42.  
  43. <dependency> 
  44.  
  45.     <groupId>cglib</groupId> 
  46.  
  47.     <artifactId>cglib-nodep</artifactId> 
  48.  
  49.     <version>2.2.2</version> 
  50.  
  51. </dependency> 
  52.  
  53.  
  54.  
  55. <!--dozer--> 
  56.  
  57. <dependency> 
  58.  
  59.     <groupId>net.sf.dozer</groupId> 
  60.  
  61.     <artifactId>dozer</artifactId> 
  62.  
  63.     <version>5.5.1</version> 
  64.  
  65. </dependency> 
  66.  
  67.  
  68.  
  69. <!--日志相關--> 
  70.  
  71. <dependency> 
  72.  
  73.     <groupId>org.slf4j</groupId> 
  74.  
  75.     <artifactId>slf4j-api</artifactId> 
  76.  
  77.     <version>1.7.7</version> 
  78.  
  79. </dependency> 
  80.  
  81.  
  82.  
  83. <dependency> 
  84.  
  85.     <groupId>org.slf4j</groupId> 
  86.  
  87.     <artifactId>jul-to-slf4j</artifactId> 
  88.  
  89.     <version>1.7.7</version> 
  90.  
  91. </dependency> 
  92.  
  93.  
  94.  
  95. <dependency> 
  96.  
  97.     <groupId>org.slf4j</groupId> 
  98.  
  99.     <artifactId>jcl-over-slf4j</artifactId> 
  100.  
  101.     <version>1.7.7</version> 
  102.  
  103. </dependency> 
  104.  
  105.  
  106.  
  107. <dependency> 
  108.  
  109.     <groupId>org.slf4j</groupId> 
  110.  
  111.     <artifactId>log4j-over-slf4j</artifactId> 
  112.  
  113.     <version>1.7.7</version> 
  114.  
  115. </dependency> 
  116.  
  117.  
  118.  
  119. <dependency> 
  120.  
  121.     <groupId>org.slf4j</groupId> 
  122.  
  123.     <artifactId>slf4j-jdk14</artifactId> 
  124.  
  125.     <version>1.7.7</version> 
  126.  
  127. </dependency> 

 

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2020-09-08 16:25:18

Apache BeancopyJava

2023-01-11 08:06:42

對象賦值項目開發

2018-10-16 15:34:17

阿里巴巴Apache Flin大數據

2020-09-22 11:40:53

BigDecimalequalsJava

2021-10-11 09:32:40

包裝類型屬性

2019-03-04 09:22:52

阿里巴巴foreach Java

2025-04-17 08:47:23

2022-09-05 10:06:21

MySQL外循環內循環

2021-08-04 17:20:30

阿里巴巴AsyncJava

2013-08-22 09:26:38

去IOE王堅

2019-06-26 07:54:53

ArrayListsubList源碼

2019-09-02 15:20:28

Java開發繼承

2019-09-04 11:02:54

繼承層次組合

2016-09-21 20:28:55

阿里巴巴IOE

2020-09-14 09:47:56

Java開發類型

2022-08-30 16:38:30

阿里巴巴JavaLog4j

2019-02-27 09:00:13

阿里巴巴for循環Java

2019-01-29 10:30:32

阿里巴巴Java字符串

2021-09-07 17:22:43

阿里巴巴辭職高薪

2018-12-04 15:54:42

阿里巴巴日志系統
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产日韩精品一区二区 | 99精品久久久久久中文字幕 | www国产精品 | 一本色道精品久久一区二区三区 | 欧美一级二级在线观看 | 欧美一区二区在线观看 | 国产乱码精品一区二区三区中文 | 成人免费网站 | 国产一区不卡 | 日韩一区二区在线免费观看 | 一色桃子av一区二区 | 日韩中文字幕视频在线观看 | 成人在线不卡 | 狠狠涩| 激情小说综合网 | 五月激情婷婷网 | 色www精品视频在线观看 | 激情小说综合网 | 亚洲精品视频久久 | 欧美不卡一区二区 | 91资源在线 | 岛国av免费观看 | 一级黄色播放 | 久久久久久久一区 | 欧美九九九 | 久久国产成人 | 99久久成人 | 久久国产精品视频 | 国产精品一区二区福利视频 | 天天操操| 婷婷精品 | 日本中文字幕日韩精品免费 | 精品99爱视频在线观看 | 一区在线免费视频 | 一区二区三区国产在线观看 | 亚洲一区二区日韩 | 色婷婷久久久亚洲一区二区三区 | 天天操天天干天天曰 | 国产91精品网站 | 国产欧美一区二区三区在线看蜜臀 | 国产精品久久久久久久免费大片 |