아래의 코드를 보면 SingletonBean
이 getPrototypeBean()
을 실행할 때마다 새로운 PrototypeBean
을 반환해야 한다. 하지만 항상 같은 PrototypeBean
을 반환하여 개발자가 의도한대로 동작하지 않는 문제가 발생한다. 이 문제를 해결하기 위해서는 의존성을 주입(DI)받는 것이 아니라 의존성을 검색(DL)해서 주입해야한다.
@Scope("prototype")
class PrototypeBean {}
class SingletonBean {
@Autowired
private PrototypeBean prototypeBean;
public PrototypeBean getPrototypeBean() {
return prototypeBean;
}
}
class SingletonWithPrototypeTest {
@Test
void singletonWithPrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class, PrototypeBean.class);
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
PrototypeBean prototypeBean1 = singletonBean1.getPrototypeBean();
PrototypeBean prototypeBean2 = singletonBean1.getPrototypeBean();
assertThat(prototypeBean1).isSameAs(prototypeBean2);
}
}
IoC 컨테이너
, ObjectProvider(ObjectFactory)
, JSR-330 Provider
등이 있다.@Scope("prototype")
class PrototypeBean {}
class SingletonBean {
@Autowired
private ApplicationContext ac;
public PrototypeBean getPrototypeBean() {
return ac.getBean(PrototypeBean.class);
}
}
class SingletonWithPrototypeTest {
@Test
void singletonWithPrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class, PrototypeBean.class);
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
PrototypeBean prototypeBean1 = singletonBean1.getPrototypeBean();
PrototypeBean prototypeBean2 = singletonBean1.getPrototypeBean();
assertThat(prototypeBean1).isSameAs(prototypeBean2);
}
}
IoC 컨테이너 전체를 주입받는 방법보다는 지정한 빈을 IoC 컨테이너에서 대신 찾아주는 방법을 사용하자.
ObjectFactory
가 있었는데, 여기에 편의 기능을 추가해서 ObjectProvider
가 만들어졌다.@Scope("prototype")
class PrototypeBean {}
class SingletonBean {
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public PrototypeBean getPrototypeBean() {
return prototypeBeanProvider.getObject();
}
}
class SingletonWithPrototypeTest {
@Test
void singletonWithPrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class, PrototypeBean.class);
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
PrototypeBean prototypeBean1 = singletonBean1.getPrototypeBean();
PrototypeBean prototypeBean2 = singletonBean1.getPrototypeBean();
assertThat(prototypeBean1).isSameAs(prototypeBean2);
}
}
@Scope("prototype")
class PrototypeBean {}
class SingletonBean {
@Autowired
private Provider<PrototypeBean> provider
public PrototypeBean getPrototypeBean() {
return provider.get()
}
}
class SingletonWithPrototypeTest {
@Test
void singletonWithPrototype() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class, PrototypeBean.class);
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
PrototypeBean prototypeBean1 = singletonBean1.getPrototypeBean();
PrototypeBean prototypeBean2 = singletonBean1.getPrototypeBean();
assertThat(prototypeBean1).isSameAs(prototypeBean2);
}
}
ObjectProvider(ObjectFactory)
는 DL을 위한 편의 기능을 많이 제공해주고 스프링 외에 별도의 의존성 추가가 필요 없어서 편리하다.JSR-330 Provider
를 사용해야 한다.