빈 스코프

byeol·2022년 12월 7일
0

9. 빈 스코프

💡 빈 스코프란? 빈이 존재할 수 있는 범위

✔ 스프링이 지원하는 다양한 스코프

  • 싱글톤 : 기본 스코프, 스프링 컨테이너 시작 ~ 종료까지
  • 프로토타입 : 스프링 컨테이너가 빈생성과 의존관계 주입까지만 관여
  • 웹 관련 스코프
    • request : 웹 요청이 들어오고 나갈 때까지 유지
    • session : 웹 세션 생성~ 종료까지
    • application : 웹의 서블릿 컨텍스트와 같은 범위로 유지

✔ 스코프 지정 방법 @Scope("스코프 종류 소문자")

  • 자동
@Scope("prototype")
@Component
public class HelloBean {}
  • 수동
@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
return new HelloBean();
}

💡 프로토타입 스코프

싱글톤 스코프 빈은 조회하면 항상 같은 인스턴스의 스프링 빈을 반환한다.
스프링 컨테이너에 객체 생성하고 그 객체 하나를 주고 받는 것이다.

  • 프로토타입 빈은 요청할 때마다 새로 생성한다.
  • 스프링 컨테이너 생성할 때 같이 생성되는 싱글톤 스코프 빈과 다르게
    조회할 때 생성된다.
  • 스프링 컨테이너는 프로토타입 생성->의존관계 주입-> 초기화 까지만 처리하고
    나머지는 클라이언트에게 권한을 넘김
  • 따라서 @PreDestory 같은 종료 메서드 호출되지 않음

싱글톤 빈과 프로토타입 스코프를 함께 사용하는 경우

static class ClientBean {
   private final PrototypeBean prototypeBean;
   
   @Autowired
   public ClientBean(PrototypeBean prototypeBean) {
         this.prototypeBean = prototypeBean;
    }
   public int logic() {
        prototypeBean.addCount();
        int count = prototypeBean.getCount();
        return count;
   }
}

@Scope("prototype")
static class PrototypeBean {
   private int count = 0;

   public void addCount() { 
     count++;
...
}

포로토타입 스코프 빈은 싱글톤 빈을 생성하고 의존관계 주입하는 시점에 생기게 된다.
싱글톤 타입의 스코프 빈은 한번 생성되는 것이기 때문에 의존관계 주입 또한 한번 일어나게 된다. 따라서 프르토타입 스코프 빈 또한 한번 생성되는 것이고 여러 클라이언트가 프로토타입을 요청할 경우 다른 프로토타입의 빈을 반환하는 것이 아니라 같은 포로토타입 빈을 반환하게 된다.

이는 개발자나 사용자가 의도한 바가 아니기 때문에
싱글톤 빈을 하나 생성하고
프로토타입 빈은 클라이언트가 요청할 때마다 생성될 수 있도록 수정하도록 하자.

💡 프로토타입 스코프와 싱글톤 빈을 함께 사용하는 경우

✔️ 스프링 컨테이너에 싱글톤 빈이 프로토타입을 요청할 때마다 새로운 프로토타입 빈을 생성

static class ClientBean {
  @Autowired
  private ApplicationContext ac;

  public int logic() {
     PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
     prototypeBean.addCount();
     int count = prototypeBean.getCount();
     return count;
    }
}

@Scope("prototype")
static class PrototypeBean {
   private int count = 0;
...
}

위를 보면 싱글톤 빈의 생성자가 프로토타입의 빈을 생성하도록 의존관계를 맺고 있는 것이 아니라 하나의 싱글톤 빈 자체가 스프링 컨테이너를 하나 만들어 놓고 요청이 들어올 때마다 여기에 프로토타입 빈을 생성하고 반환하도록 만들어 놓았다.

의존관계를 맺도록 주입하는 것이 아니라 필요한 의존관계를 찾는 것은 Dependency Lookup 의존관계 조회(탐색)이라고 한다.

그러나 이렇게 스프링 애플리케이션 컨텍스트 전체를 주입받게 되면 스프링 컨테이너에 종속적이 코드

따라서 스프링에 종속적이지 않으면 DL의 기능을 하는 무언가가 필요하다

✔️ ObjectFactory, ObjectProvider

지정할 빈을 컨테이너에서 대신 찾아주는 DL 서비스
ObjectFactory: 구버전, 기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존
ObjectProvider : 신버전, 상속, 옵션, 스트림 처리 등 편의 기능, 별도의 라이브러리 필요 없음, 스프링에 의존

static class ClientBean {

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

prototypeBeanProvider.getObject() : 항상 새로운 프로토타입 빈을 생성
-> objetProvider은 getObject를 호출해서 내부 스프링 컨테이너를 통해 해당 빈을 찾음(DL)

스프링이 제공하는 기능 사용-> 기능이 단순하므로 단위테스트 훨씬 쉬어짐
하지만 그래도 스프링에 의존

✔️JSR-330 Provider

  • javax.inject.Provider라는 자바 표준을 사용
  • javax.inject:javax.inject:1 라이브러리를 gradle에 추가
package javax.inject;
public interface Provider<T> {
  T get();
}

//implementation 'javax.inject:javax.inject:1' gradle 추가 필수
static class ClientBean {

@Autowired
private Provider<PrototypeBean> provider;

 public int logic() {
 PrototypeBean prototypeBean = provider.get();
 prototypeBean.addCount();
 int count = prototypeBean.getCount();
 return count;
}

Provider.get()을 통해서 새로운 프로토타입 빈 생성
get()메서드 하나로 기능이 매우 다양하며
별도의 라이브러리 필요 없음
자바 표준->스프링이 아닌 다른 컨테이너에서도 사용 가능

💡 웹 스코프

  • 웹 환경에서만 동작
  • 프로토타입과 다르게 스프링이 해당 스코프 종료시점까지 관리->종료 메서드 호출

✔️ 웹 스코프 종류

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

✔️ Request 스코프

profile
꾸준하게 Ready, Set, Go!

0개의 댓글