Создание нескольких объектов одного класса с различным значением аннотации @Sheduled в Spring

Рейтинг: 0Ответов: 1Опубликовано: 15.02.2023

Как динамически создавать несколько объектов одного класса с разным значением @Sheduled?

Необходимо создавать для каждого объекта А объект Б. Б имеет метод по расписанию, который использует объект А.

Как бы я хотел решить эту задачу:

@Data
public class A {
    private String text;
    private int interval;
}

класс Б:

@Data
public class B {
    private A a;

    @Scheduled(fixedRateString = a.getInterval())
    public void task(){
        System.out.println(a.getText());
    }
}

Параметры для А задаются списком в application.yml.

data:
    as:
      - text: ddd
        interval: 1
      - text: bbb
        interval: 2
      - text: aaa
        interval: 3

Объекты A создаются классом с аннотацией @ConfigurationProperties. После чего, получая все бины класса А, создаются и добавляются бины Б в контекст спринга.

Проблема этого решения в том, что для атрибута аннотации нужна константа. Ее нельзя подсунуть динамически. Мне хотелось бы иметь возможность задавать в application.yml разное количество объектов для генерации. (иначе я мог бы просто захордкодить значения для аннотации)

Ответы

▲ 2Принят

Вы можете динамически сконфигурировать шедулер создав конфигурационный бин, имплементирующий интерфейс SchedulingConfigurer. Единственный метод этого интерфейса предоставляет объект ScheduledTaskRegistrar, методы которого можно использовать для регистрации любых типов отложенных задач. Для ваших целей понадобится метод addFixedRateTask(Runnable, long):

@Data
@Configuration
@ConfigurationProperties(prefix = "data")
public class SchedulerConfiguration implements SchedulingConfigurer {

    private List<ConfData> as;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        Optional.ofNullable(as)
                .ifPresent(
                        confData -> confData.forEach(
                                data -> taskRegistrar.addFixedRateTask(
                                        new SchedulerRunnable(data.getText()),
                                        data.getInterval())
                        )
                );
    }

    @Data
    public static class ConfData {
        private String text;
        private Integer interval;
    }

    @AllArgsConstructor
    private static class SchedulerRunnable implements Runnable {

        private final String text;

        @Override
        public void run() {
            System.out.println(text);
        }
    }
}