在Spring Boot中要定时执行一些任务可以不必要使用线程来实现,它为我们提供了一种方法来简化任务的定时执行,这种方式是建立在@EnableScheduling
和@Scheduled
上的。
首先我们需要先创建一个需要定时执行的任务,如下:
@Component
public class ScheduleTask {
@Scheduled(fixedRate=5000)
public void sendMail(){
System.out.println("send mail");
}
}
关于@Scheduled
中两个经常使用的属性如下:
fixedDelay
表示当方法执行完毕后多长时间,Spring scheduling会再次调用该方法;fixedRate
表示每隔多长时间,Spring scheduling会调用一次该方法,不论该方法是否执行完;
该注解中还有其他的属性可以使用,详细内容查看JavaDoc
而被@Scheduled
注解的方法也有一些限制规定:
- 方法不能有参数,也就是参数为空;
- 返回值类型必须是
void
在应用程序的启动类中使用@EnableScheduling
注解,如下:
@SpringBootApplication
@EnableScheduling
public class SpringBootTemplateApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTemplateApplication.class, args);
}
}
运行Spring Boot程序后,上述程序就会每隔5000ms发送一次邮件,感觉很简单有没有!!
那么这一切都是怎么起作用的?首先是从注解@EnableScheduling
开始,看它的源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}
这里顺便说一下
@Import
注解,这个注解是用来导入配置类(使用@Configuration
注解的类)的,主要是通过使用注解的配置方式而不是XML配置方式起作用,如果想在注解方式中使用XML方式定义bean可以使用@ImportResource
来标明导入的配置文件名。另外在Spring 4.2及以后的版本中@Import
注解的配置类不用使用@Configuration
注解也会被当成一个bean来被容器处理。
使用@Import导入了配置类SchedulingConfiguration
,在这个配置类中配置了一个bean为ScheduledAnnotationBeanPostProcessor
,使用这个bean中的方法processScheduled(...)
来扫描所有已经创建的bean,对所有符合以下条件的方法全部记录下来:
- 方法被
@Scheduled
注解 - 方法不能有参数,也就是参数为空;
- 返回值类型必须是
void
然后为每一个这样的任务分配一个调度线程,然后根据设定的时间通过该线程执行特定的任务。