Java Spring Задачи, выполняемые в два раза:
У меня есть простой метод тестирования здесь, который запускается каждые 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 (появляется) каждый раз?
Ответы
Ответ 1
Если вы посмотрите на документацию, есть заметка, которая явно вызывает это явление.
Примечание находится в разделе в разделе 25.5.1 по этой ссылке и читается:
Убедитесь, что вы не инициализируете несколько экземпляров одного и того же класса аннотаций @Scheduled во время выполнения, если вы не хотите планировать обратные вызовы для каждого такого экземпляра. В связи с этим убедитесь, что вы не используете @Configurable в классах bean, которые аннотируются с помощью @Scheduled и зарегистрированы как обычные Spring beans с контейнером: вы получили бы двойную инициализацию в противном случае, один раз через контейнер и один раз через @Configurable аспект, вследствие того, что каждый метод @Scheduled вызывается дважды.
Я понимаю, что это просто предложение на данный момент, но я не думаю, что у нас достаточно информации, чтобы еще больше диагностировать проблему.
Ответ 2
Я знаю ответ!
Не запускайте дважды запланированный
Loot в вашем веб-журнале:
WebApplicationContext
один раз и один сервлет
поэтому в servlet.xml
не делайте этого
import resource="classpath:applicationContext.xml"
Ответ 3
это происходит из-за прослушивания контекста
Просто удалите
< слушатель >
< listener-class > org.springframework.web.context.ContextLoaderListener </listener-class >
</прослушиватель >
из web.xml он должен работать.
Ответ 4
Я столкнулся с подобной проблемой. Это может быть из-за причин.
-
Ошибка в версиях spring
https://jira.spring.io/browse/SPR-10830
-
Контекст загружается дважды.
-
Журнал log4j.xml записывает журналы дважды. Это случилось в моем случае, не уверенном в твоем. Если вы попробовали другие параметры, попробуйте также это.
Ответ 5
Я объявил свой класс как "Сервис", а также использовал аннотацию @Scheduled, чтобы объявить его планировщиком. Планировщик вызывает его нормально, но так как мы объявили класс как сервис. Это было начато дважды.
Я удалил Сервисную аннотацию. И объявил этот класс как bean-компонент в контексте XML, который я поддерживал. (пользовательский контекст XML, который объявлен в web.xml). Это исправило проблему для меня. Надеюсь, это кому-нибудь поможет.
Ответ 6
У меня была такая же проблема, и в итоге я выяснил, что проблема возникла в результате создания beans в root context
, а также servlet context
.
Итак, чтобы исправить это, вам нужно отделить создание beans в соответствующих контекстах.
Этот ответ очень хорошо объясняет, как это и было исправлено мою проблему.
Ответ 7
У меня была аналогичная проблема, я решил, что сделал это:
package com.sample.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class JobExecutorConfig {
}
в качестве конфигурации для загрузки spring. И я добавляю это как класс работы:
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
}
Ответ 8
Я использую spring 4.0.3, и у меня есть эта проблема. я решил это, переименовав мой beans.
в
<task:annotation-driven executor="taskExecutor"
scheduler="taskScheduler" />
<task:executor id="taskExecutor" pool-size="25" />
<task:scheduler id="taskScheduler" pool-size="25" />
Я заметил некоторые записи INFO, в которых говорилось, что no bean с именем taskScheduler найдено, создавая новый экземпляр. Поэтому я решил, что есть два экземпляра taskScheduler.
Сообщите мне, если это сработает для вас:)
Ответ 9
В моем случае у задания bean была аннотация @Component, и у меня это было в моем приложении ApplicationContext.xml:
<task:annotation-driven/>
<bean id="getxxx" class="com.kitar.xxxx.jobs.RomeExample"></bean>
Итак, решение состоит в том, чтобы удалить определение bean (вторая строка), потому что:
<task:annotation-driven/>
: разрешить обнаружение @Async и @Scheduled аннотаций на любом объекте Spring, поэтому нет необходимости определять задание bean или он будет вызываться дважды.
Ответ 10
Согласно этот пост и Spring Jira это ошибка в компоненте Spring Framework Scheduler.
Ответ 11
Возможно, вы захотите проверить, сканируете ли вы компоненты для одного и того же пакета в двух разных контекстах, если ваше приложение является WEB, например. applicationContext.xml, а затем снова some-servlet.xml.
Ответ 12
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/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
</param-value>
</context-param>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/spring-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Это мой web.xml. Итак, вы можете видеть, что "/WEB-INF/ spring/appServlet/spring-context.xml" загружается дважды (один раз в контексте-param, один раз в сервлет → init-param).
Ответ 13
Я столкнулся с такой же ситуацией и решил:
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?");
}
}
Ответ 14
У меня была та же проблема. Проработанные часы пытаются решить.
Решение Решение было распространено дважды на Tomcat.
При попытке очистить Tomcat он дал ошибку.
Проверка файла server.xml Tomcat Я заметил, что то же самое развертывалось дважды. Был также закрытый тег "хозяин". Не уверен, какой из них исправил его, но с облегчением он снова работал правильно.
Ответ 15
У меня была такая же проблема, глядя в моем коде, и после попытки всего, что здесь, я обнаружил, что у меня был SpringApplicationBuilder дважды в 2 различных классах
Ответ 16
У меня такая же проблема. Я использовал конфигурацию на основе аннотаций следующим образом:
@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 };
}
}
Удаление SchedulerConfig.class
из getRootConfigClasses()
мне.
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { MainConfig.class };
}
Надеюсь, это поможет.
Ответ 17
Следование этому руководству решило проблему для меня. Проблема была в моем web.xml. https://www.mkyong.com/spring-mvc/spring-mvc-beans-loaded-twice/
Ответ 18
У меня была такая же проблема, я попробовал все предложенные методы, но у меня ничего не получалось. Наконец, я смог найти решение, удалив расширение SpringBootServletInitializer и метод configure моего класса WebApplication, и с этим я перестал дублировать свою запланированную задачу.
Ответ 19
Сегодня у меня была такая же проблема.
В моем проекте я использовал планировщик с моим приложением загрузки 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 class:
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] s.b.c.e.t.TomcatEmbeddedServletContainer : 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
Ответ 20
В application.properties добавьте следующее свойство, которое сообщает приложению Spring Boot не запускать пакетное задание при запуске приложения.
spring.batch.job.enabled=false
Ответ 21
Была такая же проблема.
В моем случае я переместил свои функции @Scheduled из @Service в новый отдельный класс с аннотацией @Component, и это решило мою проблему