CGLIB는 인터페이스가 없는 구체클래스를 extends하여 동적으로 프록시를 생성하는 기술이다. 이 기술을 사용하려면 먼저 MethodInterceptor.interface를 구현해야 한다.
public interface MethodInterceptor extends Callback {
Object intercept(Object obj, Method method, Object[] args, MethodProxy
proxy) throws Throwable;
}
예를들어 메서드의 시간을 측정하는 클래스는 아래처럼 구현할 수 있다.
@Slf4j
public class TimeMethodInterceptor implements MethodInterceptor {
private final Object target;
public TimeMethodInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
log.info("TimeProxy 실행");
long startTime = System.currentTimeMillis();
Object result = methodProxy.invoke(target, args);
long endTime = System.currentTimeMillis();
long resultTime = endTime - startTime;
log.info("TimeProxy 종료, resultTime={}", resultTime);
return result;
}
}
전에 살펴본 JDK 동적 프록시 기술과 상당히 비슷한 구조를 지녔다.
한번 사용해보자.
@Slf4j
public class CglibTest {
@Test
void cglib() {
ConcreteService target = new ConcreteService();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ConcreteService.class); //인터페이스가 없는 구체클래스
enhancer.setCallback(new TimeMethodInterceptor(target));
ConcreteService proxy = (ConcreteService) enhancer.create();
log.info("targetClass={}", target.getClass());
log.info("proxyClass={}", proxy.getClass());
proxy.call();
}
}
간단하게 Enhancer에 구체클래스와 콜백을 설정하고 create()를 실행하면 프록시가 생성된다.
이처럼 구체클래스의 프록시는 CGLIB를 통해 만들 수 있다. 스프링의 ProxyFactory를 이용해 CGLIB를 더 쉽게 다루는 방법을 다른 글에 소개하겠다.