빈이 존재할 수 있는 범위
스프링은 다음과 같은 다양한 스코프를 지원한다.
@Scope("proptotype")
@Component
public class HelloBean {}
스프링 컨테이너에 요청할 때마다 항상 새로운 인스턴스를 생성해서 반환한다.
스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리한다. 그래서 @PreDestroy
같은 종료 메서드가 호출되지 않는다.
따라서 프로토타입 빈은 이를 조회한 클라이언트가 관리해야 한다. 종료 메서드 호출도 클라이언트가 직접 해주어야 한다.
매번 사용할 때마다 의존관계 주입이 완료된 새로운 객체가 필요할 때.
프로토타입 빈을 직접적으로 사용하는 일은 드물다.
@Scope("prototype")
static class PrototypeBean {
private int count = 0;
public void addCount() {
count++;
}
public int getCount() {
return count;
}
@PostConstruct
public void init() {
System.out.println("PrototypeBean.init " + this);
}
@PreDestroy
public void destroy() {
System.out.println("PrototypeBean.destroy");
}
}
@Scope("singleton")
static class ClientBean {
private final PrototypeBean prototypeBean;
public ClientBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public int logic() {
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
싱글톤 빈이 프로토타입 빈을 사용하는 경우, 싱글톤 빈은 생성 시점에만 의존관계를 주입받기 때문에 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함께 계속 유지된다.
@Scope("singleton")
static class ClientBean {
@Autowired
ApplicationContext ac;
public int logic() {
PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
ac.getBean()
을 통해 항상 새로운 프로토타입 빈이 생성됨@Scope("singleton")
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
라는 JSR-330 자바 표준을 사용하는 방법. 라이브러리를 gradle에 추가해야 한다.@Scope("singleton")
static class ClientBean {
@Autowired
private Provider<PrototypeBean> provider;
public int logic() {
PrototypeBean prototypeBean = provider.get();
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
provider.get
을 호출하면 내부에서 스프링 컨테이너를 통해 해당 빈을 찾아 반환한다(DL)웹 환경에서만 동작.
스프링이 해당 스코프의 종료 시점까지 관리한다.
[HTTP request 요청당 각각 할당되는 request 스코프]
동시에 여러 HTTP 요청이 오면 정확히 어떤 요청이 남긴 로그인지 구분하기 어렵다. 이때 사용하면 좋은 것이 request 스코프.
스프링 애플리케이션을 실행하는 시점에 싱글톤 빈은 생성해서 주입이 가능하지만, request 스코프 빈은 실제 고객의 요청이 와야 생성할 수 있으므로, 오류가 발생한다.
ObjectProvider.getObject()
를 호출하는 시점까지 request 스코프 빈의 생성을 지연할 수 있다.
ObjectProvider.getObject()
를 controller
와 service
에서 각각 한번씩 따로 호출해도 같은 HTTP 요청이면 같은 스프링 빈이 반환된다.
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {
...
}
@Scope
에 proxyMode
를 추가한다.
TARGET_CLASS
, 인터페이스면 INTERFACES
선택해당 어노테이션이 붙은 클래스의 가짜 프록시 클래스를 만들어서 주입
가짜 프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.
특징
주의사항