Dynamic Proxy와 CGlib의 차이점
안녕하세요. yeTi입니다.
Spring AOP를 공부하다보면 Java의 Dynamic Proxy와 CGlib이 언급됩니다.
그래서 Dynamic Proxy와 CGlib에 대해서 정리하고 차이점을 알아보고자 합니다.
프록시 패턴
Dynamic Proxy와 CGlib은 기존 코드에 변경을 가하지 않으면서 기능을 추가할 수 있는 프록시 기술을 구현하기 위한 방법들입니다.
소프트웨어 디자인 패턴 중 하나인 프록시 패턴을 UML로 표현하면 아래 그림과 같습니다.
프록시 패턴의 주요 개념은 동일한 인터페이스를 가진 구현 클래스는 Client에서 사용할때 다형성을 활용하여 동일한 인터페이스에 다른 기능을 정의하여 사용할 수 있는 것입니다.
Dynamic Proxy
프록시 패턴을 직접 구현하는 경우에 프록시 클래스를 직접 구현해야하고 코드량이 많아지는 문제점이 있습니다.
이에 자바에서 리플렉션을 활용한 Proxy 클래스를 제공하고 있고 이를 사용하면 런타임시에 동적으로 기능을 추가할 수 있습니다.
BookService bookService = (BookService) Proxy.newProxyInstance(BookService.class.getClassLoader(), new Class[]{BookService.class},
new InvocationHandler() {
BookService bookService = new DefaultBookService();
@Override
public Object invoke(Object proxy, Method, method, Object[] args) throws Throwable {
if (method.getName().equals("rent")) {
System.out.println("aaaa");
Object invoke = method.invoke(bookService, args);
System.out.println("bbbb");
return invoke;
}
return method.invoke(bookService, args);
}
});
해당 방식의 제약 사항은 인터페이스를 통해서만 Proxy를 생성할 수 있다는 것입니다.
CGlib
위에 Dynamic Proxy의 제약사항을 언급했던거와 같이 클래스의 프록시가 필요한경우에는 다른 방법은 사용해야 하는데
그 방법 중 하나가 CGlib을 활용하는 것인데, 이미 스프링이나 하이버네이트에서는 내장되어 사용하고 있습니다.
MethodInterceptor handler = new MethodInterceptor() {
BookService bookService = new DefaultBookService();
@Override
public Object intercept(Object interceptor, Method, method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (method.getName().equals("rent")) {
System.out.println("aaaa");
Object invoke = method.invoke(bookService, args);
System.out.println("bbbb");
return invoke;
}
return method.invoke(bookService, args);
}
});
BookService bookService = (BookService) Enhancer.create(BookService.class, handler);
CGlib의 제약사항은 final
클래스나 메소드는 advise할 수 없다는 것입니다.
AspectJ
Spring AOP는 AspectJ 스타일로 제공합니다.
이 말이 무엇이냐면 AspectJ라는 용어는 이클립스 제단에서 주관하는 프로젝트명으로 AOP를 도입할 수 있도록 기능을 제공하는 프로젝트 입니다.
Spring AOP에서 AspectJ의 기능 중 Pointcut을 파싱하고 매칭해주는 제한적인 AOP를 제공합니다.
AspectJ가 제공하는 다양한 기능을 사용하고 싶으면 5.10. Using AspectJ with Spring Applications를 참고하면 됩니다.