Spring batch的自动运行

一个最简单的spring batch的程序,照办官网的sample,如下

一个配置程序

@Configuration
@EnableBatchProcessing
@EnableAutoConfiguration
public class BatchConfiguration {

  @Autowired
  private JobBuilderFactory jobBuilderFactory;

  @Autowired
  private StepBuilderFactory stepBuilderFactory;

  @Bean
  public Step step1() {
    return stepBuilderFactory.get("step1")
        .tasklet(new Tasklet() {
          public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
            return null;
          }
        })
        .build();
  }

  @Bean
  public Job job(Step step1) throws Exception {
    return jobBuilderFactory.get("job1")
        .incrementer(new RunIdIncrementer())
        .start(step1)
        .build();
  }
}

 一个主程序

public class Main {
  public static void main(String [] args) {
    System.exit(SpringApplication.exit(SpringApplication.run(
        BatchConfiguration.class, args)));
  }
}

 你肯定会好奇,为啥Job就执行了呢?没看到调用啊

实际上在Spring batch的配置程序org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration里有以下代码

	@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;
	}

也就是当配置文件里定义spring.batch.job.enabled为true,或者没定义(默认为true)的时候,会初始化一个JobLauncherCommandLineRunner的bean。

而在SpringApplication里有以下代码

	private void callRunners(ApplicationContext context, ApplicationArguments args) {
		List<Object> runners = new ArrayList<Object>();
		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
		AnnotationAwareOrderComparator.sort(runners);
		for (Object runner : new LinkedHashSet<Object>(runners)) {
			if (runner instanceof ApplicationRunner) {
				callRunner((ApplicationRunner) runner, args);
			}
			if (runner instanceof CommandLineRunner) {
				callRunner((CommandLineRunner) runner, args);
			}
		}
	}

 也就是只要能找到ApplicationRunner或者CommandLineRunner的子类,就挨个执行。

默认是没有ApplicationRunner的子类的,而CommandLineRunner得子类就是JobLauncherCommandLineRunner了,所以会执行所配置的job。

如果想自己执行job的话,使用以下代码便可。

	@Autowired
	private JobLauncher jobLauncher;
	@Autowired
	private Job job;
	
	@Scheduled(initialDelay=3000,fixedRate = 1000)
	public void run(){
		try {
			JobExecution execution = jobLauncher.run(job, new JobParameters());
			System.out.println("Execution status: "+ execution.getStatus());
		} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
				| JobParametersInvalidException e) {
			e.printStackTrace();
		} 
	}

 这时候,你可能会好奇,JobLauncher是哪儿配置的?

上面的配置文件里使用了注解@EnableBatchProcessing

这个注解会初始化以下所有bean

写道
JobRepository bean 名称 "jobRepository"
JobLauncher bean名称"jobLauncher"
JobRegistry bean名称"jobRegistry"
PlatformTransactionManager bean名称 "transactionManager"
JobBuilderFactory bean名称"jobBuilders"
StepBuilderFactory bean名称"stepBuilders"

 在程序org.springframework.batch.core.configuration.annotation.BatchConfigurationSelector会根据定义选择配置程序,默认用的是SimpleBatchConfiguration

public class BatchConfigurationSelector implements ImportSelector {

	@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;
	}

}

 

猜你喜欢

转载自weiqingfei.iteye.com/blog/2307165