이 글은 강의 : 김영한님의 - "스프링 핵심원리 - 기본편"을 듣고 정리한 내용입니다. 😁😁
이전에 사용했던 Provider 대신 프록시 방식을 사용한다.
🎈 MyLogger 프록시 적용
@Scope 속성으로 proxyMode = ScopedProxyMode.TARGET_CLASS 를 추가한다.
package hello.core.common;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;
// 로그 출력 클래스
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS) // request 스코프로 지정, 프록시 모드 설정
public class MyLogger {
...
}
이렇게 하면 MyLooger의 가짜 프록시 클래스를 만들어두고 HTTP request와 상관 없이 가짜 프록시 클래스를 다른 빈에 미리 주입해 둘 수 있다.
Provider 사용하기 이전 코드로..
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
// MyLogger 가 잘 작동하는지 확인하는 테스트용 컨트롤러
@Controller
@RequiredArgsConstructor // 자동 생성자 주입
public class LogDemoController {
private final LogDemoService logDemoService;
private final MyLogger myLogger; // 가짜 프록시 myLogger 주입
// log-demo 요청이 오면 웹 브라우저에 데이터를 문자로 반환
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request) throws InterruptedException {
// HttpServletRequest: 클라이언트 요청 정보
String requestURL = request.getRequestURL().toString(); // 클라이언트가 요청한 URL 반환
System.out.println("myLogger = " + myLogger.getClass()); // myLogger 확인하기
myLogger.setRequestURL(requestURL); // myLogger 의 requestURL 에 값 저장
myLogger.log("controller test");
//Thread.sleep(1000);
logDemoService.logic("testId");
return "OK";
}
}
역시 Provider 사용 이전 코드로
package hello.core.web;
import hello.core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor // 자동 생성자 주입
public class LogDemoService {
private final MyLogger myLogger; // 가짜 프록시 myLogger 주입
public void logic(String id) {
// ObjectProvider로 myLogger 조회(DL)
myLogger.log("service id = " + id);
}
}
프록시모드를 설정해주면 이전과 달리 오류가 나지 않고 잘 작동해!
가짜 프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.
🧨 프록시 객체 덕분에 클라이언트는 마치 싱글톤 빈을 사용하듯이 편리하게 request scope를 사용할 수 있다.
🧨 사실 Provider를 사용하든, 프록시를 사용하든 핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점이다.
🧨 단지 애노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체할 수 있다. 이것이 바로 다형성과 DI 컨테이너가 가진 큰 강점이다.
🧨 꼭 웹 스코프가 아니어도 프록시는 사용할 수 있다.