黑马程序员_加速Java应用开发1:Spring/Hibernate应用调试时启动速度

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------

加速Java应用开发1:Spring/Hibernate应用调试时启动速度

在调试spring应用时,动辄几十秒,甚至有的应用上分钟的启动速度,会让整个调试速度慢下来了。等待时间让人抓狂。不知道大家是如何加速spring应用调试速度的,在此分享下我的一次加速过程。欢迎补充指正。

环境

配置:

1
2
3
4
5
6
thinkpad t410
内存:4G内存
CPU:Intel P8700 双核2.53GHZ
系统:WIN XP
开发工具:Intellij IDEA 12.0.4
Maven + spring3.2.3 + hibernate4.2.2+Spring data jpa 1.3.1

 

未优化前spring容器启动速度:

16890毫秒 =(14609毫秒(ContextLoaderListener加载的)+2281毫秒(Springmvc加载的)

优化后spring容器启动速度:

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

速度提升了一半多,而且以后在调试阶段,大部分就停留在这个时间左右。

注意:此处只是spring容器启动速度,不包括服务器启动时的速度。因为我的系统好久没清理了,否则可能速度会更快。

 

加速Spring

1、扫描注解Bean

写比较精确的扫描路径,如扫描@Service和@Repository:

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

这样写,比直接写com.sishuok.es速度要快很多,因为这样扫描的class会很少。

还有,如springmvc 扫描:

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

此处只扫描项目的web.controller包,这样扫描的class也很少。

还有如事务的扫描:

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

还有如使用spring data jpa时也是这样:

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

这里需要大家有良好的分包,否则无法优化。

 

2、延迟加载你的bean

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

1
default-lazy-init="true"

 

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一样,写比较精确的实体扫描路径

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

 

2、generateDdl=false 禁用掉

没必要每次都生成ddl

 

3、 禁用JSR-303验证

默认情况下是AUTO,会根据classpath下是否有jsr-303实现来自动注册;

1
2
3
4
5
<!-- 使用自定义的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的》。

 

4、如果你的项目都是注解,此时就没必要扫描hbm了,禁用掉

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

 

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

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

 

6、在调试阶段禁用掉二级缓存

通过如上手段,我的spring容器启动速度提升了一半多。大家还有好的优化策略吗?如果有欢迎补充。具体配置请参考最后。

之前提到的SpeedUpSpringProcessor配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!-- 优化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 >

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:

1
< beans profile = "development" >

即只有当System.getProperties中有spring.profiles.active=developement才执行调试模式,所以如果没有该配置还是走的正常流程,对系统没有影响,所以此处大家可以使用:

1、jetty内嵌执行时设置该属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< 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 >

2、写多个bat文件分别执行不同的情况。

----------------------- android培训java培训、java学习型技术博客、期待与您交流! ----------------------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值