版本
spring-boot:3.3.4
源码解析
依赖包 spring-boot-starter-quartz 的作用为引入相关依赖:
- spring-boot-starter
- spring-context-support
- spring-tx
- quartz
自动化配置类
依赖:spring-boot-autoconfigure:3.2.4
文件:org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration
// 因为需要使用datasource,在数据源配置之后执行配置
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class })
// 自动配置条件:
// 1. Scheduler.class - quartz 调度器
// 2. SchedulerFactoryBean.class - spring-context-support SPRING上下文工具
// 3. PlatformTransactionManager.class - spring-tx SPRING事务
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class })
// 启用spring.quartz配置项
@EnableConfigurationProperties(QuartzProperties.class)
public class QuartzAutoConfiguration {
// 注册quartz调度器工厂
@Bean
@ConditionalOnMissingBean
public SchedulerFactoryBean quartzScheduler(
QuartzProperties properties,
ObjectProvider<SchedulerFactoryBeanCustomizer> customizers,
ObjectProvider<JobDetail> jobDetails,
Map<String, Calendar> calendars,
ObjectProvider<Trigger> triggers,
ApplicationContext applicationContext
) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
// job工厂,此工厂可以构造job bean 并实现依赖注入,和 jobData 注入
SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
// 设置应用上下文,SchedulerFactoryBean需要使用 applicationContext.getAutowireCapableBeanFactory().createBean实现job bean构造和依赖注入
jobFactory.setApplicationContext(applicationContext);
schedulerFactoryBean.setJobFactory(jobFactory);
// 配置名称
if (properties.getSchedulerName() != null) {
schedulerFactoryBean.setSchedulerName(properties.getSchedulerName());
}
// 配置是否自动启动
schedulerFactoryBean.setAutoStartup(properties.isAutoStartup());
// 配置启动延迟时间
schedulerFactoryBean.setStartupDelay((int) properties.getStartupDelay().getSeconds());
// 配置关闭调度器时是否等待JOB执行完毕
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(properties.isWaitForJobsToCompleteOnShutdown());
// 配置是否覆盖已存在的JOB,标识为true后,添加相同key的作业/触发器默认将直接覆盖原有的作业/触发器。
schedulerFactoryBean.setOverwriteExistingJobs(properties.isOverwriteExistingJobs());
// 配置其他属性
if (!properties.getProperties().isEmpty()) {
schedulerFactoryBean.setQuartzProperties(asProperties(properties.getProperties()));
}
// 注册job
schedulerFactoryBean.setJobDetails(jobDetails.orderedStream().toArray(JobDetail[]::new));
// 注册日历
schedulerFactoryBean.setCalendars(calendars);
// 注册触发器
schedulerFactoryBean.setTriggers(triggers.orderedStream().toArray(Trigger[]::new));
// 注册客制化器
customizers.orderedStream().forEach((customizer) -> customizer.customize(schedulerFactoryBean));
return schedulerFactoryBean;
}
...
// 配置持久化 JDBC存储
@Configuration(proxyBeanMethods = false)
// 条件1:存在单一的数据源bean
@ConditionalOnSingleCandidate(DataSource.class)
// 条件2:配置属性 spring.quartz.job-store-type=jdbc
@ConditionalOnProperty(prefix = "spring.quartz", name = "job-store-type", havingValue = "jdbc")
// 导入数据库初始化配置器
@Import(DatabaseInitializationDependencyConfigurer.class)
protected static class JdbcStoreTypeConfiguration {
// 配置数据源的调度器工厂客制化器
@Bean
@Order(0)
public SchedulerFactoryBeanCustomizer dataSourceCustomizer(
QuartzProperties properties,
DataSource dataSource,
@QuartzDataSource ObjectProvider<DataSource> quartzDataSource,
ObjectProvider<PlatformTransactionManager> transactionManager,
@QuartzTransactionManager ObjectProvider<PlatformTransactionManager> quartzTransactionManager
) {
return (schedulerFactoryBean) -> {
// 配置数据源
DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
schedulerFactoryBean.setDataSource(dataSourceToUse);
// 配置事务管理器
PlatformTransactionManager txManager = getTransactionManager(transactionManager,
quartzTransactionManager);
if (txManager != null) {
schedulerFactoryBean.setTransactionManager(txManager);
}
};
}
// 获取数据源,优先使用 QuartzDataSource 注解的数据源,否则使用应用的主数据源(Primary)
private DataSource getDataSource(DataSource dataSource, ObjectProvider<DataSource> quartzDataSource) {
DataSource dataSourceIfAvailable = quartzDataSource.getIfAvailable();
return (dataSourceIfAvailable != null) ? dataSourceIfAvailable : dataSource;
}
// 获取事务管理器,优先使用 QuartzTransactionManager 注解的事务管理器,否则使用应用的事务管理器
private PlatformTransactionManager getTransactionManager(
ObjectProvider<PlatformTransactionManager> transactionManager,
ObjectProvider<PlatformTransactionManager> quartzTransactionManager) {
PlatformTransactionManager transactionManagerIfAvailable = quartzTransactionManager.getIfAvailable();
return (transactionManagerIfAvailable != null) ? transactionManagerIfAvailable
: transactionManager.getIfUnique();
}
// 注册数据库表初始化器,可通过配置属性 spring.quartz.jdbc.initialize-schema 指定是否初始化数据库
// 1. 默认值 EMBEDDED ,标识只初始化内置数据库
// 2. 如果需要初始化外部数据库的数据源,可配置为ALWAYS,则总是会执行初始化脚本
// 3. 初始化完成后,可配置为NEVER,则不会在每次启动时初始化数据
// 可通过 配置属性 spring.quartz.jdbc.schema 指定初始化脚本位置 ,默认使用位于 classpath:org/quartz/impl/jdbcjobstore/tables_@@platform@@.sql 的脚本
// schema中的占位符@@platform@@ 会被替换为实际数据源对应的数据库平台类型
@Bean
// 条件1:没有注册其他初始化器
@ConditionalOnMissingBean(QuartzDataSourceScriptDatabaseInitializer.class)
// 条件2:检查是否配置属性 spring.quartz.jdbc.initialize-schema
@Conditional(OnQuartzDatasourceInitializationCondition.class)
public QuartzDataSourceScriptDatabaseInitializer quartzDataSourceScriptDatabaseInitializer(
DataSource dataSource, @QuartzDataSource ObjectProvider<DataSource> quartzDataSource,
QuartzProperties properties) {
DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
return new QuartzDataSourceScriptDatabaseInitializer(dataSourceToUse, properties);
}
static class OnQuartzDatasourceInitializationCondition extends OnDatabaseInitializationCondition {
OnQuartzDatasourceInitializationCondition() {
super("Quartz", "spring.quartz.jdbc.initialize-schema");
}
}
}
}