日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

阿里巴巴为什么禁止使用Apache Beanutils进行属性复制?

發布時間:2025/3/11 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里巴巴为什么禁止使用Apache Beanutils进行属性复制? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 l Hollis

來源 l Hollis(ID:hollischuang)

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

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

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

1、Spring BeanUtils?

2、Cglib BeanCopier?

3、Apache BeanUtils?

4、Apache PropertyUtils?

5、Dozer

那么,我們到底應該選擇哪種工具類更加合適呢?為什么阿里巴巴Java開發手冊中提到禁止使用Apache BeanUtils呢?

由于篇幅優先,關于這幾種工具類的用法及區別,還有到底是什么是淺拷貝和深拷貝不在本文的討論范圍內。

本文主要聚焦于對比這幾個類庫的性能問題。

性能對比

No Data No BB,我們就來寫代碼來對比下這幾種框架的性能情況。

代碼示例如下:

首先定義一個PersonDO類:

public?class?PersonDO?{private?Integer?id;private?String?name;private?Integer?age;private?Date?birthday;//省略setter/getter}

再定義一個PersonDTO類:

public?class?PersonDTO?{private?String?name;private?Integer?age;private?Date?birthday;}

然后進行測試類的編寫:

使用Spring BeanUtils進行屬性拷貝:

private?void?mappingBySpringBeanUtils(PersonDO?personDO,?int?times)?{StopWatch?stopwatch?=?new?StopWatch();stopwatch.start();for?(int?i?=?0;?i?<?times;?i++)?{PersonDTO?personDTO?=?new?PersonDTO();org.springframework.beans.BeanUtils.copyProperties(personDO,?personDTO);}stopwatch.stop();System.out.println("mappingBySpringBeanUtils?cost?:"?+?stopwatch.getTotalTimeMillis());}

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

使用Cglib BeanCopier進行屬性拷貝:

private?void?mappingByCglibBeanCopier(PersonDO?personDO,?int?times)?{StopWatch?stopwatch?=?new?StopWatch();stopwatch.start();for?(int?i?=?0;?i?<?times;?i++)?{PersonDTO?personDTO?=?new?PersonDTO();BeanCopier?copier?=?BeanCopier.create(PersonDO.class,?PersonDTO.class,?false);copier.copy(personDO,?personDTO,?null);}stopwatch.stop();System.out.println("mappingByCglibBeanCopier?cost?:"?+?stopwatch.getTotalTimeMillis());}

使用Apache BeanUtils進行屬性拷貝:

private?void?mappingByApacheBeanUtils(PersonDO?personDO,?int?times)throws?InvocationTargetException,?IllegalAccessException?{StopWatch?stopwatch?=?new?StopWatch();stopwatch.start();for?(int?i?=?0;?i?<?times;?i++)?{PersonDTO?personDTO?=?new?PersonDTO();BeanUtils.copyProperties(personDTO,?personDO);}stopwatch.stop();System.out.println("mappingByApacheBeanUtils?cost?:"?+?stopwatch.getTotalTimeMillis());}

使用Apache PropertyUtils進行屬性拷貝:

private?void?mappingByApachePropertyUtils(PersonDO?personDO,?int?times)throws?InvocationTargetException,?IllegalAccessException,?NoSuchMethodException?{StopWatch?stopwatch?=?new?StopWatch();stopwatch.start();for?(int?i?=?0;?i?<?times;?i++)?{PersonDTO?personDTO?=?new?PersonDTO();PropertyUtils.copyProperties(personDTO,?personDO);}stopwatch.stop();System.out.println("mappingByApachePropertyUtils?cost?:"?+?stopwatch.getTotalTimeMillis());}

然后執行以下代碼:

public?static?void?main(String[]?args)throws?InvocationTargetException,?IllegalAccessException,?NoSuchMethodException?{PersonDO?personDO?=?new?PersonDO();personDO.setName("Hollis");personDO.setAge(26);personDO.setBirthday(new?Date());personDO.setId(1);MapperTest?mapperTest?=?new?MapperTest();mapperTest.mappingBySpringBeanUtils(personDO,?100);mapperTest.mappingBySpringBeanUtils(personDO,?1000);mapperTest.mappingBySpringBeanUtils(personDO,?10000);mapperTest.mappingBySpringBeanUtils(personDO,?100000);mapperTest.mappingBySpringBeanUtils(personDO,?1000000);mapperTest.mappingByCglibBeanCopier(personDO,?100);mapperTest.mappingByCglibBeanCopier(personDO,?1000);mapperTest.mappingByCglibBeanCopier(personDO,?10000);mapperTest.mappingByCglibBeanCopier(personDO,?100000);mapperTest.mappingByCglibBeanCopier(personDO,?1000000);mapperTest.mappingByApachePropertyUtils(personDO,?100);mapperTest.mappingByApachePropertyUtils(personDO,?1000);mapperTest.mappingByApachePropertyUtils(personDO,?10000);mapperTest.mappingByApachePropertyUtils(personDO,?100000);mapperTest.mappingByApachePropertyUtils(personDO,?1000000);mapperTest.mappingByApacheBeanUtils(personDO,?100);mapperTest.mappingByApacheBeanUtils(personDO,?1000);mapperTest.mappingByApacheBeanUtils(personDO,?10000);mapperTest.mappingByApacheBeanUtils(personDO,?100000);mapperTest.mappingByApacheBeanUtils(personDO,?1000000);}

得到結果如下:

工具類執行1000次耗時執行10000次耗時執行100000次耗時執行1000000次耗時
Spring BeanUtils5ms10ms45ms169ms
Cglib BeanCopier4ms18ms45ms91ms
Apache PropertyUtils60ms265ms1444ms11492ms
Apache BeanUtils138ms816ms4154ms36938ms
Dozer566ms2254ms11136ms102965ms

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

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

所以,如果考慮性能情況的話,建議大家不要選擇Apache PropertyUtils、Apache BeanUtils以及Dozer等工具類。

很多人會不理解,為什么大名鼎鼎的Apache開源出來的的類庫性能確不高呢?這不像是Apache的風格呀,這背后導致性能低下的原因又是什么呢?

其實,是因為Apache BeanUtils力求做得完美, 在代碼中增加了非常多的校驗、兼容、日志打印等代碼,過度的包裝導致性能下降嚴重。

總結

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

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

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

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

<!--Apache?PropertyUtils、Apache?BeanUtils--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1.2</version></dependency><!--Spring?PropertyUtils--><dependency><groupId>org.springframework</groupId><artifactId>org.springframework.beans</artifactId><version>3.1.1.RELEASE</version></dependency><!--cglib--><dependency><groupId>cglib</groupId><artifactId>cglib-nodep</artifactId><version>2.2.2</version></dependency><!--dozer--><dependency><groupId>net.sf.dozer</groupId><artifactId>dozer</artifactId><version>5.5.1</version></dependency><!--日志相關--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.7</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.7</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.7</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>1.7.7</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId><version>1.7.7</version></dependency>

往期推薦

URL 去重的 6 種方案!(附詳細代碼)


多圖證明,Java到底是值傳遞還是引用傳遞?


阿里為什么推薦使用LongAdder,而不是volatile?

關注下方二維碼,收獲更多干貨!

總結

以上是生活随笔為你收集整理的阿里巴巴为什么禁止使用Apache Beanutils进行属性复制?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。