목차
Spring 핵심원리 고급편 - CGLIB
Spring 핵심원리 고급편 - Dynamic Proxy 2
Spring 핵심원리 고급편 - Dynamic Proxy 1
Spring 핵심원리 고급편 - 리플렉션
Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 적용 2
Spring 핵심원리 고급편 - 구체 클래스 기반 프록시
Spring 핵심원리 고급편 - 인터페이스 프록시 1
Spring 핵심원리 고급편 - Decorator Pattern 2
Spring 핵심원리 고급편 - Decorator Pattern 1
Spring 핵심원리 고급편 - Proxy 패턴 컴포넌트 스캔으로 자동 빈 등록
Spring 핵심원리 고급편 - Proxy 패턴 인터페이스 없는 없는 구체 클래스
Spring 핵심원리 고급편 - Proxy 패턴 인터페이스와 구체 클래스
Spring 핵심원리 고급편 - Proxy 패턴
Spring 핵심원리 고급편 - Strategy 패턴
Spring 핵심원리 고급편 - Template 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);            // 로직 호출            method.invoke(target, args);            logTrace.end(status);            return result;        } catch (Exception ex) {            logTrace.exception(status, ex);            throw ex;        }    }}
@Configurationpublic class DynamicBasicProxyConfig {    @Bean    public OrderControllerV1 orderControllerV1(LogTrace logTrace){        OrderControllerV1 orderControllerV1 = new OrderControllerV1Impl(orderServiceV1(logTrace));        // Proxy 객체 생성        OrderControllerV1 proxy = (OrderControllerV1) Proxy                .newProxyInstance(                    OrderControllerV1.class.getClassLoader(),                    new Class[]{OrderControllerV1.class},                    new LogTraceBasicHandler(orderControllerV1, logTrace));        return proxy;    }    @Bean    public OrderServiceV1 orderServiceV1(LogTrace logTrace){        OrderServiceV1 orderServiceV1 = new OrderServiceV1Impl(orderRepositoryV1(logTrace));        // Proxy 객체 생성        OrderServiceV1 proxy = (OrderServiceV1) Proxy                .newProxyInstance(                    OrderServiceV1.class.getClassLoader(),                    new Class[]{OrderServiceV1.class},                    new LogTraceBasicHandler(orderServiceV1, logTrace));        return proxy;    }    @Bean    public OrderRepositoryV1 orderRepositoryV1(LogTrace logTrace){        OrderRepositoryV1 orderRepository = new OrderRepositoryV1Impl();        // Proxy 객체 생성        OrderRepositoryV1 proxy = (OrderRepositoryV1) Proxy                .newProxyInstance(                    OrderRepositoryV1.class.getClassLoader(),                    new Class[]{OrderRepositoryV1.class},                    new LogTraceBasicHandler(orderRepository, logTrace));        return proxy;    }}
@Import(DynamicBasicProxyConfig.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();    }}
2021-11-28 22:18:58.331  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] OrderControllerV1.request()2021-11-28 22:18:58.333  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] |-->OrderServiceV1.orderItem()2021-11-28 22:18:58.333  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] |   |-->OrderRepositoryV1.save()2021-11-28 22:18:59.338  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] |   |<--OrderRepositoryV1.save() time=1005ms2021-11-28 22:18:59.338  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] |<--OrderServiceV1.orderItem() time=1006ms2021-11-28 22:18:59.339  INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace   : [4e72efcd] OrderControllerV1.request() time=1007ms
특정 메소드에만 부가기능 로직 적용PatternMatchUtils.simpleMatch 를 사용해 메소드 이름이 조건을 만족하는지 Pattern Matching 한다.