2024.03.06 - [Spring/Batch Programming] - Spring Batch 실습(2)
이제 요구조건을 추가해서 테스트해보도록 할 것이다.
고객이 1년동안 접속하지 않으면 휴먼계정으로 전환한다. → 이때까지한 코드- 휴면전환 일주일 전인 고객에게 로그인 하지않으면 휴먼전환 된다는 안내 메일 전송
구현 해야할 부분은 2번이다.
public interface Job {
JobExecution execute();
}
기존 클래스였던 Job을 조건에서 2개의 작업이 생겼으므로, 인터페이스로 변경해줬다.
구현하기 전에 Spring Batch가 정확하게 어떻게 동작하는지 알고 가보도록 하자.
변경전
tasklet.execute();
변경후
steps.forEach(Step::execute);
Spring Batch를 조금더 간단히 이해하기위해 그려본 그림이다. 각 스텝마다 read, processing, save과정이 있고, 스텝간의 순서도 명확하다. 따라서 변경후 코드에서 List로 만든 steps라는 것을 계속해서 execute하는 부분이 있다.
Job : 전체적인 Batch 처리
Step : Job의 구성요소(독립적, 순차적)
→ Step은 굳이 3단계의 과정을 안거치고 구현해도 된다.
그리고 빌더 패턴도 직접 작성해봤다
public class StepJobBuilder {
private final List<Step> steps;
private JobExecutionListener jobExecutionListener;
public StepJobBuilder() {
this.steps = new ArrayList<>();
}
public StepJobBuilder start(Step step){
if(steps.isEmpty()){
steps.add(step);
} else{
steps.set(0, step);
}
return this;
}
public StepJobBuilder next(Step step){
steps.add(step);
return this;
}
public StepJobBuilder listener(JobExecutionListener jobExecutionListener){
this.jobExecutionListener = jobExecutionListener;
return this;
}
public StepJob build(){
return new StepJob(steps, jobExecutionListener);
}
}
이제 configuration 파일에서 어떻게 변화가 일어났는지 보자
생성자 패턴
List<Step> steps = Arrays.asList(step1, step2, step3);
return new StepJob(steps, null);
빌더 패턴
return new StepJobBuilder()
.start(step1)
.next(step2)
.next(step3)
.build();
눈에 띄게 직관적이고, 수정도 용이 해졌다.
근데 여기서도 살짝 불편한 부분이 있다. 바로 위에서 언급한 새로 만들어준 tasklet.execute();과steps.forEach(Step::execute); 의 차이 말고는 두클래스의 차이가 없다는 것이다. 따라서 이 부분도 관심사를 분리하고, 확장하기 쉬운 구조로 만들어 본다,, 어디까지 분리하는거야
public abstract class AbstractJob implements Job{
private final JobExecutionListener jobExecutionListener;
public AbstractJob(JobExecutionListener jobExecutionListener) {
this.jobExecutionListener = Objects.requireNonNullElseGet(jobExecutionListener, () -> new JobExecutionListener() {
@Override
public void beforeJob(JobExecution jobExecution) {
}
@Override
public void afterJob(JobExecution jobExecution) {
}
});
}
@Override
public JobExecution execute() {
JobExecution jobExecution = new JobExecution();
jobExecution.setStatus(BatchStatus.STARTING);
jobExecution.setStartTime(LocalDateTime.now());
jobExecutionListener.beforeJob(jobExecution);
try {
doExecute();
jobExecution.setStatus(BatchStatus.COMPLETED);
} catch (Exception e){
jobExecution.setStatus(BatchStatus.FAILED);
}
jobExecution.setEndTime(LocalDateTime.now());
jobExecutionListener.afterJob(jobExecution);
return jobExecution;
}
public abstract void doExecute();
}
추상 클래스로 구현해봤다. 굳이 추상클래스를 사용한 이유는, 변경이 필요한 부분은 인터페이스처럼 상황에 맞게 수정해서 사용하고, 공통적인 로직은 그대로 클래스안에 구현 해주기 위해서이다. 위에 코드에서 나는 doExecute만 상황에 맞게 구현해주면 된다!!
이제 Spring Batch의 형태는 갖춘 것같고, 다음 글에서는 완성된 로직의 Configuration을 만들어 보고자 한다.
ㅎㅇㅌ
2024.03.10 - [Spring/Batch Programming] - Spring Batch 실습(4)
'Spring > Batch Programming' 카테고리의 다른 글
Spring Batch 도메인 용어, 실전 (3) | 2024.03.12 |
---|---|
Spring Batch 실습(4) (0) | 2024.03.10 |
Spring Batch 실습(2) (0) | 2024.03.06 |
Spring Batch 실습(1) (1) | 2024.03.06 |
Spring Batch (0) | 2024.03.05 |