빈 스코프
- 빈이 존재할 수 있는 범위
- 싱글톤
- 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- 프로토타입
- 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고
- 더는 관리하지 않는 매우 짧은 범위의 스코프
- 웹 관련 스코프
- request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프
- session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프
- application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
프로토타입 스코프
- 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다
- 요청 => 프로토타입 빈을 생성, 필요한 의존관계를 주입
- 반환 => 생성한 프로토타입 빈을 클라이언트에 반환 / 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성해서 반환
@Scope("prototype")
static class PrototypeBean {
@PostConstruct
public void init() {
}
@PreDestroy
public void destroy() {
}
}
@Test
void prototypeBeanFind() {
p1 = ac.getBean("PrototypeBean.class");
p2 = ac.getBean("PrototypeBean.class");
print(p1);
print(p2);
}
// 결과
// prototypeBean1 = hello.core.scope.PrototypeTest$PrototypeBean@13d4992d
// prototypeBean2 = hello.core.scope.PrototypeTest$PrototypeBean@302f797
싱글톤 빈과 함께 사용시 문제점
- clientBean 은 싱글톤이므로, 보통 스프링 컨테이너 생성 시점에 함께 생성되고, 의존관계 주입도 발생한다.
1. clientBean 은 의존관계 자동 주입을 사용한다. 주입 시점에 스프링 컨테이너에 프로토타입 빈을 요청한다.
2. 스프링 컨테이너는 프로토타입 빈을 생성해서 clientBean 에 반환한다. 프로토타입 빈의 count 필드 값은 0이다.
- 이제 clientBean 은 프로토타입 빈을 내부 필드에 보관한다. (정확히는 참조값을 보관한다.)
- 클라이언트 A는 clientBean 을 스프링 컨테이너에 요청해서 받는다.싱글톤이므로 항상 같은 clientBean 이 반환된다
3. 클라이언트 A는 clientBean.logic() 을 호출한다.
4. clientBean 은 prototypeBean의 addCount() 를 호출해서 프로토타입 빈의 count를 증가한다. count값이 1이 된다.
- 클라이언트 B는 clientBean 을 스프링 컨테이너에 요청해서 받는다.싱글톤이므로 항상 같은 clientBean 이 반환된다
- clientBean이 내부에 가지고 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈이다.
- 주입 시점에 스프링 컨테이너에 요청해서 프로토타입 빈이 새로 생성이 된 것이지, 사용 할 때마다 새로 생성되는 것이 아니다
5. 클라이언트 B는 clientBean.logic() 을 호출한다.
6. clientBean 은 prototypeBean의 addCount() 를 호출해서 프로토타입 빈의 count를 증가한다. 원래 count 값이 1이었으므로 2가 된다
싱글톤 빈과 함께 사용시 Provider로 해결
ObjectFactory, ObjectProvider
- ObjectFactory에 편의 기능을 추가한 것이 ObjectProvider
- 지정한 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 제공
@Autowired
private ObjectProvide<PrototypeBean> prototypeBeanProvider;
public int login() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
- prototypeBeanProvider.getObject() 을 통해서 항상 새로운 프로토타입 빈이 생성
JSR-330 Provider
- 스프링 부트 3.0은 jakarta.inject.Provider 사용
@Autowired
private Provider<PrototypeBean> provider;
public int logic() {
PrototypeBean prototypeBean = provider.get();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
'Spring > Basic' 카테고리의 다른 글
[Basic] 웹 스코프 (0) | 2024.08.28 |
---|---|
[Basic] 빈 생명주기 콜백 (0) | 2024.08.27 |
[Basic] 의존관계 주입 (0) | 2024.08.27 |
[Basic] 컴포넌트 스캔 (0) | 2024.08.27 |
[Basic] 싱글톤 컨테이너 (0) | 2024.08.27 |