Java가 기본으로 제공하는.JDK동적 프록시 기술이나 CGLIB같은 프록시 생성 오픈소스 기술을 활용하면 프록시 객체를 동적으로 만들어낼 수 있다.
프록시를 적용할 코드를 하나만 만들어두고 동적 프록시 기술을 사용해서 프록시 객체를 만들면 된다.
jdk동적 프록시는 인터페이스를 기반으로 프록시를 동적으로 만들어준다. 따라서 인터페이스가 필수
public interface AInterface {
String call();
}
@Slf4j
public class AImpl implements AInterface{
@Override
public String call() {
log.info("A 호출");
return "a";
}
}
@Slf4j
public class TimeInvocationHandler implements InvocationHandler {
private final Object target;
public TimeInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("TimeProxy 실행");
long startTime = System.currentTimeMillis();
Object result = method.invoke(target, args); //target의 method를 실행
long endTime = System.currentTimeMillis();
long resultTime = endTime - startTime;
log.info("TimeProxy 종료 resultTime={}", resultTime);
return result;
}
}
@Test
void dynamicA() {
AInterface target = new AImpl();
TimeInvocationHandler handler = new TimeInvocationHandler(target);
//proxy 생성 - Proxy.newProxyInstance(어디에 생성될지, 들어가는 인터페이스(어떤 인터페이스를 기반으로 프록시를 만들지), 프록시가 사용할 로직 호출)
AInterface proxy = (AInterface) Proxy.newProxyInstance(
AInterface.class.getClassLoader(),
new Class[]{AInterface.class},
handler
);
proxy.call();
log.info("targetClass={}",target.getClass());
log.info("proxyClass={}",proxy.getClass());
}
Proxy.newProxyInstance(A, B, C)
- proxy 생성call()
실행InvocationHandler.invoke()
를 호출. TimeInvocationHandler
가 구현체로 있으므로 TimeInvocationHandler.invoke()
가 호출 됨TimeInvocationHandler
가 내부적으로 수행하고 method.invoke(target, args)
를 호출해서 target인 실제 객체 AImpl
을 호출AImpl
인스턴스의 call()
실행AImpl
인스턴스의 call()
실행이 끝나면 TimeInvocationHandler
로 응답이돈다