Web Scope, Provider, Proxy

초보개발·2021년 12월 21일
0

Spring

목록 보기
29/37

예제 오류의 해결책

1. Provider

ObjectProvider를 사용해본다.

  • Controller와 Service에서 request 스코프를 사용하는 Logger에다 적용한다. Provider의 getObject()로 myLogger를 가져오기만 하면 된다.
   private final ObjectProvider<Logger> myLoggerProvider;
  • getObject()를 호출하는 시점까지 request 스코프 빈의 생성을 지연시킬 수 있게 되었다.
  • getObject()를 호출하는 시점에는 http 요청이 진행중이므로 request 스코프의 빈의 생성이 정상적으로 처리된다.
  • getObject()를 컨트롤러와 서비스에서 각각 한번씩 따로 호출해도 같은 http 요청이면 같은 빈이 반환된다.

2. Proxy

@Component
@Scope(value = "request", proxyMode = ScopeProxyMode.TARGET_CLASS)
public class Logger{...}
  • 기존 Logger 클래스에 proxyMode = ScopeProxyMode.TARGET_CLASS를 추가
    • 적용 대상이 class : TARGET_CLASS
    • 적용 대상이 interface : INTERFACES
  • Logger의 가짜 프록시 클래스를 만들어두고 http request와 상관없이 CGLIB 라이브러리로 클래스를 상속받은 가짜 프록시 클래스를 다른 빈에 미리 주입해 둘 수 있다. 스프링 빈 이름은 기존 클래스의 이름으로 등록된다. 의존관계 주입은 이 가짜 프록시 객체가 주입된다.
   myLogger = class hello.core.common.MyLogger$$EnhancerBySpringCGLIB$$fd0ce40e


가짜 프록시 객체는 요청이 들어오면 그 때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.

  • 클라이언트가 myLogger.logic()을 호출하면 가짜 프록시의 객체를 호출한 것이다.
  • 가짜 프록시 객체는 내부에 진짜 myLogger를 찾는 방법을 알고 있으며, request scope의 진짜 logic()을 호출한다.
  • 가짜 프록시 객체는 원본 클래스를 상속받아 만들어졌으므로 이 객체를 사용하는 클라이언트 입장에서는 만들어진 클래스인지 아닌지 모르게 동일하게 사용할 수 있다. (다형성)
  • 가짜 프록시 객체는 실제 request scope와 상관없고, 위임 로직만 있으며 싱글톤처럼 동작한다.

주의사항

  • 싱글톤처럼 동작하는 것이지, 다르게 동작하기 때문에 주의해서 사용해야 한다.
  • 필요한 곳에서만 최소화하여 사용해야 한다.(무분별한 사용시 유지보수가 어렵다)

정리
Provider나 Proxy의 핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리를 할 수 있다는 점이다.
프록시는 웹 스코프가 아니여도 사용할 수 있다.
다형성과 DI 컨테이너의 강점으로 애노테이션 설정만 변경했는데, 원본 객체를 프록시 객체로 대체할 수 있다는 것이다.

0개의 댓글