【问题标题】:ScheduledExecutorService problem with Autowired service自动装配服务的 ScheduledExecutorService 问题
【发布时间】:2020-02-22 17:38:18
【问题描述】:

我正在尝试让ScheduledExecutor 服务每天在特定时间运行MyTask。我遇到的问题是该任务使用@Service 组件,如果我在没有@Component 的情况下执行@Autowire,则该服务将无法工作,如果我将@Component 放在MyTask 上,则无论组件如何都首先运行Scheduler 在哪里。

我尝试通过构造函数和@DependsOn 发送服务,但没有成功。

@Component
public class MyRunnable implements Runnable {

@Autowired
private Service service;

@Override
public void run() {

    //some code

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    scheduler.scheduleAtFixedRate(new MyTask(),
        initalDelay,
        TimeUnit.DAYS.toSeconds(1),
        TimeUnit.SECONDS);


}}

如果@Component 放在这里,首先运行

 public class MyTask extends TimerTask {

    @Autowired
    private Service service;
 }

【问题讨论】:

  • 我不太明白你的问题。 Service 有什么问题?
  • 为什么不使用 spring 中的 @Schedule 注释?
  • @AlexR 它在 MyTask 中不起作用
  • @Deadpool 我想在特定时间运行任务,比如凌晨 5 点,动态初始延迟。
  • 你想每天早上 5 点运行任务吗?这个with dynamical initial delay@M8765 是什么意思,请问您想在什么时间和哪一天运行任务?

标签: java spring autowired scheduledexecutorservice


【解决方案1】:

将任务定义为

公共类 MyTask 扩展 TimerTask {

private final DataSetService dataSetService

public MyTask(DataSetService dataSetService) {
 this.dataSetService = dataSetService;
}

// Your other code here

}

和你的 MyRunnable 为

@Component 
public class MyScheduler {

@Autowired
private final DataSetService dataSetService

private final ScheduledExecutorService scheduler =
        Executors.newScheduledThreadPool(1);

@PostConstruct
public void startScheduler() {
    scheduler.scheduleAtFixedRate(new MyTask(dataSetService),
        initalDelay,
        TimeUnit.DAYS.toSeconds(1),
        TimeUnit.SECONDS);
} 

如您所见,MyRunnable(现在更名为 MyScheduler)不再实现不必要的 Runnable,它是一个 Spring bean,实例化后 PostConstruct 启动调度程序。

【讨论】:

  • 我写过我试过了,如果我打印它,即使它确实识别出服务价值,它也不起作用。
  • 抱歉,我注意到另一件事,为什么将 MyRunnable 创建为组件?通过这种方式,您强制 Spring 将 MyRunnable 实例化为 bean。因此,从 MyRunnable 中删除 Component 会强制您拥有第三个类,这个带有 Component 的类,具有必要的 Autowired,然后实例化 ScheduledExecutorService。另一种选择是使用 [Quartz] (quartz-scheduler.org)
  • 它必须是一个组件,它还有我没有显示的其他代码。
  • 同样,问题不在于调度程序,而在于服务无法正常工作。
  • 我编辑了回复以捕捉您的笔记。我希望它现在更有意义
【解决方案2】:

你让事情变得比必要的更复杂。 Spring 可以为您处理调度,这将使 autowaring 工作。无需指定所有样板。

基本上放弃MyRunnable,不要在MyTask 中扩展TimerTask。将您的MyTask 注释为@Component 并在您要执行的方法上打一个@Scheduled。 (因为您最初扩展了 TimerTask 可能是 run 方法)。

@Component
public class MyTask {

    @Autowired
    private Service service;

    @Scheduled(cron = "0 0 5 * * *")
    public void run() { ... } 
 }

如果你真的想保持复杂性,你可以做两件事。将 @Component 注释添加到 MyTask 并将其注入到 MyRunnable 中,在调度中使用该引用。或者您可以删除@Autowired,创建字段final 并创建一个构造函数,该构造函数采用Service 依赖项并在构造函数中进行设置。

但是我强烈建议使用更简单的 @Scheduled,如果您需要初始延迟,请将计算放入单独的 bean 中并使用 SpEL 表达式来获取 initialDelay

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-02
    • 2018-08-05
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多