2.SpringBatch-配置详解源码分析

开启自动运行

配置文件

spring:
  batch:
    job:
      names: simpleJob #自动执行的Job的名字 
      enabled: true #启用
    initialize-schema: ALWAYS #是否初始化数据库
    table-prefix: # 生成的表格前缀
    schema: #生成表格的脚本

添加注解

如果需要自动运行job除了配置外需要引入
@EnableBatchProcessing
自动运行注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(BatchConfigurationSelector.class)
public @interface EnableBatchProcessing {

	/**
	 * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
	 * you should not create any @Bean Job definitions in this context, but rather supply them in separate (child)
	 * contexts through an {@link ApplicationContextFactory}.
	 *
	 * @return boolean indicating whether the configuration is going to be
	 * modularized into multiple application contexts.  Defaults to false.
	 */
	boolean modular() default false;

}

自动配置原理

注解调用配置

引入 @EnableBatchProcessing 注解后会调用 @Import(BatchConfigurationSelector.class)

BatchConfigurationSelector

BatchConfigurationSelector 会调用其 selectImports() 方法

@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		Class<?> annotationType = EnableBatchProcessing.class;
		AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(annotationType.getName(), false));
		Assert.notNull(attributes, String.format("@%s is not present on importing class '%s' as expected",annotationType.getSimpleName(), importingClassMetadata.getClassName()));

		String[] imports;
		if (attributes.containsKey("modular") && attributes.getBoolean("modular")) {
			imports = new String[] { ModularBatchConfiguration.class.getName() };
		}
		else {
			imports = new String[] { SimpleBatchConfiguration.class.getName() };
		}

		return imports;
	}

根据 @EnableBatchProcessing modular属性的配置

  • true ModularBatchConfiguration
  • 其他 SimpleBatchConfiguration

SimpleBatchConfiguration

  1. 该配置最大的问题在于懒加载最后初始化的Batch组件均为代理对象
@Override
@Bean
public JobRepository jobRepository() throws Exception {
	return createLazyProxy(jobRepository, JobRepository.class);
}

  1. 当需要的时候会调用SimpleBatchConfiguration.ReferenceTargetSource.createObject()
@Override
protected Object createObject() throws Exception {
	initialize();
	return reference.get();
}

  1. 里面会调用SimpleBatchConfiguration.initialize()
    他会将通过 getConfigurer()取到的 BatchConfigurer 配置生成的bean取出来去使用
protected void initialize() throws Exception {
	if (initialized) {
		return;
	}
	BatchConfigurer configurer = getConfigurer(context.getBeansOfType(BatchConfigurer.class).values());
	jobRepository.set(configurer.getJobRepository());
	jobLauncher.set(configurer.getJobLauncher());
	transactionManager.set(configurer.getTransactionManager());
	jobRegistry.set(new MapJobRegistry());
	jobExplorer.set(configurer.getJobExplorer());
	initialized = true;
}

  1. 调用AbstractBatchConfiguration.getConfigurer()获取配置类
private BatchConfigurer configurer;
·
·
·
protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
	if (this.configurer != null) {//如果configurer不为空 返回 
		return this.configurer;
	}
	if (configurers == null || configurers.isEmpty()) {
		if (dataSource == null) {
			DefaultBatchConfigurer configurer = new DefaultBatchConfigurer();
			configurer.initialize();
			this.configurer = configurer;
			return configurer;
		} else {
			DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
			configurer.initialize();
			this.configurer = configurer;
			return configurer;
		}
	}
	if (configurers.size() > 1) {
		throw new IllegalStateException(
				"To use a custom BatchConfigurer the context must contain precisely one, found "
						+ configurers.size());
	}
	this.configurer = configurers.iterator().next();
	return this.configurer;
}


5.BatchConfigurerConfiguration初始化BatchConfigurer

@ConditionalOnClass({PlatformTransactionManager.class})
@ConditionalOnMissingBean({BatchConfigurer.class})
@Configuration
class BatchConfigurerConfiguration {
    BatchConfigurerConfiguration() {}

    @Configuration
    @ConditionalOnClass(name = {"javax.persistence.EntityManagerFactory"})
    @ConditionalOnBean(name = {"entityManagerFactory"})
    static class JpaBatchConfiguration {
        JpaBatchConfiguration() {
        }

        @Bean
        public JpaBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers, EntityManagerFactory entityManagerFactory) {
            return new JpaBatchConfigurer(properties, dataSource, (TransactionManagerCustomizers)transactionManagerCustomizers.getIfAvailable(), entityManagerFactory);
        }
    }

    @Configuration
    @ConditionalOnMissingBean(name = {"entityManagerFactory"})
    static class JdbcBatchConfiguration {
        JdbcBatchConfiguration() {
        }

        @Bean
        public BasicBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
            return new BasicBatchConfigurer(properties, dataSource, (TransactionManagerCustomizers)transactionManagerCustomizers.getIfAvailable());
        }
    }
}
@Configuration
@ConditionalOnClass({JobLauncher.class, DataSource.class, JdbcOperations.class})
@AutoConfigureAfter({HibernateJpaAutoConfiguration.class})
@ConditionalOnBean({JobLauncher.class})
@EnableConfigurationProperties({BatchProperties.class})
@Import({BatchConfigurerConfiguration.class})
public class BatchAutoConfiguration {
    private final BatchProperties properties;
    private final JobParametersConverter jobParametersConverter;

    public BatchAutoConfiguration(BatchProperties properties, ObjectProvider<JobParametersConverter> jobParametersConverter) {
        this.properties = properties;
        this.jobParametersConverter = (JobParametersConverter)jobParametersConverter.getIfAvailable();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBean({DataSource.class})
    public BatchDataSourceInitializer batchDataSourceInitializer(DataSource dataSource, ResourceLoader resourceLoader) {
        return new BatchDataSourceInitializer(dataSource, resourceLoader, this.properties);
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(
        prefix = "spring.batch.job",
        name = {"enabled"},
        havingValue = "true",
        matchIfMissing = true
    )
    public JobLauncherCommandLineRunner jobLauncherCommandLineRunner(JobLauncher jobLauncher, JobExplorer jobExplorer) {
        JobLauncherCommandLineRunner runner = new JobLauncherCommandLineRunner(jobLauncher, jobExplorer);
        String jobNames = this.properties.getJob().getNames();
        if(StringUtils.hasText(jobNames)) {
            runner.setJobNames(jobNames);
        }

        return runner;
    }

    @Bean
    @ConditionalOnMissingBean({ExitCodeGenerator.class})
    public JobExecutionExitCodeGenerator jobExecutionExitCodeGenerator() {
        return new JobExecutionExitCodeGenerator();
    }

    @Bean
    @ConditionalOnMissingBean({JobOperator.class})
    public SimpleJobOperator jobOperator(JobExplorer jobExplorer, JobLauncher jobLauncher, ListableJobLocator jobRegistry, JobRepository jobRepository) throws Exception {
        SimpleJobOperator factory = new SimpleJobOperator();
        factory.setJobExplorer(jobExplorer);
        factory.setJobLauncher(jobLauncher);
        factory.setJobRegistry(jobRegistry);
        factory.setJobRepository(jobRepository);
        if(this.jobParametersConverter != null) {
            factory.setJobParametersConverter(this.jobParametersConverter);
        }

        return factory;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值