스프링 핵심 원리 - 기본편 # Section 9
2024. 7. 6. 17:59ㆍSpring/스프링 핵심 원리 - 기본편
반응형
❓ 빈 스코프
스프링의 다양한 스코프
- 싱글톤 : 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- 프로토타입 : 프로토타입 빈의 생성과 의존관계 주입까지만 관여하는 스코프
- 웹 관련 스코프
- request : 웹 요청이 들어오고 나갈때 까지 유지됨
- session : 웹 세션이 생성되고 종료될 때 까지 유지 됨
- application : 웹의 서블릿 컨텍스트와 같은 범위로 유지 됨
❓ 프로토타입 빈
@Scope("prototype")
@Component
public class HelloBean {}
핵심은 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리한다는 것.
이후엔 프로토타입 빈을 관리하지 않음 따라서 @PreDestroy 같은 종료 메서드를 호출 하지 않음
❓ 웹 스코프
- 웹 환경에서만 동작한다
- 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리함 따라서 종료 메서드가 실행 됨
웹 스코프 종류
- request : HTTP 요청 하나가 들어오고 나갈 때 가지 유지되는 스코프
- session : HTTP Session 과 동일한 생명주기를 가짐
- application : 서블릿 컨텍스트 (ServletContext) 와 동일한 생명주기를 가짐
- websocket : 웹 소켓과 동일한 생명주기를 가짐
request 스코프 빈 만들기
@Component
// 스코프를 request 로 지정
@Scope(value = "request")
public class MyLogger2 {
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 스코프로 지정
- 이 빈은 HTTP 요청 당 하나씩 생성되고, HTTP 요청이 끝나는 시점에 소멸 됨
❓ 스코프와 Provider, 프록시
위 예제 처럼 request 스코프로 지정 된 빈은 요청이 와야 생성이 된다.
요청이 오기전에 service 단에서 사용하려고 하면 오류가 발생하는데 해당 부분을 해결 할 수 있는 방법이 있다.
1. Provider 사용
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final ObjectProvider<MyLogger> myLoggerProvider;
public void logic(String id) {
MyLogger myLogger = myLoggerProvider.getObject();
myLogger.log("service id = " + id);
}
}
- ObjectProvider 덕분에 호출하는 시점까지 request scope 빈의 생성을 지연 할 수 있다.
2. 프록시
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {}
- proxyMode = ScopedProxyMode.TARGET_CLASS
- 적용 대상이 인터페이스가 아닌 클래스면 TARGET_CLASS
- 인터페이스면 INTERFACES 를 선택
- 이렇게 하면 MyLogger의 가짝 프록시 클래스를 만들고 다른 빈에 미리 주입해 둘 수 있다.
웹 스코프와 프록시 동작 원리
동작 정리
- CGLIB 라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입
- 이 가짜 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 있음
- 가짜 프록시 객체는 실제 request scope 와는 관계 없다.
특징 정리
- 프록시 객체 덕분에 클라이언트는 마치 싱글톤 빈을 사용하듯이 편리하게 requeset scope 를 사용 할 수 있음
- 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점
강의 출처
반응형