스프링부트 해부학 : Batch(1) - BatchAutoConfiguration

정윤성·2022년 6월 18일
0

스프링부트 해부학

목록 보기
18/20

역할

배치는 실시간으로 처리하는것이 아닌 처리할 작업물들을 모아 위그림처럼 한번에 처리하는 것이다

예를들어 1년간 접속하지않은 모든 회원들을 휴먼계정으로 처리하는 등 일반적인 비즈니스로직이 아닌 상황에 대해서 처리해주는 프로세스이다

@EnableBatchProcessing

@Import(BatchConfigurationSelector.class)

boolean modular() default false;

해당 어노테이션 BatchConfigurationSelector를 임포트한다

modular라는 속성이 있는데 이는 ApplicationContext마다 다르게 배치를 사용할때의 옵션이다

true값을 주게되면 @Bean이아닌 ApplicationContextFactory를 직접만들어 해당 Context에 주입한뒤 사용해야한다

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

위에서 설명했던 modular에따라 객체가 다르게 생성되는걸 볼 수 있다
하지만 둘은 결국 부모가 같다

@Configuration(proxyBeanMethods = false)
@Import(ScopeConfiguration.class)
public abstract class AbstractBatchConfiguration implements ImportAware, InitializingBean {
	
    @Bean
	public JobBuilderFactory jobBuilders() throws Exception {
		return this.jobBuilderFactory;
	}

	@Bean
	public StepBuilderFactory stepBuilders() throws Exception {
		return this.stepBuilderFactory;
	}
    
    @Bean
	public abstract JobRepository jobRepository() throws Exception;

	@Bean
	public abstract JobLauncher jobLauncher() throws Exception;

	@Bean
	public abstract JobExplorer jobExplorer() throws Exception;

	@Bean
	public JobRegistry jobRegistry() throws Exception {
		return this.jobRegistry;
	}
    
    @Bean
	public abstract PlatformTransactionManager transactionManager() throws Exception;
    
    @Override
	public void afterPropertiesSet() throws Exception {
		this.jobBuilderFactory = new JobBuilderFactory(jobRepository());
		this.stepBuilderFactory = new StepBuilderFactory(jobRepository(), transactionManager());
	}
}

다음과같이 배치를 사용하기위해 Factory부터 Repository, Launcher등의 객체를 생성해주며 Bean이 초기화 될 당시 Fatcory에 직접 객체를 생성하는것 또한볼 수 있다

BatchAutoConfiguration

org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration=

BatchAutoConfiguration은 spring-autocofigure-metadata.properties파일에보면 자동으로 등록되어있다

@Import({ BatchConfigurerConfiguration.class, DatabaseInitializationDependencyConfigurer.class })
public class BatchAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnProperty(prefix = "spring.batch.job", name = "enabled", havingValue = "true", matchIfMissing = true)
	public JobLauncherApplicationRunner jobLauncherApplicationRunner(JobLauncher jobLauncher, JobExplorer jobExplorer,
			JobRepository jobRepository, BatchProperties properties) {
JobLauncherApplicationRunner runner = new JobLauncherApplicationRunner(jobLauncher, jobExplorer, jobRepository);
		String jobNames = properties.getJob().getNames();
		if (StringUtils.hasText(jobNames)) {
			runner.setJobNames(jobNames);
		}
		return runner;
	}
    
    @Conditional(OnBatchDatasourceInitializationCondition.class)
	static class DataSourceInitializerConfiguration {
    	...
    }
    
    static class OnBatchDatasourceInitializationCondition extends OnDatabaseInitializationCondition {

		OnBatchDatasourceInitializationCondition() {
			super("Batch", "spring.batch.jdbc.initialize-schema", "spring.batch.initialize-schema");
		}

	}
}

JobLauncherApplicationRunner라는 ApplicationRunner가 등록되는데 이를 통해 Job들이 실행된다

이 외에 Datasource관련된 클래스들은 정보 DB에 DML, DDL과 관련된 객체들이다

JobLauncherApplicationRunner

public void run(String... args) throws JobExecutionException {
	launchJobFromProperties(StringUtils.splitArrayElementsIntoProperties(args, "="));
}

protected void launchJobFromProperties(Properties properties) throws JobExecutionException {
	JobParameters jobParameters = this.converter.getJobParameters(properties);
	executeLocalJobs(jobParameters);
	executeRegisteredJobs(jobParameters);
}

private void executeLocalJobs(JobParameters jobParameters) throws JobExecutionException {
	for (Job job : this.jobs) {
		...
        execute(job, jobParameters);
    }
}

private void executeRegisteredJobs(JobParameters jobParameters) throws JobExecutionException {
	...
	for (String jobName : jobsToRun) {
    	...
        Job job = this.jobRegistry.getJob(jobName);
        ...
        execute(job, jobParameters);
    }
}

run이 호출되면 해당 args배열을 파싱해 JobParameter를 찾아온다음 local에있는 Job과 Repository에 저장되어있는 Job에 전달해 실행시킨다

protected void execute(Job job, JobParameters jobParameters) {
	JobParameters parameters = getNextJobParameters(job, jobParameters);
    JobExecution execution = this.jobLauncher.run(job, parameters);
    if (this.publisher != null) {
    	this.publisher.publishEvent(new JobExecutionEvent(execution));
	}
}

다음과같이 JobParameter, JobExecution객체를 만들어 JobLauncher를 통해 실행한 뒤 Event를 발행한다

정리

  1. 스프링에서는 기본적으로 BatchAutoConfiguration이 들어가있다
  2. @EnableBatchProcessing을 통해 Job을 만들고, 실행하고, 저장할 수 있는 Bean들을 초기화한다
  3. JobLauncherApplicationRunner는 ApplicationRunner이므로 서버가 정상적으로 부트가되면 모든 Job을 실행한다
profile
게으른 개발자

0개의 댓글