Java

发布于 更新于

AI总结: 本文介绍了@RefreshScope在Spring中触发Bean刷新时,导致原有Bean实例被销毁并创建新实例的情况。由于ScheduledAnnotationBeanPostProcessor只在容器初始化时执行一次,新创建的Bean中的@Scheduled方法未被注册,导致定时任务失效。提供了一种解决方案,使用ApplicationListener监听RefreshScopeRefreshedEvent以解决定时任务失效的问题。 优化建议: 1. 在AlertSchedulerCron类的onApplicationEvent方法中,添加逻辑以重新注册@Scheduled任务。 2. 考虑使用Spring的TaskScheduler来动态调度任务,避免@Scheduled注解的限制。 3. 增加异常处理机制,确保在任务执行中出现错误时能够进行日志记录或告警。 4. 提供详细的文档或注释,帮助其他开发者理解如何使用该解决方案及其背后的原理。

当@RefreshScope触发Bean刷新时,原有的Bean实例被销毁,新实例被创建。 但是,ScheduledAnnotationBeanPostProcessor只在容器初始化时执行一次,不会重新扫描新创建的Bean。因此,新Bean中的@Scheduled方法未被注册,导致定时任务失效。

这里仅记录最简单的一种解决方案, 其他方式见相关链接

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@RefreshScope
public class AlertSchedulerCron implements ApplicationListener<RefreshScopeRefreshedEvent> {

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Value("${pollingtime}")
    private String pollingtime;

    /*
     * @Value("${interval}") private String interval;
     */
    @Scheduled(cron = "${pollingtime}")
    //@Scheduled(fixedRateString = "${interval}" )
    public void task() {
        System.out.println(pollingtime);
        System.out.println("Scheduler (cron expression) task with duration : " + sdf.format(new Date()));
    }

    @Override
    public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
        // TODO Auto-generated method stub

    }
}

相关链接

@RefreshScope stops @Scheduled task

@RefreshScope导致@Scheduled失效