싱글톤 스코프 빈과 프로토타입 스코프 빈을 같이 사용할 때 사용할 때마다 항상 새로운 프로토타입 스코프의 빈이 생성되지 않는다는 문제점이 있었다. 어떻게 하면 이 문제를 해결하고 올바른 의도대로 사용할 수 있을까?
가장 간단한 방법으로 싱글톤 스코프의 빈이 프로토타입을 사용할 때마다 스프링 컨테이너에 새로 요청하는 방법이다.
static class ClientBean {
@Autowired
private ApplicationContext ac;
public int logic() {
PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
...
}
}
DL(Dependency Lookup, 의존관계 탐색)
이라고 한다.DL
정도의 기능만 제공하는 것만 있으면 된다.ObjectProvider
는 지정한 빈을 컨테이너에서 대신 찾아주는 DL 기능을 제공해준다. 기존에ObjectFactory
가 있었는데 이 인터페이스를 상속받고 여러가지 기능을 추가하여 만든 것이 ObjectProvider이다.
static class ClientBean {
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
prototypeBeanProvider.getObject()
으로 항상 새로운 프로토타입 빈이 생성된다.스프링에 의존하지 않고 javax.inject.Provider
라는 자바 표준을 사용하는 방법이다. 이 방법을 사용할 경우, build.gradle에 dependency 항목에 추가해주면 되는데, implementation 'javax.inject:javax.inject:1'
추가하면 된다.
static class ClientBean {
@Autowired
private Provider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.get();
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
프로토타입 스코프의 빈을 사용할 때
매번 사용할 때마다 의존관계 주입이 완료된 새로운 객체가 필요하면 사용하면 된다. 하지만 실무에서는 싱글톤 빈으로 대부분 해결이 되므로 프로토타입 빈을 직접적으로 사용하는 경우는 거의 없다.
OjbectProvider or JSR-330 Provider ?
- ObjectProvider, JSR303 Provider는 프로토타입말고도 DL이 필요한 경우에는 언제든지 사용할 수 있다.
- 따라서 어느 것을 사용할 것인지 고민이 생기는데, ObjectProvider는 DL에 관한 기능을 많이 제공해주며 스프링 외에 별도의 의존관계 추가가 필요없다. 만약 코드를 스프링이 아닌 다른 컨테이너에서도 사용할 수 있게 해야한다면 자바 표준인 JSR-330 Provider를 사용해야 한다.(거의 그럴 일이 없다)