빈이 존재할 수 있는 범위
정리
- 싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드가 실행 되지만, 프로토타입 스코프의 빈은 스프링 컨테이너에서 빈을 조회할 때 생성되고, 초기화 메서드도 실행
- 프로토타입 빈은 스프링 컨테이너에 요청할 때 마다 새로 생성
- 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리, 관리는 하지 X >
@PreDestroy
같은 종료 메서드가 호출되지 않음- 생성된 프로토타입 빈은 클라이언트가 관리, 종료 메서드에 대한 호출도
클라이언트가 직접 해야함
1. 싱글톤 clientBean
은 의존관계 자동 주입을 사용, 주입 시점에 스프링 컨테이너에 프로토타입 빈을 요청
2. 스프링 컨테이너는 프로토타입 빈을 생성해서 clientBean
에 반환
3. clientBean
은 프로토타입 빈을 내부 필드에 보관
3. 클라이언트 A는 clientBean
을 스프링 컨테이너에 요청해서 받고, 싱글톤이므로 항상 같은 clientBean
이 반환됨
4. 클라이언트 A는 clientBean.logic()
을 호출
5. clientBean
은 prototypeBean
의 addCount()
를 호출해서 프로토타입 빈의 count를 증가 > count == 1
6. 클라이언트 B는 clientBean
을 스프링 컨테이너에 요청해서 받고, 싱글톤이므로 항상 같은 clientBean
이 반환
7. 클라이언트 B는 clientBean.logic()
을 호출
8. clientBean
은 prototypeBean
의 addCount()
를 호출해서 프로토타입 빈의 count를 증가 > count == 2
clientBean
이 내부에 가지고 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈 > 싱글톤 빈과 함께 계속 유지됨
주입 시점에 스프링 컨테이너에 요청해서 프로토타입 빈이 새로 생성이 된 것이지, 클라이언트가 사용 할 때마다 새로 생성되는 것이 아님
가장 간단한 방법은 싱글톤 빈이 프로토타입을 사용할 때 마다 스프링 컨테이너에 새로 요청
@Scope("singleton")
static class ClientBean{
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic(){
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count=prototypeBean.getCount();
return count;
}
}
getObject()
호출하면 그때서야 스프링 컨테이너에서 프로토타입 빈을 찾아서 반환(DL) > 항상 새로운 프로토타입 빈이 생성ObjectFactory
는 getObject()만 제공, ObjectProvide
는 추가 기능도 제공, 둘다 스프링에 의존@Autowired
private Provider<PrototypeBean> provider;
public int logic() {
PrototypeBean prototypeBean = provider.get();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
provider.get()
을 통해서 항상 새로운 프로토타입 빈이 생성get()
을 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환(DL)정리
- 프로토타입 빈은 매번 사용할 때 마다 의존관계 주입이 완료된 새로운 객체가 필요하면 사용 > 하지만 싱글톤 빈으로 대부분의 문제를 해결할 수 있기 때문에 프로토타입 빈을 직접적으로 사용하는 일은 매우 드묾
- ObjectProvider , JSR330 Provider 등은 프로토타입 뿐만 아니라 DL이 필요한 경우는 언제든지 사용 가능
종류
HTTP 요청이 오면 정확히 어떤 요청이 남긴 로그인지 구분하기 어렵기 때문에 request 스코프를 사용하면 좋음
가짜를 우선 집어넣어놓고 실제 기능을 호출하는 시점에서 진짜를 찾아서 동작
CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입