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 동적프록시 - 적용2, 필터 본문

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

[동적프록시] JDK 동적프록시 - 적용2, 필터

Seung__ 2021. 12. 30. 21:37

특정 조건을 만족할 때 만 프록시가 동작하도록 하자.

 

1. LogTraceFilterHandler


public class LogTraceFilterHandler implements InvocationHandler {

    private final Object target;
    private final LogTrace logTrace;
    private final String[] patterns;

    public LogTraceFilterHandler(Object target, LogTrace logTrace, String[] patterns) {
        this.target = target;
        this.logTrace = logTrace;
        this.patterns = patterns;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //메서드 이름 필터
        String methodName = method.getName();

        //save 등등등
       if (!PatternMatchUtils.simpleMatch(patterns, methodName)){
            return method.invoke(target, args);
        }
        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;
        }
    }
}
  • LogTraceFilterHandler 는 기존 기능에 다음 기능이 추가되었다.
  • 특정 메서드 이름이 매칭 되는 경우에만 LogTrace 로직을 실행한다. 
  • 이름이 매칭되지 않으면 실제 로직을 바로 호출한다.
  • 스프링이 제공하는 PatternMatchUtils.simpleMatch(..) 를 사용하면 매칭 로직을 쉽게 적용할 수 있다.
    • xxx : xxx가 정확히 매칭되면 참
    • xxx* : xxx로 시작하면 참
    • *xxx : xxx로 끝나면 참
    • *xxx* : xxx가 있으면 참
  • String[] patterns : 적용할 패턴은 생성자를 통해서 외부에서 받음.

 

 

2. Bean 등록


@Configuration
public class DynamicProxyFilterConfig {

    private static final String[] PATTERNS = {"request*", "order*", "save*"};

    @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 LogTraceFilterHandler(orderController, logTrace, PATTERNS));

        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 LogTraceFilterHandler(orderService, logTrace, PATTERNS));

        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 LogTraceFilterHandler(orderRepository, logTrace, PATTERNS));

        return proxy;
    }
}
  • public static final String[] PATTERNS = {"request*", "order*", "save*"}; 적용할 패턴이다. 
  • request , order , save 로 시작하는 메서드에 로그가 남는다.
  • LogTraceFilterHandler : 앞서 만든 필터 기능이 있는 핸들러를 사용한다. 
  • 그리고 핸들러에 적용 패턴도 넣어줌.

 

 

3. 실행


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

}

noLog()를 호출하는 경우 로그가 남지 않는다!

 

 

4. JDK 동적 프록시의 한계


  • JDK 동적 프록시는 인터페이스가 필수이다.
  • 그렇다면 V2 애플리케이션 처럼 인터페이스 없이 클래스만 있는 경우에는????
  • 어떻게 동적 프록시를 적용??
  • CGLIB 라는 바이트코드를 조작하는 특별한 라이브러리를 사용해야한다.

 

5. GitHiub : 211230 JDK Dynamic Proxy 3


 

GitHub - bsh6463/Spring_Advanced_2

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

github.com

 

Comments