빈이 생성되고 존재할 수 있는 범위를 뜻한다.
자동 등록
@Scope("prototype")
@Component
public class HelloBean {}
수동 등록
@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
return new HelloBean();
}
프로토타입 스코프 빈은 스프링 컨테이너에 빈을 요청하는 시점에 생성되고 의존관계가 주입된다.
의존관계 주입 이후 프로토타입 빈을 반환한다.
이후에 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성하여 반환한다.
정리
스프링 컨테이너는 프로토타입 빈을 생성하고 의존관계주입, 초기화까지만 처리한다. 빈을 반환한 이후에는 프로토타입 빈을 관리하지 않는다.
@PreDestroy
와 같은 종료 메서드는 호출되지 않으므로 종료 시에 처리해야하는 부분은 빈을 반환받은 클라이언트에 책임이 있다.
싱글톤 빈이 프로토타입 빈을 주입받는 경우
ClientBean
은 싱글톤 PrototypeBean
은 프로토타입이라고 가정하고 아래 코드를 보면
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;
}
}
ClientBean
이 스프링 빈으로 등록되면서 의존관계를 주입받기 때문에 PrototypeBean
도 스프링 빈으로 등록되고 ClientBean
에 주입되어야한다.PrototypeBean
을 더이상 관리하지 않는다.ClientBean
은 싱글톤이므로 스프링 컨테이너가 관리한다.이러한 경우 ClientBean
을 요청하는 다른 서비스들은 이미 ClientBean
에 주입된 PrototypeBean
을 사용하게 되고 이는 프로토타입 스코프의 빈을 싱글톤 스코프 빈 처럼 사용하게 된다.
DL(dependency LookUp) : 의존관계를 외부에서 주입(DI) 받는 것이 아니라 직접 필요한 의존관계를 찾는 것을 말한다.
스프링 빈에서 DL을 하기 위하여 스프링의 ApplicationContext 전체를 주입 받는 것은 스프링 컨테이너에 종속적인 코드가 되고, 단위테스트도 어려워진다.
이러한 경우 DL의 기능을 제공하는 Provider를 사용하면 된다.
지정한 빈을 컨테이너에서 대신 찾아주는 DL을 제공하는 것이 ObjectProvider
이다.
static class ClientBean {
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
ObjectProvider
를 주입받는다.ObjectProvider
의 getObject()
로 원하는 타입의 스프링 빈을 가져온다.(DL)자바 표준을 사용하는 방법으로 javax.inject.Provider
를 사용할 수 있다.
build.gradle에서 dependencies에
implementation 'javax.inject:javax.inject:1'
를 추가하면 된다.
package javax.inject;
public interface Provider<T> {
T get();
}
Provider는 get() 메소드를 제공한다.
static class ClientBean {
@Autowired
private Provider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.get();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
Provider
를 주입받는다.Provider
의 get()
으로 원하는 타입의 스프링 빈을 가져온다.(DL)스프링이 제공하는 기능과 자바 표준의 기능이 공통적인 부분이 있는 경우가 많다. 스프링이 더욱 편리한 기능을 제공하는 경우가 많으므로, 스프링 외에 다른 컨테이너를 사용할 일이 없다면 스프링 기능을 활용하면 된다.