목차
BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용
BeanPostProcessor
Spring 핵심원리 고급편 - ProxyFactory 적용
Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용
Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut
Spring 핵심원리 고급편 - Pointcut 만들기
Spring 핵심원리 고급편 - Advisor
Spring 핵심원리 고급편 - MethodInterceptor
Spring 핵심원리 고급편 - ProxyFactory
참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다.
인터페이스 객체에 프록시 팩토리 적용스프링에서 제공하는 MethodInterceptor 인터페이스를 이용해
import org.aopalliance.intercept.MethodInterceptor;public class LogTraceAdvice implements MethodInterceptor { private final LogTrace logTrace; public LogTraceAdvice(LogTrace logTrace) { this.logTrace = logTrace; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { TraceStatus status = null; try { Method method = invocation.getMethod(); String message = method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()"; status = logTrace.begin(message); // 로직 호출 Object result = invocation.proceed(); logTrace.end(status); return result; } catch (Exception ex) { logTrace.exception(status, ex); throw ex; } }}
@Slf4j@Configurationpublic class ProxyFactoryConfigV1 { @Bean public OrderControllerV1 orderControllerV1(LogTrace logTrace){ OrderControllerV1 orderController = new OrderControllerV1Impl(orderServiceV1(logTrace)); // OrderControllerV1 객체를 Proxy 객체로 생성한다. ProxyFactory factory = new ProxyFactory(orderController); factory.addAdvisor(getAdvisor(logTrace)); // Advisor 를 적용한다. OrderControllerV1 proxy = (OrderControllerV1) factory.getProxy(); log.info("ProxyFactory proxy = {}, target = {}", proxy.getClass(), orderController); return proxy; } @Bean public OrderServiceV1 orderServiceV1(LogTrace logTrace){ OrderServiceV1Impl orderService = new OrderServiceV1Impl(orderRepositoryV1(logTrace)); // OrderServiceV1Impl 객체를 Proxy 객체로 생성한다. ProxyFactory factory = new ProxyFactory(orderService); factory.addAdvisor(getAdvisor(logTrace)); // Advisor 를 적용한다. OrderServiceV1 proxy = (OrderServiceV1) factory.getProxy(); log.info("ProxyFactory proxy = {}, target = {}", proxy.getClass(), orderService); return proxy; } @Bean public OrderRepositoryV1 orderRepositoryV1(LogTrace logTrace){ OrderRepositoryV1Impl orderRepository = new OrderRepositoryV1Impl(); // OrderRepositoryV1Impl 객체를 Proxy 객체로 생성한다. ProxyFactory factory = new ProxyFactory(orderRepository); factory.addAdvisor(getAdvisor(logTrace)); // Advisor 를 적용한다. OrderRepositoryV1 proxy = (OrderRepositoryV1) factory.getProxy(); log.info("ProxyFactory proxy = {}, target = {}", proxy.getClass(), orderRepository); return proxy; } private Advisor getAdvisor(LogTrace logTrace) { // Point Cut NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut(); pointcut.setMappedNames("request*", "order*", "save*"); // advice LogTraceAdvice advice = new LogTraceAdvice(logTrace); // Pointcut과 Advice 를 이용해 Advisor 객체를 만들어준다. return new DefaultPointcutAdvisor(pointcut, advice); }}
애플리케이션 로딩 시점에서 해당 Bean 이 Loading 되는 것을 확인할 수 있다.
2021-12-05 01:09:21.671 INFO 64531 --- [ main] h.p.c.v.ProxyFactoryConfigV1 : ProxyFactory proxy = class com.sun.proxy.$Proxy50, target = hello.proxy.app.v1.OrderRepositoryV1Impl@5555ffcf2021-12-05 01:09:21.673 INFO 64531 --- [ main] h.p.c.v.ProxyFactoryConfigV1 : ProxyFactory proxy = class com.sun.proxy.$Proxy52, target = hello.proxy.app.v1.OrderServiceV1Impl@5a2fa51f2021-12-05 01:09:21.674 INFO 64531 --- [ main] h.p.c.v.ProxyFactoryConfigV1 : ProxyFactory proxy = class com.sun.proxy.$Proxy53, target = hello.proxy.app.v1.OrderControllerV1Impl@6ecdbab8