spring batch의 효자 클래스 카지노 게임 추천Step
본 글의 설명과 코드는 spring-batch의 4.3.x 버전을 기준으로 한다. 출처: spring-batch/4.3.x
지난 글 Spring batch와 @Transactional에서 spring batch(이하 스프링 배치)는 @Transaction 사용을 왜 막는가에 대해서 알아봤다. 이슈의 원인이 됐던 카지노 게임 추천Step을 많이 언급했었다. 그래서 이번 글에서는 카지노 게임 추천Step의 생성과 동작을 코드를 보며 분석하려 한다. 카지노 게임 추천Step은 Step 인터페이스를 구현한 클래스로 스프링 배치에서 범용적으로 사용되는 Step의 구현체이다. 우리가 쓰고 있던 생성 해서 사용하고 있던 Step은 많은 경우에 카지노 게임 추천Step으로 구현된 인터페이스였을 것이다.
아래 예제 코드와 같이 StepBuilder를 활용해서 Chunk, ItemReader, ItemProcessor, ItemWriter로 빌드하는 방식으로 Step 생성한다. 가장 보편적인 Step 생성 코드인데 여기서 생성되는 Step 역시 구현체는 카지노 게임 추천Step이다.
@Bean
publicStepstep(JobRepository jobRepository) {
return new StepBuilder("step", jobRepository)
.<Trade, Tradechunk(2)
.reader(itemReader())
.processor(itemProcessor())
.writer(itemWriter())
.build();
}
카지노 게임 추천Step에 대해서 알아보면 스프링 배치의 기본 원리에 대해서 이해하는데 도움이 된다.
카지노 게임 추천Step 관련 코드를 살펴보며 위 코드에서 주입한 ItemReader, ItemProcessor, ItemWriter가 어떻게 동작하고 Chunking은 어떻게 동작하는지 살펴보려 한다. 우선 카지노 게임 추천Step이 어떻게 생성되는지부터 알아야 한다.
StepBuilder의 빌드 메서드인 .chunk(), reader(), processor(), writer()는 모두 SimpleStepBuiler 타입을 생성해서 반환한다.
public<I, O SimpleStepBuilder<I, O chunk(int chunkSize) {
returnnew SimpleStepBuilder<I, O(this).chunk(chunkSize);
}
아래 세 개 Builder 메서드는 SimpleStepBuilder에 정의돼있다.
publicSimpleStepBuilder<I, O reader(ItemReader<? extends I reader) {
this.reader = reader;
returnthis;
}
publicSimpleStepBuilder<I, O processor(ItemProcessor<? super I, ? extends O processor) {
this.processor = processor;
returnthis;
}
publicSimpleStepBuilder<I, O writer(ItemWriter<? super O writer) {
this.writer = writer;
returnthis;
}
그리고 마침내 build 메서드는 카지노 게임 추천Step을 생성해서 반환한다.
@Override
public카지노 게임 추천Stepbuild() {
registerStepListenerAsItemListener();
registerAsStreamsAndListeners(reader, processor, writer);
returnsuper.build();
}
SimpleStepBuilder의 부모는 Abstract카지노 게임 추천StepBuilder 클래스이다. build() 함수 내부에서 부모의 메서드를 호출하는데 부모의 build() 메서드에 카지노 게임 추천Step을 세팅하는 핵심들이 로직들이 모여있다. 이곳에서 카지노 게임 추천Step이 초기화되고 카지노 게임 추천Step 동작하는데 필요한 RepeatOperations(stepOperations), TransactionManager, 카지노 게임 추천이 생성된다. 카지노 게임 추천은 ItemReader, ItemProcessor, ItemWriter의 조합이라고 생각하면 쉽다.
public카지노 게임 추천Stepbuild() {
registerStepListenerAsChunkListener();
카지노 게임 추천Step step = new 카지노 게임 추천Step(getName());
super.enhance(step);
step.setChunkListeners(chunkListeners.toArray(new ChunkListener[0]));
if (this.transactionManager != null) {
step.setTransactionManager(this.transactionManager);
}
if (transactionAttribute != null) {
step.setTransactionAttribute(transactionAttribute);
}
if (stepOperations == null) {
stepOperations = new RepeatTemplate();
...(중략)
}
step.setStepOperations(stepOperations);
step.set카지노 게임 추천(create카지노 게임 추천());
...(중략)
return step;
} (링크)
카지노 게임 추천은 create카지노 게임 추천 메서드에서 생성된다. create카지노 게임 추천은 추상 메서드로 구현체는 자식 클래스인 SimpleStepBuilder가 갖고 있다. 카지노 게임 추천 생성에 대한 제어는 Abstract카지노 게임 추천StepBuilder가 아닌 상속한 클래스가 갖도록 코드가 구조화돼있다. 코드의 주석을 보면서 따라가보자.
@Override
protected카지노 게임 추천create카지노 게임 추천() {
// reader와 writer는 nullable 하지 않다.
Assert.state(reader != null, "ItemReader must be provided");
Assert.state(writer != null, "ItemWriter must be provided");
// RepeatOperations 타입의 chunkOperations를 생성해 chunkProvider가 반복 동작하도록 한다.
// chunk 크기만큼 ItemReader가 Item을 읽기 위해서다.
RepeatOperations repeatOperations = createChunkOperations();
// ChunkProvider는 말 그대로 Item의 묶음인 Chunk<I를 공급하는 역할을 한다.
// Item을 읽어오는 ItemReader가 주입된다.
SimpleChunkProvider<I chunkProvider = new SimpleChunkProvider<(getReader(), repeatOperations);
// chunkProcessor에는 아이템을 처리하고 쓰기 위한 Processor와 Writer가 주입된다.
SimpleChunkProcessor<I, O chunkProcessor = new SimpleChunkProcessor<(getProcessor(), getWriter());
...(중략)
//*
* 최종적으로 초기화된 chunkProvider와 chunkProcessor를 주입해의
* ChunkOriented카지노 게임 추천 타입의 카지노 게임 추천을 반환한다.
*//
ChunkOriented카지노 게임 추천<I 카지노 게임 추천 = new ChunkOriented카지노 게임 추천<(chunkProvider, chunkProcessor);
카지노 게임 추천.setBuffering(!readerTransactionalQueue);
return카지노 게임 추천;
} (링크)
위 코드에서 주입된 ItemReader, ItemWriter, ItemProcessor는 Builder에서 정의돼 주입된 객체들이다. 즉 카지노 게임 추천은 위 세 개 reader, writer, processor의 조합인 것이다. 그리고 카지노 게임 추천은 ChunkOriented카지노 게임 추천 타입의 클래스로 생성된다. ChunkOriented카지노 게임 추천은 카지노 게임 추천의 구현체로 카지노 게임 추천이 동작하는 로직을 구현하고 있다.
카지노 게임 추천Step은 지난 시간에 공부했던 대로 Chunk 단위로 트랜잭션에서 처리한다.
그리고 해당 로직은 ChunkTransactionCallback의 doInTransaction에 위치하고 있다. 카지노 게임 추천의 execute메서드를 호출해 카지노 게임 추천을 실행한다.
@Override
publicRepeatStatusdoInTransaction(TransactionStatus status) {
... (중략)
try{
result = 카지노 게임 추천.execute(contribution, chunkContext);
// 카지노 게임 추천이 result가 null이면 모든 chunk가 처리된 것이므로 카지노 게임 추천Step을 종료한다.
if(result == null) {
result = RepeatStatus.FINISHED;
}
}
... (후략)
(링크)
ChunkOriented카지노 게임 추천의 execute 메서드를 살펴보자. inputs가 null인 경우 chunkProvider로 Chunk<I 타입의 inputs를 공급받아 chunkProcessor로 넘긴다. 로직은 꽤나 단순한다. 그리고 마지막으로 inputs.isEnd를 통해 inputs가 끝인지 아닌지를 체크해서 RepeatStatus를 반환한다.
@Override
publicRepeatStatus execute(StepContribution contribution, ChunkContext chunkContext)
...(중략)
if (inputs == null) {
inputs = chunkProvider.provide(contribution);
(중략)
}
chunkProcessor.process(contribution, inputs);
(중략)
return RepeatStatus.continueIf(!inputs.isEnd());
}
(링크)
RepeatStatus.continueIf는 파라미터로 넘어온 continuable이 true이면 CONTINUEABLE을 반환해서 카지노 게임 추천이 다시 호출돼 다음 Chunk를 처리하도록 하고 false이면 FINISHED를 호출해 카지노 게임 추천을 재호출 하지 않고 종료하도록 한다.
publicstaticRepeatStatuscontinueIf(boolean continuable) {
returncontinuable ? CONTINUABLE : FINISHED;
}
SimpleStepBuilder의 create카지노 게임 추천 메서드를 보면 chunkProvider와 chunkProcessor를 각각 SimpleChunkProvider와 SimpleChunkProcessor 타입의 클래스로 생성한다. 각 클래스의 provide 메서드와 process 메서드를 살펴보며 아이템 공급과 처리가 어떻게 동작하는지 살펴보자.
SimpleChunkProvider<I chunkProvider = new SimpleChunkProvider<(getReader(), repeatOperations);
SimpleChunkProcessor<I, O chunkProcessor = new SimpleChunkProcessor<
우선 SimpleChunkProvider의 provide이다. repeatOperations로 itemReader.read() 반복 호출하여 읽은 item을 Chunk(inputs)에 추가한다. itemReader가 null을 반환하면 repeatOperation를 종료(RepeatStatus.FINISHED)한다. 마지막으로 읽어 온 Item Chunk를 반환한다.
@Override
publicChunk<I provide(final StepContribution contribution) throws Exception {
final Chunk<Iinputs = new Chunk<();
repeatOperations.iterate(new RepeatCallback() {
@Override
public RepeatStatus doInIteration(final RepeatContext context) throws Exception {
I item = null;
... (중략)
try {
item= read(contribution, inputs);
}
... (중략
if (item == null) {
inputs.setEnd();
return RepeatStatus.FINISHED;
}
inputs.add(item);
contribution.incrementReadCount();
return RepeatStatus.CONTINUABLE;
}
});
returninputs;
}
(링크)
(doRead는 read 메서드에서 내부에서 호출된다)
protected finalIdoRead() throws Exception {
try {
listener.beforeRead();
I item= itemReader.read();
if (item != null) {
listener.afterRead(item);
}
returnitem;
}
...(중략)
}
ChunkProvider가 제공한 Item Chunk를 처리하는 ChunkProcessor의 process가 실행된다. isComplete, transform, write 메서드가 차례대로 호출된다.
@Override
public final void process(StepContribution contribution, Chunk<I inputs) throws Exception {
...(중략)
if (isComplete(inputs)) {
return;
}
Chunk<O outputs = transform(contribution, inputs);
contribution.incrementFilterCount(getFilterCount(inputs, outputs));
write(contribution, inputs, getAdjustedOutputs(inputs, outputs));
} (링크)
Item Chunk가 비어있으면 즉시 process를 종료한다. 더 이상 처리할 아이템이 없기 때문이다.
protectedbooleanisComplete(Chunk<I inputs) {
returninputs.isEmpty();
}
Chunk에 item이 있는 경우 transform 함수를 실행해 Chunk안에 담긴 item을 각각 순회하며 처리한다. 그리고 처리한 아이템을 Chunk<O 타입의 outputs에 담아 반환한다.
protectedChunk<O transform(StepContribution contribution, Chunk<I inputs) throws Exception {
Chunk<O outputs= new Chunk<();
for (Chunk<I.ChunkIterator iterator = inputs.iterator(); iterator.hasNext();) {
final I item = iterator.next();
O output;
...(중략)
try {
output = doProcess(item);
}
...(중략)
if (output != null) {
outputs.add(output);
} else {
iterator.remove();
}
}
returnoutputs;
} (링크)
(카지노 게임 추천Step을 생성할 때 빌더에서 주입해준 ItemProcessor가 실행된다)
protected final O doProcess(I item) throws Exception {
...(중략)
try{
listener.beforeProcess(item);
O result = itemProcessor.process(item);
listener.afterProcess(item, result);
returnresult;
}
...(중략)
}
마지막으로 write 메서드이다. ItemProcessor가 처리한 Chunk<O를 통째로 ItemWriter에 넘겨 쓰기 작업을 실행한다.
protectedvoidwrite(StepContribution contribution, Chunk<I inputs, Chunk<O outputs) throws Exception {
...(중략)
try {
doWrite(outputs);
}
...(중략)
}(링크)
protected finalvoiddoWrite(Chunk<O items) throws Exception {
...(중략)
try{
listener.beforeWrite(items);
writeItems(items);
doAfterWrite(items);
}
...(중략)
}
(역시 ItemWriter가 실행된다)
protectedvoidwriteItems(Chunk<O items) throws Exception {
if(itemWriter != null) {
itemWriter.write(items);
}
}
정리하면 스프링 배치에서 흔히 사용하는 Chunk 사이즈 별로 아이템을 읽고 처리하고 쓰는 Step은 카지노 게임 추천Step이었다(아닌 경우도 있다).
카지노 게임 추천Step 내부에는 카지노 게임 추천이 있는데 구현체는 ChunkOriented카지노 게임 추천이라는 클래스이다.
이 클래스는 ItemReader, ItemProcessor, ItemWriter를 chunk 크기만큼 읽고 처리하고 쓴다. 카지노 게임 추천Step은 ChunkTransactionCallback으로 카지노 게임 추천을 호출함으로써 chunk 단위로 트랜잭셔널하게 처리되도록 했다.
카지노 게임 추천Step의 코드 흐름을 단순화된 시퀀스 다이어그램으로 표현하면 다음과 같다.