programing

봄에 스케줄된 작업을 조건부로 활성화 또는 비활성화하려면 어떻게 해야 합니까?

goodjava 2022. 11. 5. 17:46

봄에 스케줄된 작업을 조건부로 활성화 또는 비활성화하려면 어떻게 해야 합니까?

을 cron으로 .@Scheduled석입니니다다

cron 패턴은 설정 속성 파일에 저장됩니다.실제로는 2개의 속성 파일이 있습니다.하나는 디폴트 설정이고 다른 하나는 환경 의존적인 프로파일 설정(dev, test, prod customer 1, prod customer 2 등)으로 기본값 중 일부를 덮어씁니다.

했습니다.에 의해, 「」을 할 수 .★★★★★★★★★★★★★★★★,${}스타일 플레이스 홀더를 사용하여 내 속성 파일에서 값을 가져옵니다.

작업 콩은 다음과 같습니다.

@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에서 이 파라미터를 사용하여 조건부로 bean을 작성하거나 단순히 무시하려면 어떻게 해야 합니까?

분명한 회피책 중 하나는 평가하지 않는 cron 패턴을 정의하여 작업이 실행되지 않도록 하는 것입니다.하지만 콩은 여전히 생성되고 구성이 불분명하기 때문에 더 나은 해결책이 있을 것 같습니다.

「」를 디세블로 인 방법.@Scheduled cron으로 합니다.-

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

문서에서:

CRON_DISABLED

String public static CRON_DISABLED
사용할 수 없는 트리거를 나타내는 특별한 cron 식 값:-. 이것은 주로 ${...플레이스하는 스케줄된 메서드를 할 수 .} 자자표 표표표표자 。 해당 스케줄링된 메서드를 외부에서 사용하지 않도록 설정할 수 있습니다.

5.1 이후 항목:Scheduled Task Registrar.CRON_DISABLED

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

        }
    }
}

조건별 스케줄 방식을 서비스 수로 그룹화하여 다음과 같이 시작할 수 있습니다.

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

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

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

}

Spring Boot에는 @Conditional On Property가 준비되어 있어 Spring Boot을 사용하는 경우 매우 적합합니다.이 주석은 스프링 4.0.0에서 도입된 @Conditional의 전문화입니다.

Spring Boot이 아닌 "일반" Spring을 사용하는 경우 Spring Boot의 @ConditionalOnProperty를 모방한 @Conditional과 함께 사용하는 자체 Conditional 구현을 작성할 수 있습니다.

속성에서 @EnableScheduling을 전환하려면 Spring Boot에서 @EnableScheduling 주석을 설정 클래스로 이동하고 다음과 같이 @ConditionalOnProperty를 사용합니다.

@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

당신의 질문은 실제 콩의 생성을 조건으로 하는 것입니다.이 파라미터는 스프링 3.1 이상을 사용하는 경우 @Profile을 사용하면 쉽게 실행할 수 있습니다.

다음 문서를 참조하십시오.http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/Profile.html

조건에 따라 Bean을 작성할 수도 있고 Bean이 Scheduled 메서드를 가질 수도 있습니다.

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

제 답변은 다른 질문으로 봐주세요.이게 가장 좋은 해결 방법인 것 같아요.@Scheduled 주석을 사용하여 시작된 스케줄링된 작업을 중지하려면 어떻게 해야 합니까?

다음과 같이 사용자 지정 주석을 정의합니다.

@Documented
@Retention (RUNTIME)
@Target(ElementType.TYPE)
public @interface ScheduledSwitch {
    // do nothing
}

클래스 구현 org.springframework.scheduling.annotation을 정의합니다.Scheduled Annotation Bean Post Processor.

public class ScheduledAnnotationBeanPostProcessorCustom 
    extends ScheduledAnnotationBeanPostProcessor {

    @Value(value = "${prevent.scheduled.tasks:false}")
    private boolean preventScheduledTasks;

    private Map<Object, String> beans = new HashMap<>();

    private final ReentrantLock lock = new ReentrantLock(true);

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        ScheduledSwitch switch = AopProxyUtils.ultimateTargetClass(bean)
            .getAnnotation(ScheduledSwitch.class);
        if (null != switch) {
            beans.put(bean, beanName);
            if (preventScheduledTasks) {
                return bean;
            }
        }
        return super.postProcessAfterInitialization(bean, beanName);
    }

    public void stop() {
        lock.lock();
        try {
            for (Map.Entry<Object, String> entry : beans.entrySet()) {
                postProcessBeforeDestruction(entry.getKey(), entry.getValue());
            }
        } finally {
            lock.unlock();
        }
    }

    public void start() {
        lock.lock();
        try {
            for (Map.Entry<Object, String> entry : beans.entrySet()) {
                if (!requiresDestruction(entry.getKey())) {
                    super.postProcessAfterInitialization(
                        entry.getKey(), entry.getValue());
                }
            }
        } finally {
            lock.unlock();
        }
    }

}

구성에서 ScheduledAnnotationBeanPostProcessor bean을 사용자 지정 bean으로 바꿉니다.

@Configuration
public class ScheduledConfig {

    @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationBeanPostProcessor() {
        return new ScheduledAnnotationBeanPostProcessorCustom();
    }

}

@Scheduled 작업을 방지하거나 중지할 콩에 @ScheduledSwitch 주석을 추가합니다.

내 답변이 해킹인 것은 알지만 실행하지 않는 유효한 cron 식을 지정하면 (환경 고유의 구성에서) 문제가 해결될 수 있습니다. Quartz: 실행하지 않는 Cron 식

예약된 메서드를 가진 클래스의 빈 생성을 비활성화할 수 있습니다.@Conditional주석입니다.이것은 와 매우 유사합니다.@ConditionalOnProperty스프링 콘텍스트에 맞춰 콩을 조건부로 회전시킬 때 사용합니다.값을 다음과 같이 설정하면false그러면 콩은 회전하지 않고 스프링으로 옮겨진다.코드는 다음과 같습니다.

application.properties:

    com.boot.enable.scheduling=enable

상태:

public class ConditionalBeans implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return "enabled".equalsIgnoreCase(context.getEnvironment().getProperty("com.boot.enable.scheduling"));
    }
}

나의 스케줄 클래스

@Service
@Conditional(ConditionalSchedules.class)
public class PrintPeriodicallyService {

    @Scheduled(fixedRate = 3000)
    public void runEvery3Seconds() {
        System.out.println("Current time : " + new Date().getTime());
    }
}

이 접근방식은 조건 발생이 완전히 우리의 통제 하에 있을 때 많은 유연성을 가지고 있습니다.

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