@Scheduled
アノテーションを使用して、Springでcronスタイルパターンでスケジュールジョブを定義しています。
Cronパターンは、構成プロパティファイルに保存されます。実際には、2つのプロパティファイルがあります。1つはデフォルトの構成、もう1つは環境に依存するプロファイル構成(例: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
}
}
コンテキスト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で非常にシンプルでクリーンです。
ただし、もう1つ要件があります。これらのジョブの一部は、場合によっては完全に無効にすることができます。
したがって、Springを使用してそれらを管理する前に、手動で作成し、設定ファイルにcronパラメータとともにブールパラメータがあり、ジョブを有効にする必要があるかどうかを指定します:
jobs.mediafiles.imagesPurgeJob.enable=true or false
jobs.mediafiles.imagesPurgeJob.schedule=0 0 0/12 * * ?
この設定パラメータに応じて、Springでこのパラメータを使用して条件付きでBeanを作成するか、Beanを単に無視するにはどうすればよいですか?
明らかな回避策の1つは、評価されないcronパターンを定義して、ジョブが実行されないようにすることです。しかし、Beanはまだ作成され、構成は少し不明瞭になるため、より良い解決策が必要だと感じています。
@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で使用する独自の条件実装を作成できます。
条件ごとにスケジュールメソッドをいくつかのサービスにグループ化し、次のように初期化できます。
@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 {
}
これにより、アプリケーションのスケジューリングが無効になります。これは、アプリケーションの起動方法に応じて、アプリケーションを1回またはスケジュールして実行できるようにする場合に役立ちます。
ここに関するウィルキンソナのコメントから: https://github.com/spring-projects/spring-boot/issues/12682
あなたの質問は、Beanの実際の作成を調整することを示しています。少なくとも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;
}
}
条件に基づいて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 = "";
}
}
私の答えはハックであることは知っていますが、実行されない有効なcron式を指定すると、(環境固有の構成で)問題が解決する場合があります Quartz:実行されないCron式