`

解决Spring定时计划任务重复执行两次(实例被构造两次)问题的方法

阅读更多

http://blog.csdn.net/chaijunkun/article/details/6925889

 

计划任务确实是差不多每隔3秒钟被调度的,但是每次调度执行了任务方法两次。设想一下,这仅仅是个开销很小的例子,但是如果这个方法执行的是一个非常耗时耗资源的任务,好不容易执行完一次后又要执行一次,这是对计算资源的极大浪费。于是查找了一天的原因,最后在国外的一个论坛上找到了解决的办法(http://forum.springsource.org/showthread.php?33311-IoC-Container-initializes-my-app-twice)。

 

楼主roncox和我遇到了同样的问题,他和我的配置差不多,同样也贴出了配置文件。虽然其他人没有解决问题,但是他自己解决了,并提供了最后的解决方法:

 

解决办法就是将web.xml配置文件中的如下节点删掉:

[html]view plaincopy
 
  1. <listener>
  2. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  3. </listener>
  4. <context-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>/WEB-INF/classes/applicationContext*.xml</param-value>
  7. </context-param>


修改之后程序运行一切正常。个人推测,由于org.springframework.web.context.ContextLoaderListener和org.springframework.web.servlet.DispatcherServlet都能够加载applicationContext*.xml(“*”是通配符,表示所有以“applicationContext”开头的xml文件)。而两个类殊途同归,最终都将这些配置文件交给了Spring框架的Ioc容器进行实例化。因此每个类都会被实例化两次。

 

2012年1月10日补充:今天做项目自习研究了一下spring的配置文件,发现之前说的不完全正确,不应该删除web.xml中的如下节点

 

[html]view plaincopy
 
  1. <listener>
  2. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  3. </listener>
  4. <context-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>/WEB-INF/classes/applicationContext*.xml</param-value>
  7. </context-param>


因为该节点指派的applicationContext*.xml是用于实例化除servlet之外的所有对象的,可以说项目中绝大多数的service和dao层操作都由ContextLoaderListener传递给Spring来进行实例化。

 

在web应用中,web.xml还经常出现如下的配置:

 

[html]view plaincopy
 
  1. <!--全局Servlet调度配置-->
  2. <servlet>
  3. <!--若设置servlet-name为[name]-->
  4. <!--则DispatcherServlet在实例化后会自动加载[name]-servlet.xml-->
  5. <servlet-name>spring</servlet-name>
  6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  7. <init-param>
  8. <param-name>contextConfigLocation</param-name>
  9. <param-value>classpath:servletContext.xml</param-value>
  10. </init-param>
  11. <!--随服务器一同启动-->
  12. <load-on-startup>1</load-on-startup>
  13. </servlet>
  14. <servlet-mapping>
  15. <servlet-name>spring</servlet-name>
  16. <url-pattern>*.do</url-pattern>
  17. </servlet-mapping>

这个是用来处理所有servlet的,没有它就无法通过请求地址来调用相应的Controller。
这里我明确地指示了要加载类路径下的servletContext.xml,如果不指定,则会按照注释中所描述地那样自动加载spring-servlet.xml
无论是servletContext.xml还是applicationContext*.xml都可以按照<beans>...<bean id="XXX" class="XXX" />...</beans>这样的形式来配置。
问题来了,有时候不注重对象初始化的分类,尤其是使用<context:component-scan base-package="controller" />这样的包扫描形式统一初始化,
很容易造成满足条件的对象被初始化两次,那么在计划任务的时候被执行两次也就不奇怪了。其实说来说去,还是要提醒大家,不同的配置文件其作用是不一样的,
不要将所有的初始化操作都放到一个配置文件中,更不要重复配置。不仅浪费资源,还很容易导致莫名其妙的故障。

 

 

另外,有相关文章还提到过是Tomcat服务器的问题,修改conf目录下的server.xml。修改节点Host,将appBase属性由默认的“webapps”设置为空("")即可,如下所示:

[html]view plaincopy
 
  1. <Hostname="localhost"appBase=""unpackWARs="true"autoDeploy="true"
  2. xmlValidation="false"xmlNamespaceAware="false">
  3. <ContextdocBase="/usr/local/apache-tomcat-6.0.29/webapps/semwinner"
  4. path=""reloadable="true"></Context>
  5. <ContextdocBase="/usr/local/apache-tomcat-6.0.29/webapps/emarboxmanager"
  6. path="/admin"reloadable="true"></Context>
  7. </Host>

但是本人尝试之后并没有起作用。可能不适用于我遇到的这个问题。写出上面解决方法的作者认为web应用程序默认都是放在webapps这个目录下的,如果不把“webapps“去掉,这里会调用一次quartz的任务调度,在接下来的“<Context path”中又会调用一次quartz的任务调度,所以就重复了2次。两个方法都写出来,供朋友们参考。

第二种解决方法来自http://nkliuliu.iteye.com/blog/816335

 

分享到:
评论

相关推荐

    Spring3.2.6定时任务+线程池.docx

    本文将基于Spring3.2.6版本,详细介绍如何配置线程池以及定时任务,并结合具体实例进行解析。 #### 二、Spring线程池配置 Spring框架提供了一个强大的任务调度模块,其中包含了对线程池的支持。下面通过一个具体的...

    java_Timer定时器实例_Spring实例

    后者则确保任务每隔固定时间间隔执行一次,即使上一次任务执行超时。 #### Timer示例代码分析 在提供的代码片段中,`TimerListen`类实现了`ServletContextListener`接口,这意味着它会在Web应用启动和关闭时被调用...

    定时器demo

    【定时器Demo】是一个基于Java实现的简单定时任务示例,它主要展示了如何利用Java的定时器类(java.util.Timer)或定时任务框架(如Quartz、Spring Scheduler)来执行周期性的任务。在这个demo中,开发者可能创建了...

    Java定时器.pdf

    3. 使用`Timer`的`schedule()`或`scheduleAtFixedRate()`方法来安排任务执行,根据需求选择一次性执行或周期性执行。 4. 如果需要更复杂的计划策略,可以自己实现日历算法,或者使用第三方库。 总的来说,Java...

    Timer定时器代码.zip

    在Java编程语言中,`Timer`和`TimerTask`是两个关键类,它们共同用于实现定时任务和计划程序。在大型企业级应用如Spring、Struts2和Mybatis的组合框架下,`Timer`和`TimerTask`可以发挥重要作用,比如进行后台数据...

    spring源码解析

    1. **Bean的创建与初始化**:在Spring中,Bean的实例化主要由DefaultListableBeanFactory类完成,通过构造函数或工厂方法。Bean的初始化涉及BeanPostProcessor接口,其中的postProcessBeforeInitialization和...

    Java 实现实时监听文件夹是否有新文件增加并上传服务器功能

    在Java中实现实时监听文件夹是否有新文件增加并上传服务器的功能主要涉及到使用Java NIO包中的WatchService接口,以及利用Timer定时任务执行的机制。本文将通过实例代码展示如何结合这两种技术来达到上述功能,并将...

    JAVA程序员面试问题

    而实现Runnable接口,则需要在实现类中定义run()方法,然后将其实例传递给Thread构造函数,以创建线程。两种方式各有优缺点,继承Thread类可以直接访问线程的一些内置属性和方法,但Java不支持多重继承;而实现...

    Java工程师面试宝典

    - **初始化**:执行类构造器 `()` 方法。 ##### 3.2 对象的创建过程 - **内存分配**:为新对象分配内存空间。 - **初始化零值**:将分配的内存空间初始化为零值。 - **设置对象头**:标记对象所属的类元数据信息。...

    传智播客视频JavaSE学习笔记

    Java中`String`类提供了多种构造函数,包括基于字符数组、`char`值、其他字符串实例等创建字符串的方法。其中最常见的构造函数为`String(String original)`,用于复制一个已存在的字符串。 #### 二、String常用方法...

    黑马面试宝典知识点复习

    - **监控**:可以使用Quartz提供的API来监控任务执行状态。 #### MQ(消息队列) - **RabbitMQ**: - **定义**:一种消息中间件。 - **优点**:高可用性、支持多种语言、易于集成。 - **Exchange**:交换器,...

    Java Cache详解及简单实现

    为了解决这个问题,提出了两种可能的解决方案: - **使用CacheManagerController**:尝试在`CacheManagerController`中集中管理所有缓存Controller,但这里的问题是`CacheManagerController`在构造时,其他缓存...

    SSH框架网上商城项目第15战之线程、定时器同步首页数据

    它可以一次性或周期性地执行任务。构造函数`Timer(boolean isDaemon)`中的`isDaemon` 参数决定了相关线程是否作为守护线程运行。如果设置为`true`,线程将在主程序结束时自动结束;若为`false`,即使主程序结束,...

    2023一线互联网大厂Java面试题集

    - 类实例化时,会先执行父类的静态初始化块,然后是父类的构造函数,接着是本类的静态初始化块,再是本类的构造函数,最后是成员变量的初始化。 5. **SQL优化**: - SQL优化包括选择合适的索引,避免全表扫描,...

    Java面试宝典2018

    - 如何保证一个类只被加载一次? #### 4. Web技术 - **知识点概述**: - 基础的HTTP协议及其工作原理。 - Servlet的工作机制及生命周期。 - JSP页面的执行流程。 - AJAX的工作原理及其优缺点。 - **常见面试...

    Java 面试资料 进阶版

    - **依赖注入(DI)**: 一种编程实现,通过构造函数、setter方法或字段注入等方式将一个对象所依赖的对象注入到该对象中。 - **面向切面编程(AOP)**: 提供了一种将横切关注点模块化的方法,使得应用程序业务逻辑各部分...

    JAVA核心知识点整理(有效)

    2.2.3. 本地方法区(线程私有) ................................................................................................................ 23 2.2.4. 堆(Heap-线程共享)-运行时数据区 .....................

Global site tag (gtag.js) - Google Analytics