해당 게시물은 인프런 - "스프링 핵심 원리 - 기본편" 강의를 참고하여 작성한 글 입니다
유료강의이므로 자세한 내용은 없고, 간단한 설명 위주로 정리했습니다 강의 링크
스프링 빈의 다양한 스코프
프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다
스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리한다
프로토타입 빈을 관리할 책임은 클라이언트에 있어서 종료 메소드가 호출되지 않는다
다음은 clientBean
이라는 싱글톤 빈이 의존관계 주입을 통해서 프로토타입 빈을 주입 받는 예다
clientBean
이 내부에 가지고 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈이다
따라서 사용할 때마다 새로 생성되지 않는다
싱글톤 빈과 프로토타입 빈을 함께 사용할 때, 항상 새로운 프로토타입 빈을 생성할 수 있는 방법이 있다
ObjectProvider
를 사용하면 DL(Dependency Lookup)을 쉽게 할 수 있다
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
prototypeBeanProvider.getObject()
를 통해서 항상 새로운 프로토타입 빈이 생성된다
objectProvider
의 getObject()
를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다
웹 스코프의 특징은 다음과 같다
웹 스코프의 종류는 다음과 같다
동시에 여러 HTTP 요청이 오면 어떤 요청이 남긴 로그인지 정확히 구분하기 어렵다
이럴때 사용하기 좋은것이 request 스코프다
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {
private String uuid;
private String requestURL;
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
public void log(String message) {
System.out.println("[" + uuid + "]" + "[" + requestURL + "] " + message);
}
@PostConstruct
public void init() {
uuid = UUID.randomUUID().toString();
System.out.println("[" + uuid + "] request scope bean create: " + this);
}
@PreDestroy
public void close() {
System.out.println("[" + uuid + "] request scope bean close: " + this);
}
}
@Scope(value= "request")
를 통해 request 스코프로 지정한다
@PostConstruct
초기화 메소드로 빈이 생성되는 시점에 uuid를 생성해 저장한다
uuid를 지정하면 다른 HTTP 요청과 구분할 수 있다
proxyMode = ScopedProxyMode.TARGET_CLASS
를 통해 MyLogger 클래스의 가짜 프록시 클래스를 미리 만들어서 다른 빈에 주입할 수 있다
스프링 애플리케이션을 실행하는 시점에서 request 스코프 빈은 아직 생성되지 않고, 실제 고객의 요청이 와야 생성이 된다.
그래서 프록시로 미리 빈을 만들어서 주입을 해야 한다
프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다
프록시 객체 내부에 myLogger
를 찾는 방법을 알고 있다
클라이언트가 myLogger.log()
를 호출하면, 사실은 프록시 객체의 메소드를 호출한다
그러면 프록시 객체는 request 스코프의 진짜 myLogger.log()
를 호출한다