<!-- 配置調度程序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,調度線程才真正開始調度;
