網上關於spring自帶的定時任務是怎麼運行的文檔很少,goole 百度了很久都沒找到這塊的文檔,而集成quartz的文檔很多,而spring如果單純的只是運行定時任務是不需要quartz包的。下面是我自己研究出來的,有錯見諒。
經過長時間的研究spirng的源碼,發現如果僅僅只是在xml裏配置定時任務或者通過註解來實現配置定時任務的話,無需依賴spring-context-support,這個包裏所含的scheduling包都是爲了集成quartz的,而spirng其實只用了spring-context的scheduling包。下面解讀一下spring是如何解析我們的配置並且運行的
簡單的配置一下定時任務
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- job 的包 加載定時任務實現類-->
<context:component-scan base-package="com.galaxy.fym.job"></context:component-scan>
<!-- 任務調度器配置 配置任務線性池 pool-size
指配的一個scheduled-tasks中所有的運行方法的線程總數
不同的scheduled-tasks配置了相同的task:scheduler會有相同的總數限制,而不是和的限制-->
<task:scheduler id="scheduler" pool-size="10" />
<!-- 指定運行的方法和運行時間規則時間
task:scheduler/@pool-size:調度線程池的大小,調度線程在被調度任務完成前不會空閒
task:scheduled/@cron:cron表達式,注意,若上次任務未完成,即使到了下一次調度時間,任務也不會重複調度 -->
<task:scheduled-tasks scheduler="scheduler">
<!-- 一秒一次 -->
<task:scheduled ref="jobTest" method="jobPrint" cron="*/1 * * * * ?"/>
<task:scheduled ref="jobTest" method="jobPrint2" cron="*/1 * * * * ?"/>
</task:scheduled-tasks>
</beans>
這裏因爲我在applicationContext中import了這個文件,所以spring在加載的時候也會來解析這個文件,在spring-context中我發現了spring.handlers這個文件說明了那個類是用來解析schedule配置的
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.scheduling.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.scheduling.config.AnnotationDrivenBeanDefinitionParser;
import org.springframework.scheduling.config.ExecutorBeanDefinitionParser;
import org.springframework.scheduling.config.ScheduledTasksBeanDefinitionParser;
import org.springframework.scheduling.config.SchedulerBeanDefinitionParser;
public class TaskNamespaceHandler extends NamespaceHandlerSupport {
public TaskNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
this.registerBeanDefinitionParser("executor", new ExecutorBeanDefinitionParser());
this.registerBeanDefinitionParser("scheduled-tasks", new ScheduledTasksBeanDefinitionParser());
this.registerBeanDefinitionParser("scheduler", new SchedulerBeanDefinitionParser());
}
}
上面已經清楚的說到了每個xml屬性配置是由哪個類來解析的。
spring加載的時候會實例化ContextLifecycleScheduledTaskRegistrar這個類,而這個類有繼承了ScheduledTaskRegistrar類,ScheduledTaskRegistrar類就是整個spring配置裏的定時任務的註冊中心,
下面是這個類的幾個成員屬性。
public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean {
private TaskScheduler taskScheduler;
private ScheduledExecutorService localExecutor;
private List<TriggerTask> triggerTasks;
private List<CronTask> cronTasks;
private List<IntervalTask> fixedRateTasks;
private List<IntervalTask> fixedDelayTasks;
private final Set<ScheduledFuture<?>> scheduledFutures = new LinkedHashSet();
像開始的配置,最後加載到cronTasks這個屬性裏,至於是怎麼存的,自己看一下源碼就知道了。
接下來,spring就不停用線程來跑定時任務的方法了。
如果你想在代碼運行的時候查看哪些你自己配置了哪些定時任務,很簡單,加上這段代碼
package com.galaxy.fym.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar;
import org.springframework.scheduling.config.CronTask;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created by fengyiming on 2016/8/18.
*/
@Service
public class TaskService {
private final Logger logger = LoggerFactory.getLogger("task service");
@Autowired
private ContextLifecycleScheduledTaskRegistrar contextLifecycleScheduledTaskRegistrar;
public Object print(){
try {
//你所有配置的定時任務都在這個集合中
List<CronTask> cronTasks = contextLifecycleScheduledTaskRegistrar.getCronTaskList();
return cronTasks;
}catch (Exception e){
logger.error("------------------");
return null;
}
}
}
無需再spring裏實例化ContextLifecycleScheduledTaskRegistrar類,這個類已經被實例化好了。按需取值就行了。