You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring @Scheduled注解方法(cron:0 */5 * * * *)执行两次问题求助

解决@Scheduled定时任务执行两次的问题

你找的方向完全没错——这个问题确实大概率是Spring上下文重复加载导致的。结合你给出的web.xml配置,咱们来拆解一下问题根源和解决办法:

首先得明确,Spring Web应用默认会存在两个上下文:

  • 根上下文:由ContextLoaderListener加载,对应你web.xml里<context-param>指定的mvc-config.xml
  • Servlet上下文:由DispatcherServlet加载,如果没单独指定contextConfigLocation,它会默认去加载/WEB-INF/dispatcherServlet-servlet.xml

如果这两个上下文的配置文件里,重复扫描了带有@Scheduled注解的类,或者都启用了任务调度功能(比如xml里的<task:annotation-driven>或者注解的@EnableScheduling),就会导致同一个定时任务被初始化两次,自然就会执行两次。

具体解决方案:

  • 拆分配置职责,避免重复扫描
    把根上下文和Servlet上下文的配置职责明确分开:

    • 根上下文(建议把mvc-config.xml改名为applicationContext.xml更清晰)负责加载业务层、数据层的Bean,比如service、dao包,并且在这里启用任务调度:
      <context:component-scan base-package="com.yourpackage.service, com.yourpackage.dao" />
      <task:annotation-driven /> <!-- 在这里开启定时任务支持 -->
      
    • Servlet上下文(比如dispatcherServlet-servlet.xml)只负责加载Web层的Bean,比如controller包,不要在这里启用任务调度:
      <context:component-scan base-package="com.yourpackage.controller" />
      <!-- 不要加<task:annotation-driven>,避免重复初始化调度器 -->
      
  • 检查web.xml配置,杜绝重复加载同一配置
    确认你的DispatcherServlet配置里没有指定和根上下文相同的contextConfigLocation,比如不要出现这样的错误配置:

    <servlet>
      <servlet-name>dispatcherServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-config.xml</param-value> <!-- 这会导致和根上下文重复加载同一个配置 -->
      </init-param>
    </servlet>
    
  • 确认定时任务类的扫描范围
    确保带有@Scheduled注解的类只被根上下文扫描到,不要让Servlet上下文也扫描到它所在的包。

按照这个思路调整配置后,定时任务应该就只会执行一次了。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:22:07