Post

(Spring Batch) scope bean의 이해

Scope Bean의 이해 (@JobScope, @StepScope)

Scope Bean의 생명 주기와, 글로벌 싱글턴으로 동작하는 일반 Bean의 생명 주기가 달라 처음에는 헷갈릴 수 있다.

  1. Job을 생성하는 Bean에는 @JobScope를 붙일 수 없다.
    • 붙이면 No context holder available for job scope 에러 발생한다.
    • Scope Bean은 해당 Scope 내에서의 LifeCycle을 가지는 Bean을 의미하는데, 어떤 Job이 시작되어 그 안으로 들어가면 그 때 부터 JobScope가 되는 것이다.
    • 일단 Job이 만들어진 이후에야 JobScope가 존재 할 수 있는 것이기 때문에 Job 객체를 만드는 것 자체는 JobScope가 될 수 없다. (즉, Job 안에서 새로운 Job을 만드는 것은 불가)
  2. 같은 이유로 Step을 생성하는 Bean에는 @StepScope를 붙일 수 없다. @JobScope는 붙일 수 있다.
    • 즉, Job 안에서 Step을 생성 하는 것은 가능
  3. Job이나 Step의 실행 Context 내에서만 생존해도 상관 없는 Job과 Step의 부속품들 (Listener, Tasklet 등)은 Scope여도 상관 없고, JobScope를 붙이면 Job 별로, StepScope를 붙이면 Step 별로 해당 context 내에서 개별 생성된다. (즉, 여러개가 될 수 있다.)
  4. JobParameter는 JobScope(StepScope) 내에서만 불러올 수 있다.
    • Job 여러개 실행 할 때, Job 마다 JobParameter를 다르게 가져가려면 JobParamter는 global context가 아니라 job context에서 관리되어야만 하기 때문인 듯 하다.

Scope Bean의 초기화 / 생성자 호출 시점

  • Scope Bean은 어떤 잡이든, 잡이 실행 되고 + DI 된 후 + 해당 Bean에 최초로 접근 할 때 생성자 호출하며 초기화 된다.
    • 해당 Scope Context 내에서만 생존하는 Bean이기 때문에 Context가 생성된 다음에 초기화 하게 된다.
    • Context가 여러개면 여러번 생성/초기화 되어야 하므로, 미리 1개만 초기화 해놓는다는건 앞뒤가 맞지 않는다.
  • 해당 Bean에 접근이 발생하지 않는다면 생성자도 호출되지 않는다.
  • 초기화 시점이 lazy 일 뿐, DI는 정상적으로 동작한다.

일반 Bean에서 Scope Bean을 참조한다면

1
2
3
Scope 'job' is not active for the current thread;
consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
nested exception is java.lang.IllegalStateException: No context holder available for job scope

일반 Bean은 Job Context 바깥에서도 존재 할 수 있기 때문에
@JobScope로 설정된 Bean을 스코프가 설정되지 않은 다른 Bean에서 & Job Context가 아닌 상태에서 참조하는 경우, 위 에러 발생한다.

e.g., 애플리케이션 시작 시점에 생성되는 Bean 로직에서 JobScope Bean을 참조하는 경우. 그 시점에는 JobScope가 생성되지 않아 JobScope Bean이 제대로 초기화 되기 전이다.

This post is licensed under CC BY 4.0 by the author.