简体   繁体   中英

Spring boot: How to parameterize @Scheduled

I am new to Spring and have only scratched the surface of what can be done with it.

I have a situation where I need to set up a recurring task using the @Scheduled annotation. The rate is specified as a member field in an object that is passed to the class encapsulating the method representing the task.

I've used the mechanism that allows for accessing the configuration or environment, eg @Scheduled(fixedRateString = "${some.property:default}") ; this works great.

What I don't know how to do is insert the value from an object into the @Scheduled .

For example:

class MyClass {
  private MyObject myObj;

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

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

The code above, of course, does not work, I'm just giving an example of what I'm trying to do.

Any suggestions would be appreciated.

Unfortunately the spring bean creation process will not read local variables like that.

You can use the Spring TaskScheduler class.

Essentially you just have to define a thread pool that you will use to run the scheduled tasks (as a bean) and run taskScheduler.schedule(runnable, new CronTrigger("* * * * *")). There is a detailed example here:

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

Yes you can use the @Scheduled annotation to do that with a SpEL expression (available on the @Scheduled annotation since Spring 4.3.x). Here's an example:

@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");
  }
}

However, just because you can do it like this doesn't mean you necessarily should.

Your code may be easier to follow to folks that have to maintain it in the future if you use the spring task scheduler plus you get control of the thread pool used for scheduling instead of relying on the shared executor that all @Scheduled tasks get lumped into.

You can do like follow:

@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() {
    ...
  }
}

As you can see her : https://www.baeldung.com/spring-scheduled-tasks

You can do that like follow :

A fixedDelay task:

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

A fixedRate task:

@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")

A cron expression based task:

@Scheduled(cron = "${cron.expression}")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM