spring-boot-starter-quartz 自动化配置解析

发布于:2024-08-17 ⋅ 阅读:(92) ⋅ 点赞:(0)

版本

spring-boot:3.3.4

源码解析

依赖包 spring-boot-starter-quartz 的作用为引入相关依赖:

  1. spring-boot-starter
  2. spring-context-support
  3. spring-tx
  4. 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");  
	       }  
	  
	    }  
	  
	}
}

网站公告

今日签到

点亮在社区的每一天
去签到