Programing

Spring에서 예약 된 작업을 조건부로 활성화 또는 비활성화하는 방법은 무엇입니까?

lottogame 2020. 12. 12. 09:58
반응형

Spring에서 예약 된 작업을 조건부로 활성화 또는 비활성화하는 방법은 무엇입니까?


@Scheduled주석을 사용하여 Spring에서 cron 스타일 패턴으로 예약 된 작업을 정의하고 있습니다.

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 에서이 매개 변수를 사용하여 조건부로 빈을 생성하거나 무시할 수 있습니까?

한 가지 확실한 해결 방법은 절대 평가되지 않는 크론 패턴을 정의하여 작업이 실행되지 않도록하는 것입니다. 그러나 빈은 여전히 ​​생성되고 구성은 약간 모호하므로 더 나은 솔루션이 있어야한다고 생각합니다.


@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...

        }
    }
}

Spring Boot는 @ConditionalOnProperty를 제공 하는데 , 이는 Spring Boot를 사용한다면 완벽 할 것입니다. 이 주석은 Spring 4.0.0에 도입 된 @Conditional 의 전문화입니다 .

Spring Boot가 아닌 "일반"스프링을 사용한다고 가정하면 Spring Boot의 @ConditionalOnProperty를 모방하는 @Conditional과 함께 사용할 자신의 Condition 구현을 만들 수 있습니다.


일정 방법을 조건별로 서비스 수로 그룹화하고 다음과 같이 초기화 할 수 있습니다.

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

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

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

}

속성에서 @EnableScheduling을 토글하려는 경우 @EnableScheduling 주석을 구성 클래스로 이동하고 다음과 같이 @ConditionalOnProperty를 사용하여 Spring Boot에서이를 수행 할 수 있습니다.

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

}

이렇게하면 응용 프로그램에 대한 예약이 비활성화됩니다. 이 기능은 응용 프로그램을 한 번만 실행하거나 시작 방법에 따라 예약 할 수있는 상황에서 유용 할 수 있습니다.

wilkinsona의 의견에서 : https://github.com/spring-projects/spring-boot/issues/12682


Your question states to condition the actual creation of the bean. You can do this easily with this parameter by using @Profile if you are using at least Spring 3.1.

See the documentation here: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html


@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;
    }
}

The most efficient way to disable @Scheduled in Spring. Just set crone expression like "-". It will disable the @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());
}

For more info:

enter image description here


I know my answer is a hack, but giving a valid cron expression that never executes may fix the issue (in the environment specific configuration), Quartz: Cron expression that will never execute


You can also create a Bean based on condition and that Bean can have a Scheduled method.

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

and

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

참고URL : https://stackoverflow.com/questions/18406713/how-to-conditionally-enable-or-disable-scheduled-jobs-in-spring

반응형