加速Java應用開發速度1——加速spring/hibernate應用調試時啓動速度

環境

配置:html

thinkpad t410java

內存:4G內存git

CPU:Intel P8700 雙核2.53GHZgithub

系統:WIN XPweb

開發工具:Intellij IDEA 12.0.4正則表達式

Maven + spring3.2.3 + hibernate4.2.2+Spring data jpa 1.3.1spring

未優化前spring容器啓動速度:json

16890毫秒 =(14609毫秒(ContextLoaderListener加載的)+2281毫秒(Springmvc加載的)spring-mvc

 

優化後spring容器啓動速度:緩存

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

 

速度提高了一半多,並且之後在調試階段,大部分就停留在這個時間左右。

 

注意:此處只是spring容器啓動速度,不包括服務器啓動時的速度。由於個人系統很久沒清理了,不然可能速度會更快。

加速Spring

一、掃描註解Bean

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

<context:component-scan base-package="com.sishuok.es.**.repository,com.sishuok.es.**.service,com.sishuok.es.**.extra">

這樣寫,比直接寫com.sishuok.es速度要快不少,由於這樣掃描的class會不多。

 

還有,如springmvc 掃描:

<context:component-scan base-package="com.sishuok.es.**.web.controller" use-default-filters="false">

此處只掃描項目的web.controller包,這樣掃描的class也不多。

還有如事務的掃描:

execution(* com.sishuok.es..service..*+.*(..)

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

<jpa:repositories base-package="com.sishuok.es.**.repository"

這裏須要你們有良好的分包,不然沒法優化。

二、延遲加載你的bean

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

default-lazy-init="true"

2.一、這種方式可能對如任務調度等沒有依賴的狀況形成影響;

2.二、在正式機環境仍是非lazy bean的好,這樣能夠在啓動時發現一些可能存在的問題;

2.二、還有就是若是你使用springmvc,lazy-init幾乎沒啥用,由於springmvc容器在啓動時會經過DefaultAnnotationHandlerMapping查找相關的帶有@RequestMapping的bean並註冊請求映射;因此相關的如Service/Repository也級聯非lazy-init;

所以我寫了個工具:SpeedUpSpringProcessor,其做用是:在調試時lazy-init全部bean;具體配置請參考最後。

三、移除調試階段不相干的bean

有些bean在調試階段咱們並不須要,如咱們在測試用戶模塊時,可能不須要測試權限模塊;此時咱們能夠把不相干的bean移除掉;具體配置請參考最後。

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

常見的能夠移除的如:

任務調度器(quartz)、AOP相關等等;

 

此處須要合理的分包,不然沒法應用或應用困難。

四、刪除無用屬性

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

五、替換正式機數據源爲最快的數據源

如此處我把DruidDataSource數據源直接替換爲org.springframework.jdbc.datasource.DriverManagerDataSource,這個速度最快;

六、替換jackson爲fastjson

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

七、項目分模塊開發 

若是項目模塊比較多,能夠考慮放棄註解,而使用xml配置方式+約定。

 

由於實際作項目時可能把配置分到多個配置文件,此時我嘗試了下合併到一個,幾乎沒啥速度提高,因此仍是分開存好。

 

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

加速Hibernate/JPA

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

一、 精確化packagesToScan

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

<property name="packagesToScan" value="com.sishuok.es.**.entity"/>

二、generateDdl=false 禁用掉

不必每次都生成ddl

三、 禁用JSR-303驗證

默認狀況下是AUTO,會根據classpath下是否有jsr-303實現來自動註冊

<!-- 使用自定義的validator進行jsr303驗證 -->
<entry key="javax.persistence.validation.factory" value-ref="validator"/>
<!-- jsr303驗證模式 由於其要麼驗證 要麼不驗證 不能按照規則走 因此此處禁用 -->
<!-- #http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html -->
<entry key="javax.persistence.validation.mode" value="NONE"/>

此處validator 直接引用咱們項目中定義的,而不是讓hibernate再去new一個。並且也不推薦在這驗證,具體爲何,請參考個人《我是這樣認識註解和XML的》。

四、若是你的項目都是註解,此時就不必掃描hbm了,禁用掉

<entry key="hibernate.archive.autodetection" value="class"/>

五、若是你不使用NamedQuery,禁用掉

<entry key="hibernate.query.startup_check" value="false"/>

六、在調試階段禁用掉二級緩存

經過如上手段,個人spring容器啓動速度提高了一半多。你們還有好的優化策略嗎?若是有歡迎補充。具體配置請參考最後。

以前提到的SpeedUpSpringProcessor配置

    <!-- 優化spring啓動 經過移除bean定義 和 lazy init 實現 -->
    <bean class="com.sishuok.es.common.spring.SpeedUpSpringProcessor">
        <!-- 須要從bean定義中移除的bean的名字 -->
        <property name="removedBeanNames">
            <list>
                <!-- spring-config-quartz.xml -->
                <value>scheduler</value>
                <value>autoClearDeletedRelationTrigger</value>
                <value>autoClearExpiredOrDeletedmMessageTrigger</value>
                <value>autoClearDeletedRelationJob</value>
                <value>autoClearExpiredOrDeletedmMessageJob</value>

                <!-- spring-config-shiro.xml -->
                <value>rememberMeCookie</value>
                <value>rememberMeManager</value>
                <value>shiroCacheManager</value>
                <value>sessionValidationScheduler</value>
                <value>sessionValidationScheduler</value>
                <!-- spring-mvc.xml -->
                <value>multipartResolver</value>

                <!-- spring-config-monitor.xml -->
                <value>druidStatInterceptor</value>
                <value>druidAdvisor</value>
            </list>
        </property>
        <!-- 須要從bean定義中移除的bean的屬性 -->
        <!--替換掉的屬性值 see removedBeanProperties 只支持簡單屬性-->
        <property name="removeOrReplaceBeanProperties">
            <list>
                <!-- spring-config-shiro.xml -->
                <value>sessionManager#cacheManager</value>
                <value>sessionManager#cacheManager</value>
                <value>sessionManager#sessionValidationScheduler</value>
                <value>securityManager#rememberMeManager</value>

                <!-- spring-config.xml -->
                <value>entityManagerFactory#jpaPropertyMap#hibernate.default_batch_fetch_size"</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.max_fetch_depth"</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.generate_statistics</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.bytecode.use_reflection_optimizer</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.cache.use_second_level_cache=false</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.cache.use_query_cache</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.cache.region.factory_class</value>
                <value>entityManagerFactory#jpaPropertyMap#hibernate.cache.use_structured_entries</value>
                <value>entityManagerFactory#jpaPropertyMap#net.sf.ehcache.configurationResourceName</value>
            </list>
        </property>

        <!-- 須要從bean定義中移除指定的類類型 正則表達式-->
        <property name="removedClassPatterns">
            <list>
                 <value>com\.sishuok\.es\.showcase.*</value>
                 <value>com\.sishuok\.es\.monitor.*</value>
                 <value>com\.sishuok\.es\.extra\.aop.*</value>
                 <value>com\.sishuok\.es\.extra\.quartz.*</value>
                 <value>com\.sishuok\.es\.conf.*</value>
                 <!--<value>com\.sishuok\.es\.personal.*\.web\.controller.*</value>-->
                 <!--<value>com\.sishuok\.es\.sys.*\.web\.controller.*</value>-->
            </list>
        </property>

        <!-- 指定非延遲加載的bean-->
        <property name="noneLazyBeanNames">
            <list>
                <value>domainClassConverter</value>
            </list>
        </property>
    </bean>

一、默認全部bean lazy-init;

二、removedClassPatterns:正則表達式,便可以移除的bean的class路徑模式,bean class匹配該模式的將移除;此處須要良好的分包,不然很差應用;

三、removedBeanNames:即在調試期間能夠移除的bean;

四、removeOrReplaceBeanProperties:調試期間能夠刪除/替換掉的bean屬性;

    如移除shiro的sessionManager的cacheManager;

    如禁用hibernate二級緩存:entityManagerFactory#jpaPropertyMap#hibernate.cache.use_second_level_cache=false

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

具體實現請參考:

能夠直接下載使用。

SpeedUpSpringProcessor:

http://my.oschina.net/heroShane/blog/198432

spring-speed-up.xml:

http://my.oschina.net/heroShane/blog/198434

其餘提到的配置文件都在:

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

開啓/關閉: 

此處我使用了spring的profile:

<beans profile="development" >

即只有當System.getProperties中有spring.profiles.active=developement才執行調試模式,因此若是沒有該配置仍是走的正常流程,對系統沒有影響,因此此處你們可使用:

            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>${jetty.version}</version>
                <configuration>
                    ---省略
                    <!-- spring profile  -->
                    <systemProperties>
                        <systemProperty>
                            <name>spring.profiles.active</name>
                            <value>development</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </plugin>

二、寫多個bat文件分別執行不一樣的狀況。

相關文章
相關標籤/搜索