`
jinnianshilongnian
  • 浏览: 21504374 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418721
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008857
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639521
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259943
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597361
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250234
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858982
Group-logo
跟我学Nginx+Lua开...
浏览量:702015
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785235
社区版块
存档分类
最新评论

加速Java应用开发速度1——加速spring/hibernate应用调试时启动速度

 
阅读更多

《加速Java应用开发速度》系列目录:

加速Java应用开发速度1——加速spring/hibernate应用调试时启动速度

加速Java应用开发速度2——加速项目调试启动速度

加速Java应用开发速度3——单元/集成测试+CI

加速Java应用开发速度4——使用模板技术加速项目开发速度

加速Java应用开发速度5——使用脚本自动化日常操作 

 

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

 

环境

配置:

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:

 

<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"

 

 

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

 

2、延迟加载你的bean

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

default-lazy-init="true"

2.1、这种方式可能对如任务调度等没有依赖的情况造成影响;

2.2、在正式机环境还是非lazy bean的好,这样可以在启动时发现一些可能存在的问题;

2.2、还有就是如果你使用springmvc,lazy-init几乎没啥用,因为springmvc容器在启动时会通过DefaultAnnotationHandlerMapping查找相关的带有@RequestMapping的bean并注册请求映射;所以相关的如Service/Repository也级联非lazy-init;

 

因此我写了个工具:SpeedUpSpringProcessor,其作用是:在调试时lazy-init所有bean;具体配置请参考最后。

 

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

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

  

2、generateDdl=false 禁用掉

没必要每次都生成ddl

 

3、 禁用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的》。

 

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

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

   

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

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

 

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

  

 

通过如上手段,我的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>

 

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:

<beans profile="development" >

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

 

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

            <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文件分别执行不同的情况。

 

  • 大小: 22.1 KB
27
3
分享到:
评论
34 楼 g_man1990 2017-04-04  
此处测试了下jackson速度比fastjson慢许多的
真的么?我怎么感觉jackson快很多
33 楼 chenghong 2016-06-23  
[/img][/img]
32 楼 chenghong 2016-06-23  
tomcat6.0.37  jdk1.6.0_45   没有问题   tomcat7.0.57 我用jdk6和jdk7和jdk8都是卡住不动
31 楼 429537044 2016-05-16  
Ydoing 写道
yimiaotk8801 写道
天涯陌路 写道
A208JASON 写道
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.

我也是,怎么办呢

我也是这样,求大神指教啊!


我也是这样的!

我等了15分钟,最后起来了,不过里面的东西出问题了, 列表刷不出来
30 楼 a285090024 2016-03-19  
herosam 写道
请教个问题,我本机eclipse运行ec-web时,jetty跑得,但每次到spring 初始化是就卡死,也不报错,一直停在那没反映。。。



JDK必须使用1.6。项目启动正常。
29 楼 herosam 2015-10-30  
请教个问题,我本机eclipse运行ec-web时,jetty跑得,但每次到spring 初始化是就卡死,也不报错,一直停在那没反映。。。
28 楼 Ydoing 2015-08-12  
es启动卡住了,不知道怎么解决?
信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
八月 12, 2015 2:20:27 下午 org.apache.catalina.core.ApplicationContext log
信息: No Spring WebApplicationInitializer types detected on classpath
八月 12, 2015 2:20:27 下午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring root WebApplicationContext
八月 12, 2015 2:20:31 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.bean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, taskdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_start8_4_ from maintain_task_definition taskdefini0_ where 1=1
八月 12, 2015 2:22:49 下午 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring FrameworkServlet 'spring'
27 楼 Ydoing 2015-08-12  
yimiaotk8801 写道
天涯陌路 写道
A208JASON 写道
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.

我也是,怎么办呢

我也是这样,求大神指教啊!


我也是这样的!
26 楼 yimiaotk8801 2015-03-19  
天涯陌路 写道
A208JASON 写道
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.

我也是,怎么办呢

我也是这样,求大神指教啊!
25 楼 天涯陌路 2015-02-01  
A208JASON 写道
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.

我也是,怎么办呢
24 楼 jianfu.zhang 2015-01-23  
A208JASON 写道
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.

也是遇到同样的问题,望能得到解决!
23 楼 A208JASON 2014-11-30  
楼主,我碰到一种情况,按照你文档来操作,初始化数据库等都ok,但是到执行es-web的时候,起动不了.请问是怎么回事呢?

mvn clean tomcat7:run -Dmaven.test.skip=true

最后最后一只卡在这里...

信息: Initializing Spring root WebApplicationContext
十一月 30, 2014 10:20:15 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
Hibernate: select taskdefini0_.id as id1_4_, taskdefini0_.bean_class as bean_cla2_4_, taskdefini0_.b
ean_name as bean_nam3_4_, taskdefini0_.cron as cron4_4_, taskdefini0_.description as descript5_4_, t
askdefini0_.method_name as method_n6_4_, taskdefini0_.name as name7_4_, taskdefini0_.is_start as is_
start8_4_ from maintain_task_definition taskdefini0_ where 1=1
望张大神解答下.
22 楼 jinnianshilongnian 2013-06-07  
hualiangyjb 写道
jinnianshilongnian 写道
目前知道的几个热部署的解决方案:
1、ClassLoader
2、DCEVM
3、javaagent
  开源的:spring-loaded   fakereplace
  收费的:JRebel

不知道还有其他的吗? 欢迎补充。

是啊   热部署 就是了

恩 下一篇 已经写的差不多了,
21 楼 hualiangyjb 2013-06-07  
jinnianshilongnian 写道
目前知道的几个热部署的解决方案:
1、ClassLoader
2、DCEVM
3、javaagent
  开源的:spring-loaded   fakereplace
  收费的:JRebel

不知道还有其他的吗? 欢迎补充。

是啊   热部署 就是了
20 楼 jinnianshilongnian 2013-06-07  
魔力猫咪 写道
如果真的想快就做单元测试自动化测试呀。

这个肯定要做的。如果做界面的东西,你不可能不启动服务器测试;而且单元测试也可以使用如上的策略;最常见的就是如集成测试时,ds使用内存数据库;上CI也是应该的
如果用github开发可以使用免费的https://travis-ci.org 现在使用着 挺好用   欢迎补充
19 楼 魔力猫咪 2013-06-07  
如果真的想快就做单元测试自动化测试呀。
18 楼 jinnianshilongnian 2013-06-07  
kjj 写道
楼主勤奋上进的精神值得我们学习啊,有空关注一下ssh下的多数据源jta事务方案,我现在是配置成功了,但是偶尔事务会出问题,搜了一下,大多数是配置问题,没多少人解决,希望能一起研究!!!!!!!!!

如果项目中使用jta,遇到问题肯定研究,不过没在项目中使用 单独研究估计重现不了。 或者给个例子,
17 楼 kjj 2013-06-06  
楼主勤奋上进的精神值得我们学习啊,有空关注一下ssh下的多数据源jta事务方案,我现在是配置成功了,但是偶尔事务会出问题,搜了一下,大多数是配置问题,没多少人解决,希望能一起研究!!!!!!!!!
16 楼 jinnianshilongnian 2013-06-06  
1927105 写道
jinnianshilongnian 写道
1927105 写道
JRebel靠谱些,呵呵

收费啊

在天朝还有收费这概念么?

前些日子 开源中国卖idea 还花钱买了个,
不过jrebel确实强大 对比了几个 没人能比啊
15 楼 1927105 2013-06-06  
jinnianshilongnian 写道
1927105 写道
JRebel靠谱些,呵呵

收费啊

在天朝还有收费这概念么?

相关推荐

Global site tag (gtag.js) - Google Analytics