ScheduledExecutorService проблема с автоматической проводной службой - PullRequest
1 голос
/ 26 октября 2019

Я пытаюсь сделать службу ScheduledExecutor для запуска MyTask каждый день в определенное время. У меня проблема в том, что задача использует @Service компонент, и если я делаю @Autowire без @Component, служба не будет работать, если я поставлю @Component, MyTask запускается первым, независимо от компонентагде Scheduler есть.

Я попытался отправить службу через конструктор и @DependsOn, но она не сработала.

@Component
public class MyRunnable implements Runnable {

@Autowired
private Service service;

@Override
public void run() {

    //some code

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    scheduler.scheduleAtFixedRate(new MyTask(),
        initalDelay,
        TimeUnit.DAYS.toSeconds(1),
        TimeUnit.SECONDS);


}}

, если поставить здесь @Component, это сначала выполняется

 public class MyTask extends TimerTask {

    @Autowired
    private Service service;
 }

Ответы [ 2 ]

0 голосов
/ 28 октября 2019

Вы делаете вещи более сложными, чем необходимо. Spring может обработать расписание для вас, что заставит работать autowaring. Без необходимости указывать все шаблоны.

В основном угробите MyRunnable, не расширяйте TimerTask в вашем MyTask. Аннотируйте ваш MyTask как @Component и добавьте @Scheduled к методу, который вы хотите выполнить. (Поскольку вы расширили TimerTask изначально, возможно, run метод).

@Component
public class MyTask {

    @Autowired
    private Service service;

    @Scheduled(cron = "0 0 5 * * *")
    public void run() { ... } 
 }

Если вы действительно хотите сохранить сложность, вы можете сделать 2 вещи. Добавьте аннотацию @Component к MyTask и добавьте ее в MyRunnable, используйте эту ссылку в планировании. Или вы можете удалить @Autowired, создать поле final и создать конструктор, который принимает зависимость Service и выполняет настройку в конструкторе.

Однако я настоятельно рекомендую использовать более простой @Scheduled, и если вам нужна начальная задержка, поместите это вычисление в отдельный компонент и используйте выражение SpEL, чтобы получить initialDelay.

0 голосов
/ 26 октября 2019

Определить задачу как

открытый класс MyTask extends TimerTask {

private final DataSetService dataSetService

public MyTask(DataSetService dataSetService) {
 this.dataSetService = dataSetService;
}

// Your other code here

}

и ваш MyRunnable как

@Component 
public class MyScheduler {

@Autowired
private final DataSetService dataSetService

private final ScheduledExecutorService scheduler =
        Executors.newScheduledThreadPool(1);

@PostConstruct
public void startScheduler() {
    scheduler.scheduleAtFixedRate(new MyTask(dataSetService),
        initalDelay,
        TimeUnit.DAYS.toSeconds(1),
        TimeUnit.SECONDS);
} 

Как вы можетевидите, MyRunnable (теперь переименованный в MyScheduler) больше не реализует ненужный Runnable, это - пружинный компонент, и после его создания PostConstruct запускает планировщик.

...