加速Java應用開發1:Spring/Hibernate應用除錯時啟動速度

張開濤發表於2013-06-30

伯樂線上注:本文來自文章作者張開濤的推薦投稿(原文)。如果其他朋友也有不錯的原創或譯文,可以嘗試推薦給伯樂線上

————————————————————

在除錯spring應用時,動輒幾十秒,甚至有的應用上分鐘的啟動速度,會讓整個除錯速度慢下來了。等待時間讓人抓狂。不知道大家是如何加速spring應用除錯速度的,在此分享下我的一次加速過程。歡迎補充指正。

環境

配置:

 

未優化前spring容器啟動速度:

16890毫秒 =(14609毫秒(ContextLoaderListener載入的)+2281毫秒(Springmvc載入的)

優化後spring容器啟動速度:

7797毫秒 =(6563毫秒(ContextLoaderListener載入的)+1234毫秒(Springmvc載入的)

速度提升了一半多,而且以後在除錯階段,大部分就停留在這個時間左右。

注意:此處只是spring容器啟動速度,不包括伺服器啟動時的速度。因為我的系統好久沒清理了,否則可能速度會更快。

 

加速Spring

1、掃描註解Bean

寫比較精確的掃描路徑,如掃描@Service和@Repository:

這樣寫,比直接寫com.sishuok.es速度要快很多,因為這樣掃描的class會很少。

還有,如springmvc 掃描:

此處只掃描專案的web.controller包,這樣掃描的class也很少。

還有如事務的掃描:

還有如使用spring data jpa時也是這樣:

這裡需要大家有良好的分包,否則無法優化。

 

2、延遲載入你的bean

常見的方式是在配置檔案中在<beans>上加:

 

2.1、這種方式只對xml宣告的bean有效;

2.2、註解掃描的bean無效,如@Service,需要使用@Lazy指定,但這樣太麻煩,需要一個一個的配置;

2.3、還有就是如果你使用springmvc,lazy-init幾乎沒啥用,因為springmvc容器在啟動時會通過DefaultAnnotationHandlerMapping查詢相關的帶有@RequestMapping的bean並註冊請求對映;所以相關的如Service/Repository也級聯非lazy-init;

因此我寫了個工具:SpeedUpSpringProcessor,其作用是:lazy-init所有bean,包括註解的bean;對於【2.3】後續介紹解決方案;具體配置請參考最後。

 

3、移除除錯階段不相干的bean

有些bean在除錯階段我們並不需要,如我們在測試使用者模組時,可能不需要測試許可權模組;此時我們可以把不相干的bean移除掉;具體配置請參考最後。

這樣的話,可以考慮如把@Controller的bean移除,這樣的話如Service/Repository就可以lazy-init了。

常見的可以移除的如:

任務排程器(quartz)、AOP相關等等;

此處需要合理的分包,否則無法應用或應用困難。

 

4、刪除無用屬性

如在測試shiro時,可能不需要remember的功能,此時可以把屬性移除/禁用(即將值設定為false);具體配置請參考最後。

 

5、替換正式機資料來源為最快的資料來源

如此處我把DruidDataSource資料來源直接替換為org.springframework.jdbc.datasource.DriverManagerDataSource,這個速度最快;

 

6、替換jackson為fastjson

此處測試了下jackson速度比fastjson慢許多的。支援國產。

 

7、專案分模組開發 

如果專案模組比較多,可以考慮放棄註解,而使用xml配置方式+約定。

因為實際做專案時可能把配置分到多個配置檔案,此時我嘗試了下合併到一個,幾乎沒啥速度提升,所以還是分開存好。

到此spring容器啟動速度算是比較快了,不知道大家還有沒有好的策略。歡迎指點。

 

加速Hibernate/JPA

此處以org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean為例。

1、 精確化packagesToScan

和之前的spring一樣,寫比較精確的實體掃描路徑

 

2、generateDdl=false 禁用掉

沒必要每次都生成ddl

 

3、 禁用JSR-303驗證

預設情況下是AUTO,會根據classpath下是否有jsr-303實現來自動註冊;

 

此處validator 直接引用我們專案中定義的,而不是讓hibernate再去new一個。而且也不推薦在這驗證,具體為什麼,請參考我的《我是這樣認識註解和XML的》。

 

4、如果你的專案都是註解,此時就沒必要掃描hbm了,禁用掉

 

5、如果你不使用NamedQuery,禁用掉

 

6、在除錯階段禁用掉二級快取

通過如上手段,我的spring容器啟動速度提升了一半多。大家還有好的優化策略嗎?如果有歡迎補充。具體配置請參考最後。

之前提到的SpeedUpSpringProcessor配置

1、預設所有bean lazy-init;

2、removedClassPatterns:正規表示式,即可以移除的bean的class路徑模式,bean class匹配該模式的將移除;此處需要良好的分包,否則不好應用;

3、removedBeanNames:即在除錯期間可以移除的bean;

4、removeOrReplaceBeanProperties:除錯期間可以刪除/替換掉的bean屬性;

如移除shiro的sessionManager的cacheManager;

如禁用hibernate二級快取:entityManagerFactory#jpaPropertyMap#hibernate.cache.use_second_level_cache=false

5、noneLazyBeanNames:有些bean不能lazy-init;排除掉。

具體實現請參考:

可以直接下載使用。

SpeedUpSpringProcessor:

https://github.com/zhangkaitao/es/blob/master/common/src/main/java/com/sishuok/es/common/spring/SpeedUpSpringProcessor.java

spring-speed-up.xml:

https://github.com/zhangkaitao/es/blob/master/web/src/main/resources/spring-speed-up.xml

其他提到的配置檔案都在:

https://github.com/zhangkaitao/es/tree/master/web/src/main/resources

開啟/關閉:

此處我使用了spring的profile:

即只有當System.getProperties中有spring.profiles.active=developement才執行除錯模式,所以如果沒有該配置還是走的正常流程,對系統沒有影響,所以此處大家可以使用:

1、jetty內嵌執行時設定該屬性

2、寫多個bat檔案分別執行不同的情況。

 

相關文章