配置: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容器启动速度,不包括服务器启动时的速度。由于个人系统很久没清理了,不然可能速度会更快。
一、扫描注解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容器启动速度算是比较快了,不知道你们还有没有好的策略。欢迎指点。
此处以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文件分别执行不一样的状况。