Spring 调度:@Controller 注释的 class 中的方法上的 @Scheduled 注释运行两次

Spring Scheduling: @Scheduled annotation on a method inside a class annotated with @Controller runs twice

考虑以下代码片段:

@Controller
public class RestController {

    @Scheduled(cron = "0 0 */* * * ?") // run every hour
    public void runMeHourly() {
        LOGGER.debug("RestController#runMeHourly triggered to run at: " + System.currentTimeMillis());

        // Do your hourly work here
    }


}

当我在 J2EE Web 服务器中部署此控制器时,我发现 RestController#runMeHourly() 方法每小时触发两次。

我在 spring docs scheduling 上找到了对类似内容的引用。

它说:

Make sure that you are not initializing multiple instances of the same @Scheduled annotation class at runtime, unless you do want to schedule callbacks to each such instance. Related to this, make sure that you do not use @Configurable on bean classes which are annotated with @Scheduled and registered as regular Spring beans with the container: You would get double initialization otherwise, once through the container and once through the @Configurable aspect, with the consequence of each @Scheduled method being invoked twice.

这有关系吗?这是否意味着我需要从 RestController 外部安排方法 runMeHourly()

[编辑 1:看起来 @Configurable 是其他东西,并没有导致问题,我没有在任何地方使用过它。所以一定有其他原因导致这种行为]

[编辑 2:

我的web.xml:

<web-app>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
     </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>com.company.module.ModuleContextListener</listener-class>
    </listener>

</web.xml>

mvc-调度程序-servlet.xml

<beans>

    <mvc:annotation-driven />

    <task:annotation-driven />

    <context:component-scan base-package="com.company" />

    <import resource="module/module-servlet.xml"/>

</beans>

module/module-servlet.xml

<beans>

    <context:component-scan base-package="com.company.module"/>

</beans>

]

com.company.module.ModuleContextListener 迫使 DispatcherServlet 寻找根应用程序上下文,并且由于根应用程序上下文与 mvc-dispatcher-servlet.xml 相同,因此它被加载了两次。一次作为根上下文,一次在 DispatcherServlet 下,名称为 mvc-dispatcher.

将根上下文 xml mvc-dispatcher-servlet.xml 重命名为 applicationContext.xml 并添加一个空的 mvc-dispatcher-servlet.xml 解决了问题。

感谢@6ton 指出这一点。