Подтвердить что ты не робот

Как условно включить или отключить запланированные задания в Spring?

Spring я определяю запланированные задания с помощью шаблонов стилей cron, используя аннотацию @Scheduled.

Шаблон cron хранится в файле свойств конфигурации. На самом деле есть два файла свойств: один конфиг по умолчанию и один конфиг профиля, который зависит от среды (например, dev, test, prod customer 1, prod customer 2 и т.д.) И переопределяет некоторые из значений по умолчанию.

Я сконфигурировал компонент-заполнитель свойства в моем весеннем контексте, который позволяет мне использовать заполнители стиля ${} для импорта значений из моих файлов свойств.

Работа bean выглядит следующим образом:

@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {
        //Do something
            //can use DAO or other autowired beans here
    }
}

Соответствующие части моего контекста XML:

<!-- Enable configuration of scheduled tasks via annotations -->
    <task:annotation-driven/>

<!-- Load configuration files and allow '${}' style placeholders -->
    <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:config/default-config.properties</value>
                <value>classpath:config/environment-config.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="ignoreResourceNotFound" value="false"/>
    </bean>

Мне действительно это нравится. Это довольно просто и чисто с минимальным XML.

Однако у меня есть еще одно требование: в некоторых случаях некоторые из этих заданий могут быть полностью отключены.

Итак, прежде чем я использовал Spring для управления ими, я создал их вручную, и в конфигурационных файлах есть логический параметр вместе с параметром cron, чтобы указать, должно ли задание быть включено или нет:

jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?

Как я могу использовать этот параметр в Spring для условного создания или просто игнорирования компонента в зависимости от этого параметра конфигурации?

Один очевидный обходной путь - определить шаблон cron, который никогда не будет оцениваться, поэтому задание никогда не выполняется. Но bean-компонент все равно будет создан, а конфигурация будет немного неясной, поэтому я считаю, что должно быть лучшее решение.

4b9b3361

Ответ 1

@Component
public class ImagesPurgeJob implements Job {

    private Logger logger = Logger.getLogger(this.getClass());

    @Value("${jobs.mediafiles.imagesPurgeJob.enable}")
    private boolean imagesPurgeJobEnable;

    @Override
    @Transactional(readOnly=true)
    @Scheduled(cron = "${jobs.mediafiles.imagesPurgeJob.schedule}")
    public void execute() {

         //Do something
        //can use DAO or other autowired beans here
        if(imagesPurgeJobEnable){

            Do your conditional job here...

        }
    }
}

Ответ 2

Spring Boot обеспечивает @ConditionalOnProperty, который был бы идеальным, если бы вы использовали Spring Boot. Эта аннотация является специализацией @Conditional, представленной с Spring 4.0.0.

Предполагая, что вы просто используете "обычный" Spring, а не Spring Boot, вы можете создать собственную реализацию условия для использования с @Conditional, которая будет имитировать Spring Boot @ConditionalOnProperty.

Ответ 3

Вы можете группировать методы расписания по условиям в число сервисов и инициализировать их следующим образом:

@Service
@ConditionalOnProperty("yourConditionPropery")
public class SchedulingService {

@Scheduled
public void task1() {...}

@Scheduled
public void task2() {...}

}

Ответ 4

Если вы хотите переключить @EnableScheduling из свойства, вы можете сделать это в Spring Boot, переместив аннотацию @EnableScheduling в класс конфигурации и используя @ConditionalOnProperty следующим образом:

@Configuration
@EnableScheduling
@ConditionalOnProperty(prefix = "com.example.scheduling", name="enabled", havingValue="true", matchIfMissing = true)
public class SchedulingConfiguration {

}

Это отключит планирование для приложения. Это может быть полезно в ситуации, когда вы хотите иметь возможность запускать приложение один раз или по расписанию в зависимости от того, как оно запускается.

От Уилкинсона комментарий здесь: https://github.com/spring-projects/spring-boot/issues/12682

Ответ 6

@Component
public class CurrencySyncServiceImpl implements CurrencySyncService {

    private static Boolean isEnableSync;
    /**
     * Currency Sync FixedDelay in minutes
     */
    private static Integer fixedDelay;

    @Transactional
    @Override
    @Scheduled(fixedDelayString = "#{${currency.sync.fixedDelay}*60*1000}")
    public void sync() {
        if(CurrencySyncServiceImpl.isEnableSync) {
            //Do something
            //you can use DAO or other autowired beans here.
        }
    }

    @Value("${currency.sync.fixedDelay}")
    public void setFixedDelay(Integer fixedDelay) {
        CurrencySyncServiceImpl.fixedDelay = fixedDelay;
    }

    @Value("${currency.sync.isEnable}")
    public void setIsEnableSync(Boolean isEnableSync) {
        CurrencySyncServiceImpl.isEnableSync = isEnableSync;
    }
}

Ответ 7

Самый эффективный способ отключить @Scheduled spring. Просто установите выражение кроны как "-". Это отключит @Scheduled.

@Scheduled(cron = "-")
public void autoEvictAllCache() {
    LOGGER.info("Refresing the Cache Start :: " + new Date());
    activeMQUtility.sendToTopicCacheEviction("ALL");
    LOGGER.info("Refresing the Cache Complete :: " + new Date());
}

Для получения дополнительной информации:

enter image description here

Ответ 9

Вы также можете создать Бин на основе условия, и у Бина может быть запланированный метод.

@Component
@Configuration
@EnableScheduling
public class CustomCronComponent {
    @Bean
    @ConditionalOnProperty(value = "my.cron.enabled", matchIfMissing = true, havingValue = "true")
    public MyCronTask runMyCronTask() {
        return new MyCronTask();
    }
}

и

@Component
public class MyCronTask {
    @Scheduled(cron = "${my.cron.expression}")
    public void run() {
        String a = "";
    }
}