@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);
}
}
프록시
)를 만들어두고 HTTP req와 상관없이 가짜 프록시 클래스를 다른 빈에 미리 주입해 둘 수 있다.왜 가짜라했다면 위 사진을 보면 되게 오랜만에 "쒸쥐립"을 볼 수 있다. 이는 @Configuration
할 때 봤던건데 스프링이 조작해서 만들 빈들이 주로 이렇게 씨지립을 달고나왔었다.
그래서 일단 생성되는 시점 즉, 스프링 프로젝트가 뜨는 시점에는 바이트 코드를 조작하는 라이브러리인 CGLIB 을 통해서 가짜를 만들어서 넣어놨다가 나중에 호출되는 시점에서 진짜를 찾아서 동작하는 것이다.
그래서 ac.getBean("MyLogger", MyLogger.class)
로 테스팅을 해도 프록시 객체가 조회된다. 그래서 DI도 이 가짜 프록시 객체가 주입된다.
myLogger.logic()
을 호출하면 사실은 가짜 프록시 객체의 메서드를 호출한 것이다.myLogger.logic()
을 호출한다.
- CGLIB이라는 라이브러리로 내 클래스를 상속 받는 가짜 프록시 객체를 만들어서 주입한다.
- 이 가짜 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 들어있다.
- 가짜 프록시 객체는 실제 request scope와는 관계가 없다. 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤 처럼 동작한다.