오봉이와 함께하는 개발 블로그

스프링 핵심 원리 - 고급편 > 구체 클래스 기반 프록시 적용 본문

BE/Spring

스프링 핵심 원리 - 고급편 > 구체 클래스 기반 프록시 적용

오봉봉이 2024. 8. 27. 23:30
728x90

스프링 핵심 원리 - 고급편 > 구체 클래스 기반 프록시 적용

실제 적용을 해보자.

@RequiredArgsConstructor
public class OrderRepositoryConcreteProxy extends OrderRepositoryV2 {

  private final OrderRepositoryV2 orderRepositoryV2;
  private final LogTrace logTrace;

  @Override
  public void save(String itemId) {
    TraceStatus status = null;
    try {
      status = logTrace.begin("orderRepositoryV2.save");
      orderRepositoryV2.save(itemId);
      logTrace.end(status);
    } catch (Exception e) {
      logTrace.exception(status, e);
      throw e;
    }
  }
}
public class OrderServiceConcreteProxy extends OrderServiceV2 {

  private final OrderServiceV2 orderServiceV2;
  private final LogTrace logTrace;

  public OrderServiceConcreteProxy(OrderServiceV2 orderServiceV2, LogTrace logTrace) {
    super(null);
    this.orderServiceV2 = orderServiceV2;
    this.logTrace = logTrace;
  }

  @Override
  public void orderItem(String itemId) {
    TraceStatus status = null;
    try {
      status = logTrace.begin("OrderService.orderItem()"); //target 호출
      orderServiceV2.orderItem(itemId);
      logTrace.end(status);
    } catch (Exception e) {
      logTrace.exception(status, e);
      throw e;
    }
  }

}
public class OrderControllerConcreteProxy extends OrderControllerV2 {

  private final OrderControllerV2 orderControllerV2;
  private final LogTrace logTrace;

  public OrderControllerConcreteProxy(OrderControllerV2 orderControllerV2, LogTrace logTrace) {
    super(null);
    this.orderControllerV2 = orderControllerV2;
    this.logTrace = logTrace;
  }

  @Override
  public String request(String itemId) {
    TraceStatus status = null;
    try {
      status = logTrace.begin("OrderControllerProxy.request()");
      String result = orderControllerV2.request(itemId);
      logTrace.end(status);
      return result;
    } catch (Exception e) {
      logTrace.exception(status, e);
      throw e;
    }
  }

  @Override
  public String noLog() {
    return orderControllerV2.noLog();
  }
}
@Configuration
public class ConcreteProxyConfig {

  @Bean
  public OrderControllerV2 orderController(LogTrace logTrace) {
    OrderControllerV2 orderControllerV2 = new OrderControllerV2(orderService(logTrace));
    return new OrderControllerConcreteProxy(orderControllerV2, logTrace);
  }

  @Bean
  public OrderServiceV2 orderService(LogTrace logTrace) {
    OrderServiceV2 orderServiceV2 = new OrderServiceV2(orderRepository(logTrace));
    return new OrderServiceConcreteProxy(orderServiceV2, logTrace);
  }

  @Bean
  public OrderRepositoryV2 orderRepository(LogTrace logTrace) {
    OrderRepositoryV2 orderRepositoryV2 = new OrderRepositoryV2();
    return new OrderRepositoryConcreteProxy(orderRepositoryV2, logTrace);
  }

}

크게 어려운 코드는 없지만 단점이 보인다.
super(null)은 자바 기본 문법에 의해 자식 클래스를 생성할 때는 항상 super()로 부모 클래스의 생성자를 호출해주어야만 한다. 이 부분을 생략하면 기본 생성자가 호출되는데, 부모 클래스에 기본 생성자가 없고 생성자에서 파라미터 1개를 필수로 받고 있다.
따라서 super(params...)를 호출해야 한다.

프록시는 부모 객체의 기능을 사용하지 않기 때문에 super(null)을 해도 된다.
단, super.someMethod()와 같이 부모 객체의 기능을 사용할 경우는 필요할 것이다.

참고로 OrderServiceV2의 생성자는 아래와 같다.

public OrderServiceV2(OrderRepositoryV2 orderRepository) {
    this.orderRepository = orderRepository;
}

 

출처: 김영한 지식공유자의 스프링 핵심 원리 고급편

728x90
Comments