如何在Spring中有条件地启用或禁用预定作业?
我使用@Scheduled
注释在Spring中定义了使用cron样式模板的计划作业。
cron模式存储在configuration属性文件中。 实际上,有两个属性文件:一个默认configuration和一个与环境相关的configuration文件configuration(例如dev,test,prod customer 1,prod customer 2等),并覆盖一些默认值。
我在我的spring上下文中configuration了一个属性占位符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 } }
我的上下文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来pipe理它们之前,我手动创build了它们,并且在configuration文件中还有一个布尔参数以及cron参数来指定是否启用作业:
jobs.mediafiles.imagesPurgeJob.enable=true or false jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?
如何在Spring中使用这个参数来有条件的创build或者直接忽略bean,这取决于这个configuration参数?
一个明显的解决方法是定义一个永远不会计算的cron模式,所以这个工作永远不会被执行。 但是这个bean仍然会被创build,configuration会变得模糊,所以我觉得必须有一个更好的解决scheme。
任何想法 ?
@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,而不是春季启动,你可以创build自己的条件实现与@Conditional一起使用,可以模仿Spring Boot的@ConditionalOnProperty。
您可以按照条件将调度方法分组为多个服务,并像下面这样初始化它们:
@Service @ConditionalOnProperty("yourConditionPropery") public class SchedulingService { @Scheduled public void task1() {...} @Scheduled public void task2() {...} }
你的问题说明了这个bean的实际创build。 如果您至less使用Spring 3.1,则可以使用@Profile通过此参数轻松完成此操作。
请参阅此处的文档: 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; } }