4. Object Communication
1: do() 2: do()
: Client : Proxy Service : Real Service
Real real = new Real() private Service real;
Proxy proxy = new Proxy();
proxy.setReal(real); public void do() {
// before: doSomeThing
Client client = new Client();
client.setService(proxy); real.do();
// after: doAnyThing
}
6. CBLIB
• Code Generation Library
– 프록시 생성 기능 제공
– 인터페이스 및 클래스에 대한 프록시 생성
– http://cglib.sourceforge.net/
• 오픈 소스에서 프록시 생성 용도로 사용
– Spring, Hibernate, iBATIS 등
7. CGLIB 설치
• 다운로드 사이트
– http://sourceforge.net/project/showfiles.php?
group_id=56933
• 배포판
– cglib-nodep-2.2.jar : ASM 모듈 포함
– cglib-2.2.jar : ASM 모듈 비 포함
9. Enhancer를 이용한 프록시 생성
Enhancer enhancer = new Enhancer();
// 프록시 대상 지정
enhancer.setSuperclass(SomeService.class); public, pakcage, protected
메서드가 대상
// 프록시에서 호출할 Callback
enhancer.setCallback(someCallback);
// 프록시 생성
Object proxy = enhancer.create();
service.SomeService$$EnhancerByCGLIB$$91a42e4f
SomeService someService = (SomeService) proxy;
someService.create(quot;publicquot;); // proxy를 호출
10. 프록시 대상 지정
• 클래스 지정
enhancer.setSuperclass(RealService.class);
• 인터페이스 지정
enhancer.setInterfaces(
new Class<?>[] {Service.class});
11. 주요 Callback
NoOp 아무 기능도 수행하지 않는 않음
MethodInterceptor 대상 객체의 메서드 호출 전/후로 자
유롭게 기능 추가가 가능
LazyLoader 대상 객체가 최초로 필요할 때 생성
해서 리턴
Dispatcher 각 메서드 호출에 알맞은 대상 객체
를 전달한다.
12. MethodInterceptor
• 대상 객체 호출 이전/이후에 필요한 기능
삽입 가능한 Callback
public interface MethodInterceptor extends Callback {
public Object intercept(
Object obj, 프록시 객체
java.lang.reflect.Method method, 호출되는 메서드
Object[] args, 호출 시 전달받은 인자
MethodProxy proxy) 대상 객체 메서드를 호출할 때 사용
throws Throwable;
}
13. MethodInterceptor 구현
public class InterceptorImpl implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method,
Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(quot;BEFOREquot;);
Object result = proxy.invokeSuper(obj, args);
Enhancer.setSuperclass()로
System.out.println(quot;AFTERquot;);
지정한 클래스의 메서드 호출
return result;
}
}
14. MethodInterceptor 샘플
public interface Service { Enhancer enhancer = new Enhancer();
public String say();
} enhancer.setSuperclass(RealService.class);
enhancer.setCallback(new InterceptorImpl());
public class RealService Service service = (Service) enhancer.create();
implements Service {
@Override service.say();
BEFORE
public String say() {
System.out.println( RealService 호출
quot;RealService 호출quot;); AFTER
return quot;안녕하세요quot;;
}
}
15. MethodInterceptor 주의 사항
public class InterceptorImpl implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method,
Object[] args, MethodProxy proxy) throws Throwable {
프록시 객체의 메서드가 호출
obj.toString();
↓
Interceptor가 호출
proxy.invoke(obj, args); ↓
반복 실행 후, StackOverflowError 발생
return result;
}
}
16. LazyLoader
• 최초 요청 시 실제 객체를 제공하기 위한
용도로 사용
public interface LazyLoader extends Callback {
Object loadObject() throws Exception;
}
17. LazyLoader 구현 예
package service;
import net.sf.cglib.proxy.LazyLoader;
public class LazyLoaderImpl implements LazyLoader {
private Class<?> realClass;
public LazyLoaderImpl(Class<?> realClass) {
this.realClass = realClass;
}
@Override
public Object loadObject() throws Exception {
System.out.println(quot;실제 객체 생성quot;);
return realClass.newInstance();
}
}
18. 실행 예
Enhancer enhancer = new Enhancer();
enhancer.setInterfaces(new Class<?>[] {Service.class});
enhancer.setCallback(new LazyLoaderImpl(RealService.class));
Service service = (Service) enhancer.create();
실제 객체 생성
service.say(); RealService 호출
service.say(); RealService 호출
19. 활용
• Proxy 패턴
– Lazy Instantication
– 접근 제어
• Decorator 패턴
– 메서드 기반 AOP 구현
• before, after, around Advice 구현에 적용