В настоящее время я сталкиваюсь с проблемой при использовании аннотации @Scheduled (cron) весной.
@Scheduled(cron = "0 0 3 * * MON-FRI", zone = "Europe/Berlin")
Эта задача выполняется каждый день в 3 часа ночи (понедельник-пятница):
Мой вопрос: почему эта задача выполняется дважды? Я заявил, что он должен работать только в минуту «0» и «0» секунд, но это кажется неправильным (см. время выполнения). У меня есть две такие задачи, и у обеих есть эта проблема. Кто-нибудь может знать причину, почему это происходит и как этого избежать?
Я использую версию Spring Boot 2.1.6
. Примечание: скоро будет обновление до версии 2.7
.
Редактировать:
Мой класс планировщика:
@Component
@RequiredArgsConstructor
@Log4j2
public class LdapTask {
private final IAppUserService appUserService;
private final IEmployeeService employeeService;
//second, minute, hour, day of month, month, day(s) of week
@Scheduled(cron = "0 0 3 * * MON-FRI", zone = "Europe/Berlin")
public void blockAppUsers() {
/* Logic here */
}
@Scheduled(cron = "0 20 3 * * MON-FRI")
public void checkEmailAddresses() {
/* Logic here */
}
}
Приложение (запись для этого приложения):
@SpringBootApplication(exclude = MultipartAutoConfiguration.class)
@EntityScan(basePackages = "...")
@EnableScheduling
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Ответ на мою проблему:
Я заменил переопределенный метод configure
из SpringBootServletInitializer
body на это:
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class, LdapTask.class);
}
вместо:
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
и удаление аннотации @Component
в классе LdapTask
.
Как намекнул ответ на этот пост, Spring фактически создавал два экземпляра ApplicationContext, которые дважды выполняли этот метод.
Да, я проверял несколько раз. Эти два метода «blockAppUsers()» и «checkEmailAddresses» вызываются не мной, а только Spring через аннотацию.
Внимательно проверяйте журналы при инициализации приложения.
Скорее всего, ваш планировщик был инициализирован дважды.
Одна из причин может быть связана с SpringBootServletInitializer
— он может инициализировать bean-компоненты один раз для контекста WebApplicationContext и еще раз для контекста сервлета.
P.S. чтобы дать вам решение, мне понадобится доступ ко всему коду src, так как это может быть даже дополнительная стартовая зависимость в pom
Странно, что они бегают один за другим. Вы уверены, что ваш метод не вызывает себя в каком-то случае?