Skip to the content.

참조:https://oingdaddy.tistory.com/180

[[Spring Batch] Listener Example (Springboot based)

지난 글에서 다뤘던 Springboot Batch Chunk Example에서 소스들을 살펴 볼때 Listener도 살짝 나왔다. 우리가 정의한 Job이나 Step 실행 전 후로 필요한 공통 작업을 기술하기 위해 주로 사용되며 사용된다.

oingdaddy.tistory.com](https://oingdaddy.tistory.com/180)

실제로 스프링 배치에서는 거의 모든 측면에서 생명주기가 잘 정의되있다.

이를 바탕으로 스프링 배치는 생명 주기의 여러 시점에 로직을 추가할 수 있는 기능을 제공한다.

잡 실행과 관련이 있다면 JobExecutionListener를 사용할 수 있다.

이 인터페이스는 beforeJob과 afterJob의 두 메서드를 제공한다.

말그대로 잡주기에서 가장 먼저 실행되거나 가장 나중에 실행되는것을 말한다.

@Slf4j
public class SavePersonListener {

	//어노테이션을 이용한 리스너(Step)
    public static class SavePersonStepExecutionListener {
        @BeforeStep
        public void beforeStep(StepExecution stepExecution) {
            log.info("beforeStep");
        }

        @AfterStep
        public ExitStatus afterStep(StepExecution stepExecution) {
            log.info("afterStep : {}", stepExecution.getWriteCount());
            if (stepExecution.getWriteCount() == 0) {
                return ExitStatus.FAILED;
            }
            return stepExecution.getExitStatus();
        }
    }

	//JobExecutionListener 구현체를 이용한 리스너(Job)
    public static class SavePersonJobExecutionListener implements JobExecutionListener {

        @Override
        public void beforeJob(JobExecution jobExecution) {
            log.info("beforeJob");
        }

        @Override
        public void afterJob(JobExecution jobExecution) {
            int sum = jobExecution.getStepExecutions().stream().mapToInt(StepExecution::getWriteCount).sum();
            log.info("afterJob : {}", sum);
        }
    }

	//어노테이션을 이용한 리스너(Job)
    public static class SavePersonAnnotationJobExecutionListener {

        @BeforeJob
        public void beforeJob(JobExecution jobExecution) {
            log.info("annotationBeforeJob");
        }

        @AfterJob
        public void afterJob(JobExecution jobExecution) {
            int sum = jobExecution.getStepExecutions().stream().mapToInt(StepExecution::getWriteCount).sum();
            log.info("annotationAfterJob : {}", sum);
        }
    }

}
    @Bean
    public Job savePersonJob() throws Exception {
        return this.jobBuilderFactory.get("savePersonJob")
                .incrementer(new RunIdIncrementer())
                .start(this.savePersonStep(null))
                //리스너 사용(Job)
                .listener(new SavePersonListener.SavePersonJobExecutionListener())
                .listener(new SavePersonListener.SavePersonAnnotationJobExecutionListener())
                .build();
    }

    @Bean
    @JobScope
    public Step savePersonStep(@Value("#{jobParameters[allow_duplicate]}") String allowDuplicate) throws Exception {
        return this.stepBuilderFactory.get("savePersonStep")
                .<Person, Person>chunk(10)
                .reader(itemReader())
                .processor(new DuplicateValidationProcessor<>(Person::getName, Boolean.parseBoolean(allowDuplicate)))
                .writer(itemWriter())
                //리스너 사용(Step)
                .listener(new SavePersonListener.SavePersonStepExecutionListener())
                .build();
    }