ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 10. Scope
    BackEnd/Spring Batch 2021. 12. 24. 04:42
    반응형

      스프링 컨테이너에서 빈이 관리되는 범위로는 singleton, prototype, request, session, application이 있으며, 기본은 singleton으로 생성됩니다.

     

    Spring Batch Scope

      스프링 배치 스코프로는 @JobScope@StepScope가 있으며, Job과 Step의 빈 생성과 실행에 관여합니다. 프록시 모드를 기본값으로 하는 스코프로, 해당 스코프가 선언되면 빈의 생성이 애플리케이션 구동 시점이 아닌 빈의 실행 시점에 이루어집니다. 병렬처리 시 각 스레드마다 생성된 스코프 빈이 할당되기 때문에 스레드에 안전하게 실행이 가능합니다.

    • @Values를 주입해서 빈의 실행 시점에 값을 참조할 수 있으며 일종의 Lazy Binding이 가능해 진다.
    • @Value("#{jobParameters[파라미터명]}"), @Value("#{jobExecutionContext[파라미터명]"}), @Value("#{stepExecutionContext[파라미터명]}"
    • @Values를 사용할 경우 빈 선언문에 @JobScope, @StepScope를 정의하지 않으면 오류를 발생하므로 반드시 선언해야 합니다.

     

      @JobScope는 Step 선언문에 정의하며 @Value: jobParameter, jobExecutionContext만 사용가능합니다.

      @StepScope는 Tasklet이나 ItemReader, ItemWriter, ItemProcessor 선언문에 정의하며 @Value: jobParameter, jobExecutionContext, stepExecutionContext 사용이 가능합니다.

     

      @JobScope, @StepScope 어노테이션이 붙은 빈 선언은 애플리케이션 구동 시점에 내부적으로 빈의 Proxy 객체가 생성되며, Job 실행 시 Proxy 객체가 실제 빈을 호출해서 해당 메서드를 실행시키는 구조입니다.

    • @JobScope: @Scope(value="job", proxyMode = ScopedProxyMode.TARGET_CLASS)
    • @StepScope: @Scope(value="step", proxyMode = ScopedProxyMode.TARGET_CLASS)
    package io.springbatch.springbatchlecture;
    
    import lombok.RequiredArgsConstructor;
    import org.springframework.batch.core.*;
    import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
    import org.springframework.batch.core.configuration.annotation.JobScope;
    import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
    import org.springframework.batch.core.configuration.annotation.StepScope;
    import org.springframework.batch.core.job.builder.FlowBuilder;
    import org.springframework.batch.core.job.flow.Flow;
    import org.springframework.batch.core.job.flow.FlowExecutionStatus;
    import org.springframework.batch.core.job.flow.JobExecutionDecider;
    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.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @RequiredArgsConstructor
    @Configuration
    public class JobScope_StepScope_Configuration {
    
        private final JobBuilderFactory jobBuilderFactory;
        private final StepBuilderFactory stepBuilderFactory;
    
        @Bean
        public Job job() {
            return jobBuilderFactory.get("batchJob")
                    // 컴파일 오류가 나지 않기 위해 null 설정
                    .start(step1(null))
                    .next(step2())
                    .listener(new JobListener())
                    .build();
        }
    
        @Bean
        @JobScope
        public Step step1(@Value("#{jobParameters['message']}") String message) {
    
            System.out.println("jobParameters['message'] : " + message);
            return stepBuilderFactory.get("step1")
                    .tasklet(tasklet1(null))
                    .build();
        }
    
        @Bean
        public Step step2() {
            return stepBuilderFactory.get("step2")
                    .tasklet((contribution, chunkContext) -> {
                        System.out.println("step2 has executed");
                        return RepeatStatus.FINISHED;
                    })
                    .build();
        }
    
        @Bean
        @StepScope
        // name: JobListener에서 설정
        public Tasklet tasklet1(@Value("#{jobExecutionContext['name']}") String name){
            return (stepContribution, chunkContext) -> {
                System.out.println("jobExecutionContext['name'] : " + name);
                return RepeatStatus.FINISHED;
            };
        }
    }
    package io.springbatch.springbatchlecture;
    
    import org.springframework.batch.core.JobExecution;
    import org.springframework.batch.core.JobExecutionListener;
    
    public class JobListener implements JobExecutionListener {
    
        @Override
        public void beforeJob(JobExecution jobExecution) {
            jobExecution.getExecutionContext().putString("name", "user1");
        }
    
        @Override
        public void afterJob(JobExecution jobExecution) {
    
        }
    }

    Architecture

    JobScope, StepScope

      Proxy 객체의 실제 대상이 되는 Bean을 등록, 해제하는 역할입니다. 실제 빈을 저장하고 있는 JobContext, StepContext를 가지고 있습니다.

     

    JobContext, StepContext

      스프링 컨테이너에서 생성된 빈을 저장하는 컨텍스트 역할입니다. Job의 실행 시점에서 프록시 객체가 실제 빈을 참조할 때 사용됩니다.

     

    [참고자료]

    인프런-스프링 배치 - Spring Boot 기반으로 개발하는 Spring Batch

    반응형

    'BackEnd > Spring Batch' 카테고리의 다른 글

    12. ItemReader (File)  (0) 2021.12.30
    11. 스프링 배치 청크 프로세스 (Chunk)  (0) 2021.12.24
    09. Flow  (0) 2021.12.23
    08. 배치 상태 유형  (0) 2021.12.22
    07. Step  (0) 2021.12.21

    댓글

Designed by Tistory.