Java Spring @Scheduled任务执行两次
我在这里有一个简单的测试方法,设置为每5秒运行一次,但是看看System.out,你可以看到它似乎在做一些奇怪的事情。
@Scheduled(cron="*/5 * * * * ?") public void testScheduledMethod() { System.out.println(new Date()+" > Running testScheduledMethod..."); }
输出:
Wed Jan 09 16:49:15 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:15 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:20 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:20 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:25 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:25 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:30 GMT 2013 > Running testScheduledMethod... Wed Jan 09 16:49:30 GMT 2013 > Running testScheduledMethod...
为什么每次都运行TWICE (出现) ?
如果你查看文档,就会有一个明确指出这种现象的说明。
该说明在此链接的第25.5.1节下,并写着:
确保您没有在运行时初始化同一@Scheduled注释类的多个实例,除非您确实要为每个此类实例安排回调。 与此相关,请确保不对使用@Scheduled注释的bean类使用@Configurable,并将其注册为带有容器的常规Spring bean:否则将获得双初始化,一次通过容器,一次通过@Configurable方面,每个@Scheduled方法的结果被调用两次。
我知道这只是目前的建议,但我认为我们没有足够的信息来进一步诊断问题。
我知道答案!!
不要初始化您的预定两次
在你的网络日志中抢夺:
WebApplicationContext
一次和servlet一次
所以在你的servlet.xml
不要这样做
import resource="classpath:applicationContext.xml"
它是由于上下文监听器而发生的
只需删除
<听众>
listener>
从web.xml它应该工作。
我遇到过类似的问题。 可能是由于以下原因。
-
春季版本中的错误https://jira.spring.io/browse/SPR-10830
-
上下文被加载两次。
-
log4j.xml两次写日志。 它发生在我的情况下,不确定你的。 如果您已尝试过其他选项,请尝试使用此选项。
我遇到了类似的问题,我解决了这个问题:
package com.sample.config; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; @Configuration @EnableScheduling public class JobExecutorConfig { }
作为弹簧靴的配置。 我将其添加为jobclass:
package com.sample.jobs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class Job { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired MyOtherClass moc; @Scheduled(fixedRate = 60000) // every 60 seconds public void doJob() { log.debug("Job running !!!"); try { moc.doSomething() } catch (Exception e) { log.error(e.getMessage()); } finally { log.debug("job Done !!!"); } } // examples of other CRON expressions // * "0 0 * * * *" = the top of every hour of every day. // * "*/10 * * * * *" = every ten seconds. // * "0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day. // * "0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day. // * "0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays // * "0 0 0 25 12 ?" = every Christmas Day at midnight }
我有同样的问题,我最终发现问题是由于在root context
创建bean以及servlet context
。
因此,要解决此问题,您需要将bean的创建分离到适当的上下文中。
这个答案真的很好地解释了如何解释我的问题。
我有同样的问题。 花了好几个小时试图解决。
解决方案是应用程序在Tomcat上部署了两次。
在尝试清理Tomcat时,它出错了。
检查server.xml Tomcat文件我注意到它被部署了两次。 还有一个未公开的“主机”标签。 不知道这些中的哪一个修复了它,但让它再次正常工作而松了一口气。
我使用的是Spring 4.0.3,我遇到了这个问题。 我通过重命名我的豆来解决它。
至:
我注意到一些INFO日志记录说没有找到名为taskScheduler的bean,创建了一个新实例。 所以我认为有两个taskScheduler实例。
让我知道这是否也适合你:)
在我的情况下,作业的bean有@Component注释,我在applicationContext.xml中有这个:
所以解决方案是删除bean定义(第二行),因为:
:允许在任何Spring管理的对象上检测@Async和@Scheduled注释,因此不需要定义作业的bean或者它将被调用两次。
根据这篇文章和Spring Jira,这是Spring Framework Scheduler组件中的一个错误。
如果您的应用程序是WEB,则可能需要检查是否在两个不同的上下文中扫描同一包的组件,例如applicationContext.xml,然后再检查some-servlet.xml。
contextConfigLocation /WEB-INF/spring/root-context.xml /WEB-INF/spring/security/spring-security.xml /WEB-INF/spring/mongo/mongo-config.xml /WEB-INF/spring/appServlet/spring-context.xml appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/spring/appServlet/spring-context.xml 1
那是我的web.xml。 因此,您可以看到“/WEB-INF/spring/appServlet/spring-context.xml”被加载两次(一次在context-param中,一次在servlet中 – > init-param)。
我遇到了同样的情况并通过这个解决了:
1)调度服务
@Service public class SchedulerService { @Autowired @Qualifier("WorkerClass") private Worker worker; @Scheduled(cron="0/5 * * * * ?", zone="Asia/Colombo")//zone is a sample public void doSchedule() { worker.work(); } }
2)工人阶级
@Component("WorkerClass") public class WorkerClass implements Worker { @Override public void work() { doSomething(); } protected void doSomething() { system.out.pringln("What must I do?"); } }
我今天遇到了同样的问题。
在我的项目中,我使用调度程序和我的Spring启动应用程序,在我的ScheduledTaks类中,我正在使用@Component注释。 但我犯了一个错误,因为@Component代表我的类的bean,而在我的Application类中,我使用代码为这个类创建了另一个bean:
public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } @Bean public ScheduledTasks getScheduledTasks() { return new ScheduledTasks(); } }
我只是删除了这个注释,并且调度程序可以正常工作。
按照我的代码ScheduledTasks类的示例:
public class ScheduledTasks { private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); @Scheduled(cron = "00 14 11 * * *") public void reportCurrentTime() { log.info("The date is: {} " + dateFormat.format(new Date()) ); } }
结果如下:
2016-10-20 11:13:41.298 INFO 6832 --- [ main] sbcetTomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2016-10-20 11:13:41.302 INFO 6832 --- [ main] br.com.Application : Started Application in 9.257 seconds (JVM running for 9.676) 2016-10-20 11:14:00.002 INFO 6832 --- [pool-2-thread-1] br.com.scheduler.ScheduledTasks : The date is: {} 11:14:00
我确实有同样的问题,查看我的代码,在尝试了所有这些之后,我确实发现我在2个不同的类中有两次SpringApplicationBuilder
在application.properties中,添加以下属性,该属性告诉Spring Boot Application在应用程序启动时不启动批处理作业。
spring.batch.job.enabled=false
我有同样的问题。 我使用基于注释的配置如下:
@Configuration @EnableScheduling public class SchedulerConfig { @Scheduled(fixedDelay = 60 * 1000) public void scheduledJob() { // this method gets called twice... } }
我还扩展了AbstractAnnotationConfigDispatcherServletInitializer来初始化它。
public class SpringWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class>[] getRootConfigClasses() { return new Class>[] { MainConfig.class, SchedulerConfig.class }; } @Override protected Class>[] getServletConfigClasses() { return new Class>[] {SpringWebConfig.class}; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected Filter[] getServletFilters() { final CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); encodingFilter.setEncoding(CHARACTER_ENCODING); encodingFilter.setForceEncoding(true); return new Filter[] { encodingFilter }; }
}
从getRootConfigClasses()
方法中删除SchedulerConfig.class
对我来说getRootConfigClasses()
。
@Override protected Class>[] getRootConfigClasses() { return new Class>[] { MainConfig.class }; }
我希望这有帮助。