一、@RefreshScope导致定时任务失效
当定时任务使用@RefreshScope想达到配置动态刷新时,你会发现定定时任务失效了,失效的原因和@RefreshScope的原理有关:配置的刷新会导致原来的对象被清除,需要重新使用对象才能出发生成新对象,但因为对象没了,又没法重新使用对象(死循环),所以导致了定时任务的失效。(这样描述是否恰当)
二、定时任务的动态刷新实现方式
1. @RefreshScope+RefreshScopeRefreshedEvent
RefreshScopeRefreshedEvent刷新作用域刷新事件
1.1 简单写法
@RefreshScope
@Component
public class TestTask implements ApplicationListener<RefreshScopeRefreshedEvent> {
@Value("${test.num}")
private String num;
@Scheduled(cron = "* * * * * *")
// @Scheduled(cron = "${test.cron}")// 可实现定时任务执行时间的动态刷新
public void schedule() {
System.out.println("============ 定时任务执行了,num["+num+"] ============");
}
@Override
public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
}
}
1.2复杂写法
public interface RefreshScheduler {
default void materializeAfterRefresh() {
}
}
@Component
public class RefreshScopeListener implements ApplicationListener<RefreshScopeRefreshedEvent> {
private final List<RefreshScheduler> refreshSchedulers;
public RefreshScopeListener(List<RefreshScheduler> refreshSchedulers) {
this.refreshSchedulers = refreshSchedulers;
}
@Override
public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
refreshSchedulers.forEach(RefreshScheduler::materializeAfterRefresh);
}
}
@Component
@RefreshScope
public class TestTask implements RefreshScheduler{
@Value("${test.num}")
private String num;
@Scheduled(cron = "${test.cron}")
public void schedule() {
System.out.println("============ 定时任务执行了,当前时间["+ DateUtil.formatDateTime(new Date()) +"] ==== num["+num+"] ============");
}
}
2. Environment
@Component
public class TestTask {
@Autowired
private Environment env;
@Scheduled(cron = "* * * * * *")
public void schedule() {
String num = env.getProperty("test.num");
System.out.println("============ 定时任务执行了,num["+num+"] ============");
}
}
3. @RefreshScope+@Value
@RefreshScope
@Component
public class TestConfig {
@Value("${test.num}")
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
@Component
public class TestTask {
@Autowired
private TestConfig testConfig;
@Scheduled(cron = "* * * * * *")
public void schedule() {
System.out.println("============ 定时任务执行了,num["+testConfig.getUrl()+"] ============");
}
}
4. @ConfigurationProperties
@Component
@ConfigurationProperties(prefix = "test")
public class TestConfig {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
@Component
public class TestTask {
@Autowired
private TestConfig testConfig;
@Scheduled(cron = "* * * * * *")
public void schedule() {
System.out.println("============ 定时任务执行了,num["+testConfig.getUrl()+"] ============");
}
}
5. EnvironmentChangeEvent
EnvironmentChangeEvent环境变化事件
public interface RefreshScheduler {
default void materializeAfterRefresh() {
}
}
@Component
@RefreshScope
public class TestTask implements ApplicationListener<EnvironmentChangeEvent>,RefreshScheduler {
@Value("${test.num}")
private String num;
@Scheduled(cron = "${test.cron}")
public void schedule() {
System.out.println("============ 定时任务执行了,当前时间["+ DateUtil.formatDateTime(new Date()) +"] ==== num["+num+"] ============");
}
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
this.materializeAfterRefresh();
}
}