- request 스코프 예제 만들기
- gradle에 implement 하기
- 동시에 여러 HTTP요청이 오면 정확이 어떤 요청이 남긴 로그인지 구분하기 어려움
- 이럴 때 사용하기 좋은 것이 request 스코프
- 로그가 남도록 request 스코프를 활용해서 추가기능 개발하기
- UUID를 사용해서 HTTP요청 구분해볼것
- 스코프와 Provider
- 코드보기
package hello.core.common;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;
//로그를 출력하기 위한 MyLogger class
@Component
@Scope(value = "request")
public class MyLogger {
private String uuid;
private String requestURL;
public void setRequestURL(String requestURL){
this.requestURL = requestURL;
}
public void log(String msg){
System.out.println("["+uuid+"]"+"["+requestURL+"]"+msg);
}
@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);
}
}
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final ObjectProvider<MyLogger> myLoggerProvider;
//MyLogger는 request가 들어와서 나갈 때까지만 존재하는 애인데
//따라서 그 안에 주입하려고 달라 해야하는데 없어!
//이럴 땐 provider 사용하면 됨.
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request){
String requestURL = request.getRequestURL().toString();
MyLogger myLogger = myLoggerProvider.getObject();
myLogger.setRequestURL(requestURL);
myLogger.log("controller test");
logDemoService.logic("testId");
return "OK";
}
}
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final ObjectProvider<MyLogger> myLoggerProvicer;
public void logic(String id) {
MyLogger myLogger = myLoggerProvicer.getObject();
myLogger.log("service id = "+id);
}
}
- 결과
- 스코프와 프록시
- 위와 같이 코드 변경
- CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입
- 결과를 확인해보면 순수한 MyLogger 클래스가 아니라 다른 클래스로 만들어진 객체가 대신 등록 됨
- 실제 요청이 들어오면 진짜 빔을 요청하는 위임 로직이 가짜 프록시 객체에 들어가 있음
- 가짜 프록시 객체는 원본 클래스를 상속받아 만들어져 이 객체를 사용하는 클라이언트 입장에서는 원본인지 아닌지 모르게 동일하게 사용 가능함(다형성)
- 따라서 request scope와 상관없이 싱글톤 처럼 사용가능(실제 싱글톤은 아님. 다른 객체로 동작)
- 진짜 객체조회를 꼭 필요한 시점까지 지연처리한다는 것이 Provider와 프록시가 가진 공통점