스프링 빈 스코프


📌

시나리오

  1. 프로토타입 스코프의 빈을 스프링 컨테이너에 요청한다.
  2. 스프링 컨테이너는 이 시점에 프로토타입 빈을 생성하고, 필요한 의존관계를 주입한다.
  3. 스프링 컨테이너는 생성한 프로토타입 빈을 클라이언트에게 반환한다.
  4. 이후 같은 요청이 오면 새로운 프로토타입 빈을 생성하여 반환한다.

핵심은 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화 까지만 처리하고 더 이상 관리하지 않는다. 그래서, @PreDestory 콜백 메서드가 호출되지 않기 때문에 호출이 필요하다면 해당 메서드를 직접 호출해야한다.

📑

정리하기

  • 스프링 컨테이너에 요청하는 시점에 새로 생성된다.
  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화 까지만 관여하고 그 이후엔 관리하지 않는다.
  • 위와 같은 이유 때문에 소멸 콜백 메서드가 호출되지 않는다.
  • 프로토타입 빈은 참조하는 클라이언트가 직접 관리해야한다.

싱글톤 빈이 프로토타입 빈 객체를 참조하고 있어 생성자로 의존관계를 주입한다면, 싱글톤 빈은 생성과 의존관계 주입 과정을 한 번 거친 후 스프링 컨테이너가 관리하기 때문에 프로토타입 빈은 한 번만 주입되고 그 이후로 계속 재사용된다. 즉, 프로토타입 빈이 의도대로 새롭게 생성되지 않는 문제가 발생한다.

그럼, 이 문제를 어떻게 해결 해야할까? 싱글톤 빈에 의존관계로 주입하지 말고, 싱글톤 빈 내부에서 스프링 컨테이너에 프로토타입 빈을 조회하여 참조하도록 변경하면 이 문제를 해결할 수 있는데, 이렇게 설계하는 것은 스프링에 의존적이기 때문에 좋은 설계 방식은 아니다.

의존 관계를 주입 받지 않고, 탐색하는 과정을 DL(DependencyLookup) 이라고 하며 스프링에서 제공하는 이 방법을 통해 문제를 풀어나갈 수 있다.

@ObjectProvider 사용하기

스프링 컨테이너에서 빈을 더 편리하게 조회 하는 대리자로, ApplicationContext 를 직접 주입 받지 않고 사용할 수 있는 편의 기능을 제공한다. 단, 아직 스프링 프레임워크에 의존 하는 단점을 해결하진 못하였다. 이를 해결하기 위해 자바 표준 프로바이더 객체를 사용하면 된다.

@Autowired  
private ObjectProvider<PrototypeBean> prototypeBeanProvider;  
  
public int logic() {  
    PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
    ...
    }

자바 표준 @Provider 사용하기

자바 표준으로 사용할 수 있기 때문에 스프링 프레임워크에 의존적인 단점을 해결할 수 있지만, 별도의 라이브러리를 설치해야 하는 불편함이 있다.

프로바이더는 프로토타입 빈을 해결하기 위해서만 사용하지 않고 순환 참조하는 의존성, 지연 로딩이 필요한 빈을 제어할 때 프로바이더를 사용할 수 있다.

의존성 설치

// Provider  
implementation 'jakarta.inject:jakarta.inject-api:2.0.1'

프로바이더 사용

@RequiredArgsConstructor  
static class ClientBean {  
  
    private final Provider<PrototypeBean> prototypeBeanProvider;  
  
    public int logic() {  
        PrototypeBean prototypeBean = prototypeBeanProvider.get();  
        prototypeBean.addCount();  
        return prototypeBean.getCount();  
    }}

웹 스코프는 웹 환경에서만 동작하고, 프로토타입과 달리 종료 시점까지 관리하기 때문에 종료 콜백 메서드가 호출된다.

📌

웹 스코프 종류

  • request: HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프이며, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.
  • session: HTTP 세션과 동일한 생명 주기를 갖고 있는 스코프
  • application : 서블릿 컨텍스트와 동일한 생명주기를 가지는 스코프
  • websocket : 웹 소켓과 동일한 생명주기를 가지는 스코프

HTTP request 요청 당 각각 할당되는 request 스코프