코드에 적용하기
1. ObjectProvider<T> 의존 관계 주입 받기
private final ObjectProvider<PrototypeBean> prototypeBeanProvider;PrototypeBean prototypeBean = prototypeBeanProvider.getObject();싱글톤 빈에서 프로토타입 빈 사용시 주의점
예시를 통해 알아보자.
다음과 같이 싱글톤 빈에서 프로토타입 빈을 의존한다.
@Component
@Scope(value = "singleton")
public class SingletonBean {
//프로토타입 빈 의존
private final PrototypeBean prototypeBean;
//프로토타입 빈 의존관계 주입
@Autowired
public SingletonBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public void logic(){
//프로토타입 빈 주소 출력
prototypeBean.logic();
}
}
이 때 아래 테스트를 수행한 결과를 보자.
@Test
public void provider(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
SingletonBean bean1 = ac.getBean(SingletonBean.class);
bean1.logic();
SingletonBean bean2 = ac.getBean(SingletonBean.class);
bean2.logic();
}
실행결과
test.core.prototype.PrototypeBean@281f23f2
test.core.prototype.PrototypeBean@281f23f2
프로토타입 빈 두번 사용했지만 같은 주소를 반환한 것을 볼 수 있다!
싱글톤 빈은 한번 생성된다. 이때 의존관계 주입이 일어난다.
프로토타입 빈은 의존관계 생성될 때 한번 호출된다.
이후 싱글톤 빈 안에서 프로토타입 빈 사용이 일어날 때 생성한 프로토타입 빈만 사용한다.
따라서 이런 결과가 일어난 것이다. 이 때 프로바이더를 사용하여 내가 필요할 때 스프링 빈에서 찾아 꺼내 사용하는 것이다.
@Scope(value = "prototype"): 프로토타입 빈 생성한다.import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Scope(value = "prototype")
public class PrototypeBean {
@PostConstruct
public void init(){
System.out.println("PrototypeBean.init");
}
public void logic(){
System.out.println(this);
}
}
ObjectProvider<T> : 저장한 빈을 컨테이너에서 대신 찾아주기 위해 프로바이더를 선언한다.getObject()로 호출한다.import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "singleton")
public class SingletonBean {
private final ObjectProvider<PrototypeBean> prototypeBeanObjectProvider;
public SingletonBean(ObjectProvider<PrototypeBean> prototypeBeanObjectProvider) {
this.prototypeBeanObjectProvider = prototypeBeanObjectProvider;
}
public void logic(){
PrototypeBean prototypeBean = prototypeBeanObjectProvider.getObject();
prototypeBean.logic();
}
}
@Test
public void provider(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
SingletonBean bean1 = ac.getBean(SingletonBean.class);
bean1.logic();
SingletonBean bean2 = ac.getBean(SingletonBean.class);
bean2.logic();
}
실행결과
PrototypeBean.init
test.core.prototype.PrototypeBean@23e44287
PrototypeBean.init
test.core.prototype.PrototypeBean@2b8d084
출처
인프런 '스프링 핵심 원리 - 기본편' 강의