본문 바로가기

강의/스프링배치

스프링 배치 실행 - JobBuilderFactory / JobBuilder

 

 

지금까지는 SimpleJobBuilder를 사용했다.

Job을 생성하는 것 자체가 내부적으로 SimpleJobBuilder를 사용한다는 것이다.

 

FlowJobBuilder는 나중에 살펴볼 예정이다.

 

 

Job을 생성하기 위한 절차적인 과정을 살펴볼 것이다.

simplejobbuilder는 step만 들어갈 수 있고

flowjobbuilder는 step 또는 flow가 들어갈 수 있다.

 

 

CommonJobProperties는 job이 실행될 때 필요한 항목들을 다 가지고 있다.

JobBuilderHelper는 SimpleJobRepository를 참조한다.

 

 

JobBuilder가 생성되는 클래스간의 계층 및 구조를 명확하게 이해하면 Job Configuration을 구성할 때 많은 도움이 된다.

JobRepository는 빌더 클래스를 통해 Job 객체에 전달되어 메타데이터를 기록하는데 사용된다.

 

JobBuildeFactory는 get 메서드가 있고 jobRepository클래스를 이용하여 jobBuilder 클래를 생성한다.

JobBuilderFactory, StepBuilderFactory 클래스는 SimplebatchConfiguration에서 생성된다.

부모인 AbstractBatchconfiguration에 가면 jobBuilderFactory와 StepBuilderFactory를 생성하는 과정이 있기 때문에

Spring batch가 초기화 될 때 생성이 되는 것이다.

JobBuilder는 JobBuilderHelper 클래스를 상속 받고 있다.

하위 builder를 생성한다.

조건에 의해서 생성하는 하위 builder가 구분이 되는데

SimpleJobBuilder또는 FlowJobBuilder를 생성한다.

JobBuilderHelper 클래스는 CommonJobProperties 공통적인 job의 속성들을 가지고 있는 클래스이다.

job을 수행하는데 있어서 필요한 속성들을 가지고 있다.

 

 

동작 순서

1. Abstractbatchconfiguration클래스 afterPropertiesSet 메서드에서 jobBuilderFactory와 stepBuilderFactory 객체를 생성하고 Bean으로 등록함.

 

2. 사용자가 생성한 configuration을 살펴보면 jobBuilderFactory를 이용하여 job을 생성, start할 때 step을 넣었기 때문에 SimplejobBuilder가 생성된 것을 확인할 수 있음.

 

3. SimpleJobBuilder는 step list를 가지고 있고, next를 통해 step list에 각각의 step을 넣

 

package io.springbatch.springbatch;


import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@RequiredArgsConstructor
@Configuration
public class ExecutionContextConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final ExecutionContextTasklet1 executionContextTasklet1;
    private final ExecutionContextTasklet2 executionContextTasklet2;

    private final JobExecutionListener jobRepositoryListener;

    @Bean
    public Job batchJob2() {
        return jobBuilderFactory.get("batchJob1")
                .start(flow())
                .next(step5())
                .end()
                .build();
    }

    @Bean
    public Flow flow() {
        // step과 비슷한 level을 flow라고 봐도 무방할 것 같다.
        FlowBuilder<Flow> flowBuilder = new FlowBuilder<>("flow");
        // flow는 end를 구성해야한다.
        flowBuilder.start(step3())
                .next(step4())
                .end();

        return flowBuilder.build();
    }
    @Bean
    public Step step3() {
        return stepBuilderFactory.get("step3")
                .tasklet((stepContribution, chunkContext) -> {
                    System.out.println("step3 was executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step step4() {
        return stepBuilderFactory.get("step4")
                .tasklet((stepContribution, chunkContext) -> {
                    System.out.println("step3 was executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step step5() {
        return stepBuilderFactory.get("step3")
                .tasklet((stepContribution, chunkContext) -> {
                    System.out.println("step5 was executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}