Spring Batch - 01. @EnableBatchProcessing

출처

목차

@EnableBatchProcessing

@EnableBatchProcessing 을 이용해 어플리케이션이 Spring Batch 로 실행될 수 있도록 자동으로 설정해준다.

@SpringBootApplication
@EnableBatchProcessing // Spring Batch 활성화
public class SpringBatchApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBatchApplication.class, args);
}
}

Spring Batch 초기화 과정

@EnableBatchProcessing 을 명시해주면 Batch 관련 설정 클래스 SimpleBatchConfiguration, BatchConfigurerConfiguration, BatchAutoConfiguration 를 실행시켜 Spring Batch 초기화 및 실행 구성이 이뤄진다.

SimpleBatchConfiguration

SimpleBatchConfiguration은 Spring Batch에서 배치 처리를 위한 기본 설정 을 제공하는 클래스

SimpleBatchConfiguration 클래스는 SimpleBatchConfigurer 클래스에서 설정한 값을 기반으로 배치 처리를 위한 JobRepository, JobLauncher, JobExplorer 등을 설정합니다.

  • JobBuilderFactoryStepBuilderFactory 를 생성한다.

SimpleBatchConfiguration.java

@Configuration(proxyBeanMethods = false)
public class SimpleBatchConfiguration extends AbstractBatchConfiguration {

@Autowired
private ApplicationContext context;
private boolean initialized = false;
private AtomicReference<JobRepository> jobRepository = new AtomicReference<>();
private AtomicReference<JobLauncher> jobLauncher = new AtomicReference<>();
private AtomicReference<JobRegistry> jobRegistry = new AtomicReference<>();
private AtomicReference<PlatformTransactionManager> transactionManager = new AtomicReference<>();
private AtomicReference<JobExplorer> jobExplorer = new AtomicReference<>();

@Override
@Bean
public JobRepository jobRepository() throws Exception {
return createLazyProxy(jobRepository, JobRepository.class);
}

@Override
@Bean
public JobLauncher jobLauncher() throws Exception {
return createLazyProxy(jobLauncher, JobLauncher.class);
}

@Override
@Bean
public JobRegistry jobRegistry() throws Exception {
return createLazyProxy(jobRegistry, JobRegistry.class);
}

@Override
@Bean
public JobExplorer jobExplorer() {
return createLazyProxy(jobExplorer, JobExplorer.class);
}

@Override
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
return createLazyProxy(transactionManager, PlatformTransactionManager.class);
}

private <T> T createLazyProxy(AtomicReference<T> reference, Class<T> type) {
ProxyFactory factory = new ProxyFactory();
factory.setTargetSource(new ReferenceTargetSource<>(reference));
factory.addAdvice(new PassthruAdvice());
factory.setInterfaces(new Class<?>[] { type });
@SuppressWarnings("unchecked")
T proxy = (T) factory.getProxy();
return proxy;
}

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

private class PassthruAdvice implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return invocation.proceed();
}
}

private class ReferenceTargetSource<T> extends AbstractLazyCreationTargetSource {

private AtomicReference<T> reference;

public ReferenceTargetSource(AtomicReference<T> reference) {
this.reference = reference;
}

@Override
protected Object createObject() throws Exception {
initialize();
return reference.get();
}
}
}

BatchConfigurerConfiguration

BatchConfigurerConfiguration 은 Spring Batch 에서 배치 처리를 위한 데이터베이스 연결, 트랜잭션 관리 등을 수행하는 BatchConfigurer 를 설정하는 자동 구성 클래스

BatchConfigurerConfiguration 클래스는 JdbcBatchConfiguration 와 JpaBatchConfiguration 두개의 정적 클래스를 제공한다.

JdbcBatchConfiguration

JdbcBatchConfiguration은 JDBC 기반의 데이터베이스 연동을 처리

JdbcBatchConfiguration 은 Spring Batch에서 JDBC 기반의 데이터베이스 연동을 위해 사용됩니다. 이 클래스는 JobRepository, TransactionManager, DataSource, JobLauncher 등을 설정합니다.

JdbcBatchConfiguration 은 H2 데이터베이스를 사용하여 JobRepository를 생성합니다. 따라서 개발자가 H2 데이터베이스를 사용하지 않고 다른 데이터베이스를 사용하려면, JdbcBatchConfiguration 클래스를 상속받아 새로운 설정 클래스를 작성해야 합니다.

JdbcBatchConfiguration 는 BasicBatchConfigurer 객체를 생성하고 Bean 으로 등록하기 때문에 필요할때 의존성 주입을 통해 BasicBatchConfigurer 객체를 사용할 수 있다.

BasicBatchConfigurer

BasicBatchConfigurer 객체는 SimpleBatchConfiguration 에서 생성한 프록시 객체의 실제 대상 객체를 생성한다.

BasicBatchConfigurer는 Batch의 다양한 구성 요소를 구성하는 데 사용됩니다. 예를 들어, JobRepository, JobLauncher, TaskExecutor 등의 구성 요소를 구성합니다. 또한, BasicBatchConfigurer는 필요한 데이터베이스 연결 정보를 설정하고, 트랜잭션 관리를 위한 트랜잭션 매니저를 구성하는 등의 일을 처리합니다.

Spring Batch에서는 개발자가 직접 BasicBatchConfigurer를 상속하여 필요한 Batch 환경을 구성할 수도 있습니다. 이를 통해, 개발자는 Batch Job의 실행 시나리오에 맞게 Batch 환경을 유연하게 구성할 수 있습니다.

BasicBatchConfigurer는 일반적으로 SimpleBatchConfiguration을 기반으로 구현됩니다. SimpleBatchConfiguration은 가장 기본적인 Batch 환경을 구성하는 클래스이며, 모든 Batch 구성 요소를 메모리 내 데이터 저장소를 사용하여 구성합니다. 이러한 메모리 내 데이터 저장소는 단순한 Batch 작업을 테스트하거나, 개발 단계에서 사용하기 적합합니다. 하지만, 실제 운영 환경에서는 데이터베이스를 사용하여 Batch 작업을 구성하는 것이 좋습니다.

JpaBatchConfiguration

JpaBatchConfiguration은 JPA 기반의 데이터베이스 연동을 처리

JpaBatchConfiguration 은 Spring Batch에서 JPA 기반의 데이터베이스 연동을 위해 사용됩니다. 이 클래스는 JobRepository, TransactionManager, EntityManagerFactory, JobLauncher 등을 설정합니다.

JpaBatchConfiguration 은 Hibernate JPA 구현체를 사용하여 EntityManagerFactory 를 생성합니다. 따라서 개발자가 다른 JPA 구현체를 사용하려면, JpaBatchConfiguration 클래스를 상속받아 새로운 설정 클래스를 작성해야 합니다.

JpaBatchConfiguration 는 JpaBatchConfigurer 객체를 생성하고 Bean 으로 등록한다.

JpaBatchConfigurer

JpaBatchConfigurer 는 BasicBatchConfigurer 를 상속받아 구현한 클래스로 JPA 관련 객체를 설정하는 설정 클래스다.

JpaBatchConfigurer는 Batch 환경을 구성하는 데 사용됩니다. 이를 위해, JpaBatchConfigurer는 EntityManagerFactory, JpaTransactionManager, JpaJobRepository 등의 구성 요소를 구성합니다. 또한, 데이터베이스 연결 정보와 JPA 설정을 구성하고, 필요한 빈을 등록합니다.

JpaBatchConfigurer는 일반적으로 DefaultBatchConfigurer를 상속하여 구현됩니다. DefaultBatchConfigurer는 가장 기본적인 Batch 환경을 구성하는 클래스이며, 모든 Batch 구성 요소를 기본값으로 구성합니다. JpaBatchConfigurer는 이러한 DefaultBatchConfigurer를 상속하여, JPA를 사용하여 Batch 작업을 구성할 수 있도록 확장한 것입니다.

JpaBatchConfigurer를 사용하면, 개발자는 JPA를 사용하여 Batch 작업을 쉽게 구성할 수 있습니다. 또한, JPA를 사용하므로서 데이터베이스와의 매핑 작업이 간단해지며, 유지보수성이 향상됩니다.

BatchConfigurerConfiguration.java

@ConditionalOnClass(PlatformTransactionManager.class)
@ConditionalOnBean(DataSource.class)
@ConditionalOnMissingBean(BatchConfigurer.class)
@Configuration(proxyBeanMethods = false)
class BatchConfigurerConfiguration {

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

@Bean
BasicBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource,
@BatchDataSource ObjectProvider<DataSource> batchDataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {

return new BasicBatchConfigurer(properties, batchDataSource.getIfAvailable(() -> dataSource),
transactionManagerCustomizers.getIfAvailable());
}

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(EntityManagerFactory.class)
@ConditionalOnBean(name = "entityManagerFactory")
static class JpaBatchConfiguration {

@Bean
JpaBatchConfigurer batchConfigurer(BatchProperties properties, DataSource dataSource,
@BatchDataSource ObjectProvider<DataSource> batchDataSource,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers,
EntityManagerFactory entityManagerFactory) {

return new JpaBatchConfigurer(properties, batchDataSource.getIfAvailable(() -> dataSource),
transactionManagerCustomizers.getIfAvailable(), entityManagerFactory);
}

}

}

BatchAutoConfiguration

  • 스프링 배치가 초기화 될때 자동으로 실행되는 설정 클래스
  • Job 을 실행하는 JobLauncherApplicationRunner Bean 을 생성한다.

BatchConfigurationSelector

BatchConfigurationSelector 클래스를 @EnableBatchProcessing 에 의해 Bean 으로 등록을 한다.

BatchConfigurationSelector 클래스 내부에서는 modular Key 여부에 따라 ModularBatchConfiguration 혹은 SimpleBatchConfiguration 를 스프링 빈으로 등록한다.

BatchConfigurationSelector.java

public class BatchConfigurationSelector implements ImportSelector {
public BatchConfigurationSelector() {
}

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;

// modular Key 여부에 따라 ModularBatchConfiguration 혹은 SimpleBatchConfiguration 를 스프링 빈으로 등록
if (attributes.containsKey("modular") && attributes.getBoolean("modular")) {
imports = new String[]{ModularBatchConfiguration.class.getName()};
} else {
imports = new String[]{SimpleBatchConfiguration.class.getName()};
}

return imports;
}
}
Share