如何在Spring中有条件地启用或禁用预定作业?

Pie*_*nry 59 java cron spring scheduled-tasks

我使用@Scheduled注释在Spring中定义具有cron样式模式的预定作业.

cron模式存储在配置属性文件中.实际上有两个属性文件:一个默认配置,一个依赖于环境的配置文件配置(例如dev,test,prod customer 1,prod customer 2等)并覆盖一些默认值.

我在spring上下文中配置了一个属性占位符bean,它允许我使用${}样式占位符从我的属性文件中导入值.

作业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
    }
}
Run Code Online (Sandbox Code Playgroud)

我的上下文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>
Run Code Online (Sandbox Code Playgroud)

我真的很喜欢这个.使用最少的XML,它非常简单和干净.

但是我还有一个要求:在某些情况下,其中一些工作可以完全禁用.

因此,在我使用Spring管理它们之前,我手动创建它们,并在配置文件中有一个布尔参数和cron参数,以指定是否必须启用作业:

jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?
Run Code Online (Sandbox Code Playgroud)

我如何在Spring中使用此参数来有条件地创建或明显忽略bean,具体取决于此配置参数?

一个明显的解决方法是定义永远不会评估的cron模式,因此永远不会执行作业.但是仍然会创建bean并且配置会有点模糊,所以我觉得必须有更好的解决方案.

Pra*_*ran 40

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

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这是一个选项,但我宁愿不实例化bean而不是创建bean并定期执行一个方法,即使它什么都不做. (13认同)
  • 而不是"在这里做你的工作"我宁愿检查是否(!启用){return;}我认为它更清洁. (9认同)
  • 我最终像这样实现它,因为虽然不完美但它很简单.我了解了@Value注释很好. (2认同)

小智 27

Spring Boot提供@ConditionalOnProperty,如果你使用的是Spring Boot,那将是完美的.这个注释是@Conditional的一个特化,在Spring 4.0.0中引入.

假设你只是使用"常规"弹簧而不是Spring Boot,你可以创建自己的Condition实现,以便与模仿Spring Boot的@ConditionalOnProperty的@Conditional一起使用.

  • 根据`@ Conditional`文档,注释仅在方法级别上适用于以`@ Bean`注释的方法,即。Bean定义。 (4认同)
  • 理想情况下,这应该可以工作,但它不适用于我的情况与Spring Boot的1.3.2-RELEASE. (2认同)

Ole*_*leg 25

您可以按条件将计划方法分组为多个服务,并按如下方式初始化它们:

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

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

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

}
Run Code Online (Sandbox Code Playgroud)

  • 您可以将“@ConditionalOnProperty”放在单个方法上吗?或者为不同的`@Scheduled`方法指定不同的属性? (2认同)

use*_*985 6

如果您希望从属性切换@EnableScheduling,可以在Spring Boot中将@EnableScheduling注释移动到配置类并使用@ConditionalOnProperty,如下所示:

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

}
Run Code Online (Sandbox Code Playgroud)

这将禁用应用程序的计划.在您希望能够运行应用程序一次或根据其启动方式安排应用程序的情况下,这可能很有用.

来自wilkinsona的评论:https://github.com/spring-projects/spring-boot/issues/12682


小智 5

在Spring中禁用@Scheduled的最有效方法。只需将crone表达式设置为“-”即可。它将禁用@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());
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息:

在此处输入图片说明

  • 最好使用 const 而不是“-” ```java @Scheduled(cron = Scheduled.CRON_DISABLED) ``` (6认同)