클래스 프록시
디자인 패턴 ·자바의 Proxcy는 오직 인터페이스만 적용할 수 있다.
그래서 이번에는 cglib과 bytebuddy를 이용해 클래스 프록시를 구현하는 방법을 알아본다.
cglib으로 구현하는 방법
cglib은 자바 클래스 파일을 조작하여 동적으로 클래스를 생성할 수 있는 라이브러리다.
따라서 프록시 객체를 생성하기 위해 대상 객체와 같은 클래스를 만들어내는 방식으로 구현된다.
maven dependency
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
방법
Enhancer.create(Class type, Callback callback)
프록시 객체를 생성하는 함수
type에 프록시 적용할 클래스와 callback에 프록시를 구현할 MethodInterceptor를 매개 변수로 넘긴다.
예제 코드
BookService cglibBookService = (BookService) Enhancer.create(BookServiceImpl.class, new MethodInterceptor() {
final BookServiceImpl bookService = new BookServiceImpl();
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
if(!method.getName().equals("rent")) {
return method.invoke(bookService, args);
}
System.out.println("aaa");
Object invoke = method.invoke(bookService, args);
System.out.println("bbb");
return invoke;
}
});
Book book = new Book();
book.setTitle("spring");
cglibBookService.rent(book);
cglibBookService.returnBook(book);
bytebuddy로 구현하는 방법
bytebuddy는 cglib과 비슷한 동적 클래스 생성 라이브러리다.
maven dependency
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.16</version
</dependency>
방법
메소드를 인터셉트해 프록시를 적용한 새로운 클래스를 만든다.
예제 코드
Class<? extends BookServiceImpl> proxyClass = new ByteBuddy()
.subclass(BookServiceImpl.class)
.method(named("rent"))
.intercept(InvocationHandlerAdapter.of(new InvocationHandler() {
final BookService bookService = new BookServiceImpl();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!method.getName().equals("rent")) {
return method.invoke(bookService, args);
}
System.out.println("aaa");
Object invoke = method.invoke(bookService, args);
System.out.println("bbb");
return invoke;
}
}))
.make().load(BookServiceImpl.class.getClassLoader()).getLoaded();
BookService bookService = proxyClass.getConstructor(null).newInstance();
Book book = new Book();
book.setTitle("spring");
bookService.rent(book);
bookService.returnBook(book);
주의
단 상속이 제한된 클래스에 한해서는 사용할 수 없다.
예제는 이곳 에서 확인하실수 있습니다.