Quartz 是 Java 領域功能最強大的調度框架,Spring 通過 SchedulerFactoryBean、MethodInvokingJobDetailFactoryBean、CronTriggerFactoryBean 等 FactoryBean 將其無縫納入 IoC 容器。本文展示純 XML 配置實現「目標類無需實現 Job 接口」的鬆耦合定時任務,並解析啟動延遲、線程池、Cron 表達式等關鍵參數。
public class MyJob2 {
public void targetMethod() {
System.out.println("hello world, quartz, date:" + new Date());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 1. 目標 Bean -->
<bean id="myJob" class="com.nucsoft.quartz.job.MyJob2"/>
<!-- 2. JobDetail:綁定目標對象與方法 -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myJob"/>
<property name="targetMethod" value="targetMethod"/>
</bean>
<!-- 3. CronTrigger:指定 JobDetail 與 Cron 表達式 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"/>
<!-- 每 5 秒執行一次 -->
<property name="cronExpression" value="0/5 * * * * ?"/>
</bean>
<!-- 4. Scheduler:註冊 Trigger、配置線程池、啟動延遲 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<array><ref bean="cronTrigger"/></array>
</property>
<!-- Quartz 底層屬性覆蓋 -->
<property name="quartzProperties">
<props>
<prop key="org.quartz.threadPool.threadCount">10</prop>
</props>
</property>
<!-- 容器啟動 10 秒後啟動調度器,避免與業務啟動衝突 -->
<property name="startupDelay" value="10"/>
</bean>
</beans>
| FactoryBean | 職責 | 關鍵屬性 |
|---|---|---|
| MethodInvokingJobDetailFactoryBean | 將 POJO 方法包裝為 Quartz JobDetail | targetObject, targetMethod, concurrent(false 默認串行) |
| CronTriggerFactoryBean | 構建基於 Cron 表達式的 Trigger | jobDetail, cronExpression, startTime, timezone |
| SimpleTriggerFactoryBean | 構建固定頻率/延遲 Trigger | jobDetail, repeatInterval, repeatCount, startDelay |
| SchedulerFactoryBean | 創建並啟動 Quartz Scheduler,註冊 Trigger | triggers, quartzProperties, startupDelay, schedulerName |
* * * * * * ? 秒 分 時 日 月 周 年(可選) 0/5 * * * * ? 每 5 秒 0 0/1 * * * ? 每 1 分鐘 0 0 2 * * ? 每天 02:00 0 0 2 ? * MON-FRI 工作日 02:00 0 0 2 1 * ? 每月 1 號 02:00 0 0 2 L * ? 每月最後一天 02:00
public class QuartzTest {
public static void main(String[] args) {
// 僅啟動 Spring 容器,Scheduler 自動啟動
new ClassPathXmlApplicationContext("spring-quartz.xml");
}
}
關鍵現象:首次執行時間 = 容器啟動 + startupDelay;第二次執行才按 Cron 間隔。因為首次是「啟動調度器」,非「觸發任務」。
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">MyCluster</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.dataSource">myDS</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.dataSource.myDS.driver">com.mysql.jdbc.Driver</prop>
<prop key="org.quartz.dataSource.myDS.URL">jdbc:mysql://...</prop>
<prop key="org.quartz.dataSource.myDS.user">root</prop>
<prop key="org.quartz.dataSource.myDS.password">pwd</prop>
<prop key="org.quartz.dataSource.myDS.maxConnections">20</prop>
</props>
</property>
<property name="dataSource" ref="dataSource"/> <!-- 引用 Spring DataSource -->
<property name="transactionManager" ref="transactionManager"/>
集群模式下多節點共享數據庫表,自動實現負載均衡與故障轉移。
@Configuration
@EnableScheduling
public class QuartzConfig {
@Bean
public JobDetail jobDetail() {
return JobBuilder.newJob(MyJob.class).storeDurably().build();
}
@Bean
public Trigger trigger(JobDetail jobDetail) {
return TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
.build();
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource ds, PlatformTransactionManager tm) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(ds);
factory.setTransactionManager(tm);
factory.setTriggers(trigger(jobDetail()));
factory.setQuartzProperties(quartzProps());
return factory;
}
}
Spring 整合 Quartz 核心思想:「大容器管小容器」。Spring 管理 Scheduler 生命周期,Quartz 專注調度邏輯。FactoryBean 模式讓業務代碼零依賴 Quartz API,遷移至 Spring Boot 只需將 XML 翻譯為 @Bean 方法。掌握 Cron 表達式、線程池、持久化集群三大進階點,即可應對企業級調度場景。