<!-- 配置調度程序quartz ,其中配置JobDetail有兩種方式--> <!-- 使用MethodInvokingJobDetailFactoryBean,任務類可以不實現Job接口,通過targetMethod指定調用方法--> <!-- 定義目標bean和bean中的方法 --> <bean id="SpringQtzJob" class="com.sky.JobSchedule.Job.JobTest"/> <bean id="SpringQtzJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <ref bean="SpringQtzJob"/> </property> <property name="targetMethod"> <!-- 要執行的方法名稱 --> <value>helloSky</value> </property> <property name="arguments" value="11"/> <property name="concurrent " value="false"></property > <!--非並發--> </bean> <!-- 調度觸發器 --> <bean id="CronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="SpringQtzJobMethod"></property> <property name="cronExpression" value="0/5 * * * * ?"></property> </bean> <!-- 調度工廠 --> <bean id="SpringJobSchedulerFactoryBean" lazy-init="true" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="CronTriggerBean"/> </list> </property> </bean>
public class JobTest { String name; public JobTest() { System.out.println("Hello, Quartz! ----------------------"); } public void helloSky(int age) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Hello, " + age + " sky !" + formatter.format(new Date())); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public static void main(String[] args) throws SchedulerException { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:quartz-config.xml"); }
另外一種方式:任務類必須繼承QuartzJobBean或者實現Job方法。
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.mc.bsframe.job.TestJob"></property> <property name="durability" value="true"></property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail" /> <property name="startDelay" value="3000" /> <property name="repeatInterval" value="2000" /> </bean> <!-- 總管理類 如果將lazy-init='false'那么容器啟動就會執行調度程序 --> <bean id="DefaultQuartzScheduler" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 管理trigger --> <property name="triggers"> <list> <ref bean="simpleTrigger" /> </list> </property>
<property name="configLocation" value="classpath:quartz.properties" />
</bean>
只持久化jobDetail
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.sky.JobSchedule.Job.HelloQuartzJob"></property> <property name="durability" value="true"></property> </bean> <bean id="DefaultQuartzScheduler" lazy-init="true" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobDetails"> <list> <ref bean="jobDetail" /> </list> </property> <property name="configLocation" value="classpath:quartz.properties" /> </bean>
兩種方法的說明
使用QuartzJobBean,需要繼承。而使用MethodInvokeJobDetailFactoryBean則需要指定targetObject(任務實例)和targetMethod(實例中要執行的方法)
后者優點是無侵入,業務邏輯簡單,一目了然,缺點是無法持久化(目前還不太清楚這點!)
從我使用的經驗來說,我更推薦的第二種,其中一個很重要的原因就是因為定時任務中注入相關Service的時候,后者可以直接注入,而前者還需要進行Schedular的替換修改。
上述配置的SchedulerFactoryBean的Id需要注意的是:
假若需要進行可視化調度管理的話,不可缺的是獲取所有的jobDetail等等,這時候需要注意的是,獲取過程中,實例化Scheduler時,instanceName會根據quartz.properties來進行獲取,沒有的話默認“QuartzSchelduer”,會獲取數據庫中SCHED_NAME一致的數據。
自定義的名字,可以直接保持配置的id和instanceName一致。
或者顯示的調用SchedulerFactoryBean:
StdSchedulerFactory sf = new StdSchedulerFactory(); Properties props = new Properties(); props.put("org.quartz.scheduler.instanceName", "你定義的名字"); props.put("org.quartz.threadPool.threadCount", "10");#必填 sf.initialize(props); scheduler = sf.getScheduler(); System.out.println(scheduler.getSchedulerName()); scheduler.shutdown();
添加監聽器:在spring-quartz中,監聽器:http://www.cnblogs.com/skyLogin/p/6928431.html
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.sky.JobSchedule.Job.HelloQuartzJob"></property> <property name="durability" value="true"></property> </bean> <bean id="jobDetail2" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.sky.JobSchedule.Job.JobCron"></property> <property name="name" value="test2"></property> <property name="durability" value="true"></property> <property name="jobDataAsMap"> <map> <entry key="name" value="sky"></entry> </map> </property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail" /> <property name="repeatInterval" value="2000" /> </bean> <bean id="jobCountListener" class="com.sky.JobSchedule.Listener.JobCountListener" /> <!--id--> <bean id="DefaultQuartzScheduler" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!--<property name="autoStartup" value="false"></property>--> <property name="jobDetails"> <list> <ref bean="jobDetail" /> <ref bean="jobDetail2" /> </list> </property> <!-- 管理trigger --> <property name="triggers"> <list> <ref bean="simpleTrigger" /> </list> </property> <property name="configLocation" value="classpath:quartz.properties" /> <property name="globalJobListeners" ref="jobCountListener"></property> </bean> </beans>
quartz啟動流程
當服務器啟動時,就會裝載相關的bean。SchedulerFactoryBean實現了InitializingBean接口,因此在初始化bean的時候,會執行afterPropertiesSet方法,該方法將會調用SchedulerFactory(DirectSchedulerFactory 或者 StdSchedulerFactory,通常用StdSchedulerFactory)創建Scheduler。SchedulerFactory在創建quartzScheduler的過程中,將會讀取配置參數,初始化各個組件
-
ThreadPool:一般是使用SimpleThreadPool,SimpleThreadPool創建了一定數量的WorkerThread實例來使得Job能夠在線程中進行處理。WorkerThread是定義在SimpleThreadPool類中的內部類,它實質上就是一個線程。在SimpleThreadPool中有三個list:workers-存放池中所有的線程引用,availWorkers-存放所有空閑的線程,busyWorkers-存放所有工作中的線程;
-
JobStore:分為存儲在內存的RAMJobStore和存儲在數據庫的JobStoreSupport(包括JobStoreTX和JobStoreCMT兩種實現,JobStoreCMT是依賴於容器來進行事務的管理,而JobStoreTX是自己管理事務),若要使用集群要使用JobStoreSupport的方式;
- QuartzSchedulerThread:
SchedulerFactoryBean還實現了SmartLifeCycle接口,因此初始化完成后,會執行start()方法,該方法將主要會執行以下的幾個動作:
- 創建ClusterManager線程並啟動線程:該線程用來進行集群故障檢測和處理,將在下文詳細討論;
- 創建MisfireHandler線程並啟動線程:該線程用來進行misfire任務的處理,將在下文詳細討論;
- 置QuartzSchedulerThread的paused=false,調度線程才真正開始調度;