One of the simplest spring batch programs, follow the sample on the official website , as follows
a configurator
@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(); } }
a main program
public class Main { public static void main(String [] args) { System.exit(SpringApplication.exit(SpringApplication.run( BatchConfiguration.class, args))); } }
You must be curious, why is the Job executed? I don't see the call
In fact, there is the following code in the Spring batch configuration program 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; }
That is, when spring.batch.job.enabled is defined as true in the configuration file , or not defined (default is true), a JobLauncherCommandLineRunner bean will be initialized.
And in SpringApplication there is the following code
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); } } }
That is, as long as you can find a subclass of ApplicationRunner or CommandLineRunner, execute them one by one.
By default, there is no subclass of ApplicationRunner, and the subclass of CommandLineRunner is JobLauncherCommandLineRunner, so the configured job will be executed.
If you want to execute the job yourself, use the following code.
@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 (); } }
At this point, you may be wondering, where is the JobLauncher configured?
The above configuration file uses the annotation @EnableBatchProcessing
This annotation will initialize all the following beans
JobLauncher bean名称"jobLauncher"
JobRegistry bean名称"jobRegistry"
PlatformTransactionManager bean名称 "transactionManager"
JobBuilderFactory bean名称"jobBuilders"
StepBuilderFactory bean名称"stepBuilders"
In the program org.springframework.batch.core.configuration.annotation.BatchConfigurationSelector will select the configuration program according to the definition, the default is 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; } }