728x90
이전 의존관계




- 빈을 등록하는 설정 파일을 활용(클라이언트 코드 수정X)
ContrlloerProxy
@RequiredArgsConstructor
public class OrderControllerInterfaceProxy implements OrderControllerV1 {
private final OrderControllerV1 target;
private final LogTrace logTrace;
@Override
public String request(String itemId) {
TraceStatus status = null;
try {
status = logTrace.begin("OrderController.request()");
//target 호출
String result = target.request(itemId);
logTrace.end(status);
return result;
}catch (Exception e){
logTrace.exception(status, e);
throw e;
}
}
@Override
public String noLog() {
return target.noLog();
}
}
ServiceProxy
@RequiredArgsConstructor
public class OrderServiceInterfaceProxy implements OrderServiceV1 {
private final OrderServiceV1 target;
private final LogTrace logTrace;
@Override
public void orderItem(String itemId) {
TraceStatus status = null;
try {
status = logTrace.begin("OrderService.orderItem()");
//target 호출
target.orderItem(itemId);
logTrace.end(status);
}catch (Exception e){
logTrace.exception(status, e);
throw e;
}
}
}
RepositoryProxy
@RequiredArgsConstructor
public class OrderRepositoryInterfaceProxy implements OrderRepositoryV1 {
private final OrderRepositoryV1 target;
private final LogTrace logTrace;
@Override
public void save(String itemId) {
TraceStatus status = null;
try {
status = logTrace.begin("OrderRepository.save()");
//target 호출
target.save(itemId);
logTrace.end(status);
}catch (Exception e){
logTrace.exception(status, e);
throw e;
}
}
}
- 프록시 코드에서 LogTrace의 로그남기는 기능을 대신처리 해준다.
- 클라이언트 코드 수정 X
- target : 실제 호출할 원본 인스턴스 참조를 가지고 있어야한다.
Bean 등록( 빈으로 등록할 떄 실제 target이 아닌 프록시를 등록해야 한다->부가 기능이 추가된)
@Configuration
public class InterfaceProxyConfig {
@Bean
public OrderControllerV1 orderController(LogTrace logTrace){
OrderControllerV1Impl controllerImpl = new OrderControllerV1Impl(orderService(logTrace));
return new OrderControllerInterfaceProxy(controllerImpl, logTrace);
}
@Bean
public OrderServiceV1 orderService(LogTrace logTrace) {
OrderServiceV1Impl serviceImpl = new OrderServiceV1Impl(orderRepository(logTrace));
return new OrderServiceInterfaceProxy(serviceImpl, logTrace);
}
@Bean
public OrderRepositoryV1 orderRepository(LogTrace logTrace) {
OrderRepositoryV1Impl repositoryImpl = new OrderRepositoryV1Impl();
return new OrderRepositoryInterfaceProxy(repositoryImpl, logTrace);
}
}
- 이제 프록시의 런타임 객체 의존 관계를 설정하면 된다. 기존에는 스프링 빈이 orderControlerV1Impl , orderServiceV1Impl 같은 실제 객체를 반환했다. 하지만 이제는 프록시를 사용해야한다. 따라서 프록시를 생성하고 프록시를 실제 스프링 빈 대신 등록한다. 실제 객체는 스프링 빈으로 등록하지 않는다
- 프록시는 내부에 실제 객체를 참조하고 있다. 예를 들어서 OrderServiceInterfaceProxy 는 내부에 실제 대상 객체인 OrderServiceV1Impl 을 가지고 있다.
- 정리하면 다음과 같은 의존 관계를 가지고 있다.
- proxy -> target
- orderServiceInterfaceProxy -> orderServiceV1Impl
- 스프링 빈으로 실제 객체 대신에 프록시 객체를 등록했기 때문에 앞으로 스프링 빈을 주입 받으면 실제 객체 대신에 프록시 객체가 주입된다.
- 실제 객체가 스프링 빈으로 등록되지 않는다고 해서 사라지는 것은 아니다. 프록시 객체가 실제 객체를 참조하기 때문에 프록시를 통해서 실제 객체를 호출할 수 있다. 쉽게 이야기해서 프록시 객체 안에 실제 객체가 있는 것이다
프록시 적용 전

프록시 적용 후

- 스프링 컨테이너에 프록시 객체가 등록된다. 스프링 컨테이너는 이제 실제 객체가 아니라 프록시 객체를 스프링 빈으로 관리한다
- 이제 실제 객체는 스프링 컨테이너와는 상관이 없다. 실제 객체는 프록시 객체를 통해서 참조될 뿐이다.
- 프록시 객체는 스프링 컨테이너가 관리하고 자바 힙 메모리에도 올라간다. 반면에 실제 객체는 자바 힙 메모리에는 올라가지만 스프링 컨테이너가 관리하지는 않는다.

설정 파일 등록
@Import(InterfaceProxyConfig.class)
@SpringBootApplication(scanBasePackages = "hello.proxy.app") //주의
public class ProxyApplication {
public static void main(String[] args) {
SpringApplication.run(ProxyApplication.class, args);
}
@Bean
public LogTrace logTrace(){
return new ThreadLocalLogTrace();
}
}
- logTrace도 빈으로 등록하자
- 프록시와 DI 덕분에 원본 코드를 전혀 수정하지 않고, 로그 추적기를 도입할 수 있었다. 물론 너무 많은 프록시 클래스를 만들어야 하는 단점이 있기는 하다.
- 이 부분은 나중에 해결하기로 하고, 우선은 v2 - 인터페이스가 없는 구체 클래스에 프록시를 어떻게 적용할 수 있는지 알아보자.
728x90
'스프링 핵심 원리(고급편)' 카테고리의 다른 글
| Ch04. 프록시 패턴과 데코레이터 패턴 - 구체 클래스 기반 프록시(적용) (0) | 2022.04.10 |
|---|---|
| Ch04. 프록시 패턴과 데코레이터 패턴 - 구체 클래스 기반 프록시(테스트) (0) | 2022.04.10 |
| Ch04. 프록시 패턴과 데코레이터 패턴 - 프록시 패턴과 데코레이터 패턴 정리 (0) | 2022.04.10 |
| Ch04. 프록시 패턴과 데코레이터 패턴 - 데코레이터 패턴 (0) | 2022.04.10 |
| Ch04. 프록시 패턴과 데코레이터 패턴 - 프록시 패턴 (0) | 2022.04.10 |