spring定時任務如何運行 schedule解析

網上關於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類,這個類已經被實例化好了。按需取值就行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章