빈이 존재할 수 있는 범위
스프링 컨테이너에 요청할 때 마다 항상 새로운 인스턴스를 생성해서 반환한다.
핵심은 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리하고, 더는 관리하지 않는다.
@PreDestroy 같은 종료 메서드가 호출되지 않는다.
@Component
@Scope("prototype")
public class PrototypeBean {}
문제 - 싱글톤 빈에서 프로토타입 빈 사용
스프링은 일반적으로 싱글톤 빈을 사용하므로, 싱글톤 빈이 프로토타입 빈을 사용하게 된다. 그런데 싱글톤 빈은 생성 시점에만 의존관계 주입을 받기 때문에, 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함께 계속 유지되는 것이 문제다. 아마 원하는 것이 이런 것은 아닐 것이다. 프로토타입 빈을 주입 시점에만 새로 생성하는게 아니라, 사용할 때 마다 새로 생성해서 사용하는 것을 원할 것이다.
해결 - 싱글톤 빈과 함께 사용시 ObjectProvider or JSR-330 Provider
@Autowired
private ObjectProvider prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
}
@Autowired
private Provider provider;
public int logic() {
PrototypeBean prototypeBean = provider.get();
}
웹 환경에서만 동작한다. 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리한다. 따라서 종료 메서드가 호출된다.
@Component
@Scope(value = "request")
public class MyLogger {}
문제 - 싱글톤 빈에서 request 빈 사용
스프링 애플리케이션을 실행하는 시점에 싱글톤 빈은 생성해서 주입이 가능하지만, request 스코프 빈은 아직 생성되 지 않는다. 이 빈은 실제 고객의 요청이 와야 생성할 수 있다.
해결 - 프록시
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {}
MyLogger의 가짜 프록시 클래스를 만들어두고 HTTP request와 상관 없이 가짜 프록시 클래스를 다른 빈에 미리 주입해 둘 수 있다.
핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점이다.