싱글톤 스코프 : 스프링 컨테이너가 생성되고 내려갈 때까지 같은 객체
프로토타입 스코프 : 매번 요청이 올 때마다 스프링 컨테이너가 새로 생성, 의존관계 주입, 초기화까지 해주고 전달함
프로토타입은 말 그대로 스프링 컨테이너 입장에서는 요청이 오면 만들어서 던져주는 것이기 때문에 관리는 전적으로 클라이언트가 해야한다. 그런데 만약 싱글톤 빈이 프로토타입을 자동주입 받게 되면? 싱글톤 빈은 계속해서 같은 프로토타입의 참조를 들고 있을 것이니 프로토타입이라해도 싱글톤으로 자동주입 들어가는 순간 싱글톤이나 다름 없게 된다. 이를 해결하기 위한 방법은 싱글톤에서 프로토타입 객체를 가져와야할때 매번 스프링 컨테이너에 조회해야 한다. 이를 간단하게 하기 위한 것이 ObjectProvider이다.
@Scope("singleton")
static class ClientBean {
@Autowired
private ObjectProvider<PrototypeBean> pp;
public int logic() {
PBean pbean = pp.get();
pbean.addCount();
return pbean.getCount();
}
}
ObjectProvider은 별도의 라이브러리가 필요없지만 스프링에 의존적이다.
그래서 자바 표준을 사용하는 방법인 javax.inject.Provider이다. 코드는 아래와 같다.
@Scope("singleton")
static class ClientBean {
@Autowired
private Provider<PrototypeBean> protoProvider;
public int logic() {
PBean pbean = pp.get();
pbean.addCount();
return pbean.getCount();
}
}
하지만 다른 컨테이너를 사용할 필요가 없다면 혹은 스프링이 제공하는 것이 더 좋은 경우라면 스프링이 제공하는 것을 사용하고(ex. Autowired), 기능이 비슷하다거나 스프링측에서 자바 표준을 써라라고 하는 건 표준을 쓰는 것이 좋다.(ex. PostConstruct, PreDestroy)
프로토타입 빈은 언제 사용할까? - 매번 사용시 의존관계 주입이 다 된 새 객체가 필요하다 할때 사용한다. 근데 실제로는 거의 사용되지 않는다고 한다.
웹 스코프 중 request 스코프 : 사용자의 요청이 들어오고 끝날 때까지 유지됨
예시를 통해 이해해보면 일단 MyLogger라는 클래스가 request 스코프 스프링 빈으로 등록되어있을때
@RequestMapping("log-demo")
public String logDemo(HttpServletRequest request) {
//컨트롤러에서 MyLogger 사용
MyLogger myLogger = myLoggerProvider.getObject();
String r = request.getRequestURL().toString();
myLogger.setRequest_url(r);
myLogger.log("controller test");
//서비스 로직 호출
logS.logic("testid");
return "OD";
}
}
// 서비스 로직의 logic 함수. 여기서도 MyLogger를 getObject로 가져온다.
public void logic(String id) {
MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("service id = " + id);
}
컨트롤러에서 myLoggerProvider.getObject로 가져온 MyLogger 객체와 서비스에서 가져온 MyLogger 객체는 동일한 객체이다. MyLogger는 request 스코프로, 사용자의 요청이 들어오고 처리될 때까지 동일하게 유지되기 때문이다. 멀티 스레드 환경에서 ThreadLocal을 통해 request 요청마다 다른 MyLogger 객체를 생성해주는 것이다.
ThreadLocal에 대한 내용은 다음 블로그가 정리가 잘 되어있다.
https://javacan.tistory.com/entry/ThreadLocalUsage
관련글
'백엔드 > 스프링' 카테고리의 다른 글
프론트 컨트롤러 패턴 (0) | 2021.08.17 |
---|---|
Http Request 데이터 형식 정리 (0) | 2021.08.17 |
스프링 빈 등록 총정리 (0) | 2021.08.13 |
스프링 설정 - Xml 형식 (0) | 2021.08.12 |
스프링 리액트 연동 Rest API 써보기 (0) | 2021.03.28 |