Spring Boot:如何参数化@Scheduled

5
我刚接触Spring,只了解了它的表面功能。 我遇到了这样一个情况:我需要使用@Scheduled注释设置一个重复任务。 频率是作为一个成员字段在传递给封装任务方法的类中的对象中指定的。 我已经使用了访问配置或环境的机制,例如 @Scheduled(fixedRateString = "$ {some.property:default}"),这很好用。但我不知道如何在@Scheduled中插入来自一个对象的值。 例如:
class MyClass {
  private MyObject myObj;

  public MyClass(MyObject myObj) {
    this.myObj = myObj;
  }

  @Scheduled(fixedRateString = "${myObj.rate:5000}")
  private void someTask() {
    ...
  }
}

当然,上面的代码并不能运行,我只是举例说明我想要做什么。

如果您有任何建议,将不胜感激。


2
我认为你不能使用注释来做这件事。你需要以编程的方式来完成,而不是声明式的方式。 - Matt Ball
你能提供(或指向)如何做到这一点的示例吗? - Joseph Gagnon
使用@ConfigurationProperties,您可以将属性存储在对象中,并可以使用SpEL访问它们。 - IEE1394
4个回答

7

是的,你可以使用@Scheduled注解和SpEL表达式来实现这个功能(自Spring 4.3.x版本起,@Scheduled注解已经支持SpEL表达式)。下面是一个例子:

@Slf4j
@Configuration
@EnableScheduling
public class ExampleClass {

  static class ScheduleCalculator {
    public String calc() {
      return "5000";
    }
  }

  @Bean("scheduleCalculator")
  public ScheduleCalculator createScheduleCalculator() {
    return new ScheduleCalculator();
  }

  @Scheduled(fixedRateString = "#{scheduleCalculator.calc()}")
  public void someTask() {
    log.info("Hello world");
  }
}

然而,仅仅因为你可以这样做,并不意味着你一定应该这样做。
如果你使用spring task scheduler,你的代码可能更容易被未来维护者理解,并且你可以控制用于调度的线程池,而不是依赖于所有@Scheduled任务都被归并到的共享执行器。

5

很不幸,Spring bean创建过程不会读取局部变量。

您可以使用Spring TaskScheduler类。

基本上,您只需定义一个线程池(作为bean)来运行计划任务,并使用taskScheduler.schedule(runnable, new CronTrigger("* * * * *"))运行计划任务。这里有一个详细的例子:

https://www.baeldung.com/spring-task-scheduler


2
您可以按照以下方式操作:

最初的回答:

@Component
@ConfigurationProperties(prefix = "my.obj")
public class MyObject {

    private String cronExecExpr = "*/5 * * * * *";

    // getter and setter
}
class MyClass {
  private MyObject myObj;

  public MyClass(MyObject myObj) {
    this.myObj = myObj;
  }

  @Scheduled(cron = "${my.obj.cron-exec-expr:*/5 * * * * *}")
  private void someTask() {
    ...
  }
}

2

我可以看到这里:https://www.baeldung.com/spring-scheduled-tasks

你可以像下面这样做:

一个fixedDelay任务:

@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")

一个fixedRate任务:
@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")

一个基于Cron表达式的任务:
@Scheduled(cron = "${cron.expression}")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接