自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

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

[[335679]]

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

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

1、Spring BeanUtils

2、Cglib BeanCopier

3、Apache BeanUtils

4、Apache PropertyUtils

5、Dozer

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

性能對比

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用于記錄代碼執(zhí)行時間,方便進行對比。

使用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.  

然后執(zhí)行以下代碼:

  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.  

得到結(jié)果如下:

工具類 執(zhí)行1000次耗時 執(zhí)行10000次耗時 執(zhí)行100000次耗時 執(zhí)行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

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

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

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

總結(jié)

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

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

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

 

本文用到的第三方類庫的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

對象賦值項目開發(fā)

2018-10-16 15:34:17

阿里巴巴Apache Flin大數(shù)據(jù)

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外循環(huán)內(nèi)循環(huán)

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開發(fā)繼承

2019-09-04 11:02:54

繼承層次組合

2020-09-14 09:47:56

Java開發(fā)類型

2022-08-30 16:38:30

阿里巴巴JavaLog4j

2016-09-21 20:28:55

阿里巴巴IOE

2019-02-27 09:00:13

阿里巴巴for循環(huán)Java

2019-01-29 10:30:32

阿里巴巴Java字符串

2021-09-07 17:22:43

阿里巴巴辭職高薪

2018-12-04 15:54:42

阿里巴巴日志系統(tǒng)
點贊
收藏

51CTO技術棧公眾號