Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[동적프록시] JDK 동적프록시 - 적용 본문

인프런/[인프런] 스프링 핵심 원리 - 고급

[동적프록시] JDK 동적프록시 - 적용

Seung__ 2021. 12. 30. 21:20

JDK 동적프록시는 인터페이스가 필수이다. 따라서 V1에 적용해보자.

 

 

1. LogTraceBasicHandler


import hello.proxy.trace.TraceStatus;
import hello.proxy.trace.logtrace.LogTrace;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class LogTraceBasicHandler implements InvocationHandler {

    private final Object target;
    private final LogTrace logTrace;

    public LogTraceBasicHandler(Object target, LogTrace logTrace) {
        this.target = target;
        this.logTrace = logTrace;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        TraceStatus status = null;
        try{
            String message = method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()";
            status = logTrace.begin(message);
            //로직 호출
            Object result = method.invoke(target, args);
            logTrace.end(status);
            return result;
        }catch (Exception e){
            logTrace.exception(status, e);
            throw e;
        }
    }
}
  • LogTraceBasicHandler 는 InvocationHandler 인터페이스를 구현해서 JDK 동적 프록시에서
    사용된다.
  • private final Object target : 프록시가 호출할 대상이다.
  • String message = method.getDeclaringClass().getSimpleName() + "." ...
    • LogTrace 에 사용할 메시지이다. 프록시를 직접 개발할 때는 "OrderController.request()" 와 같이 
      프록시마다 호출되는 클래스와 메서드 이름을 직접 남겼다. 
      이제는 Method 를 통해서 호출되는 메서드 정보와 클래스 정보를 동적으로 확인할 수 있기 때문에 
      이 정보를 사용하면 된다.
  • 동적 프록시를 사용하도록 수동 빈 등록을 설정하자

 

2. Bean 등록


@Configuration
public class DynamicProxyBasicConfig {
    @Bean
    public OrderControllerV1 orderControllerV1(LogTrace logTrace){
        OrderControllerV1 orderController = new OrderControllerV1Impl(orderServiceV1(logTrace));

        OrderControllerV1 proxy = (OrderControllerV1) Proxy.newProxyInstance(OrderControllerV1.class.getClassLoader(),
                new Class[]{OrderControllerV1.class},
                new LogTraceBasicHandler(orderController, logTrace));

        return proxy;
    }

    @Bean
    public OrderServiceV1 orderServiceV1(LogTrace logTrace){
        OrderServiceV1 orderService = new OrderServiceV1Impl(orderRepositoryV1(logTrace));

        OrderServiceV1 proxy = (OrderServiceV1) Proxy.newProxyInstance(OrderServiceV1.class.getClassLoader(),
                new Class[]{OrderServiceV1.class},
                new LogTraceBasicHandler(orderService, logTrace));

        return proxy;
    }

    @Bean
    public OrderRepositoryV1 orderRepositoryV1(LogTrace logTrace){
        OrderRepositoryV1 orderRepository = new OrderRepositoryV1Impl();

        OrderRepositoryV1 proxy = (OrderRepositoryV1) Proxy.newProxyInstance(OrderRepositoryV1.class.getClassLoader(),
                new Class[]{OrderRepositoryV1.class},
                new LogTraceBasicHandler(orderRepository, logTrace));

        return proxy;
    }
}
  • 이전에는 프록시 클래스를 직접 개발했지만, 
  • 이제는 JDK 동적 프록시 기술을 사용해서 각각의 Controller , Service , Repository 에 맞는 동적 프록시 생성
  • LogTraceBasicHandler : 동적 프록시를 만들더라도 LogTrace 를 출력하는 로직은 모두 같기 때문
    프록시는 모두 LogTraceBasicHandler 를 사용한다.

 

 

3. 실행, 결과


@Import(DynamicProxyBasicConfig.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();
    }

}
[4f7429ae] OrderControllerV1.request()
[4f7429ae] |-->OrderServiceV1.orderItem()
[4f7429ae] |   |-->OrderRepositoryV1.save()
[4f7429ae] |   |<--OrderRepositoryV1.save() time=1000ms
[4f7429ae] |<--OrderServiceV1.orderItem() time=1001ms
[4f7429ae] OrderControllerV1.request() time=1002ms

 

 

4. 의존관계


 

하지만 no-log를 실행해도 동적 프록시가 적용되고, LogTraceBasicHandler 가 실행되기 때문에 로그가 남는다.
이 부분을 로그가 남지 않도록 처리해야 한다.

 

5. GitHub : 211230 JDK Dynamic Proxy 2


 

GitHub - bsh6463/Spring_Advanced_2

Contribute to bsh6463/Spring_Advanced_2 development by creating an account on GitHub.

github.com

 

Comments