-
[JAVA] 다이나믹 프록시 - 2Java 2020. 10. 4. 17:06
- 참고 : 인프런 >> 더 자바, 코드를 조작하는 다양한 방법, (백기선 강의)
다이나믹 프록시
1. JDK Proxy
(java.lang.refelction.proxy)
- 반드시 Interface가 정의 되어있어야 한다.
- 런타임시 동적으로 생성
- InvocationHandler 라는 Interface를 구현
- invoke 메소드 Override하여 Proxy의 위임 기능을 수행
- 'Object'에 대해 Reflection기능을 사용하여 기능을 구현
[예제 코드]
@Test public void test_다이나믹_프록시() { BookService bookService = (BookService) Proxy.newProxyInstance(BookService.class.getClassLoader(), new Class[]{BookService.class}, new InvocationHandler() { //리얼 서브젝트 클래스 BookService bookService = new RealBookService(); @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { if (method.getName().equals("rent")) { System.out.println("[before]"); Object invoke = method.invoke(bookService, args); System.out.println("[after]"); return invoke; } return method.invoke(bookService, args); } }); bookService.rent(); }
2. CGLIB Proxy
- 사용 ?
- 하이버 네이트
- 스프링 AOP
[예제 코드]
@Test public void test_다이나믹_프록시2_cglib() { MethodInterceptor handler = new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { BookService bookService = new RealBookService(); if (method.getName().equals("rent")) { System.out.println("[before]"); Object invoke = method.invoke(bookService, args); System.out.println("[after]"); return invoke; } return method.invoke(bookService, args); } }; //Enhnacer라는 클래스를 이용하여 프록시를 생성한다. BookService bookService = (BookService) Enhancer.create(BookService.class, handler); bookService.rent(); }
3. Bytebuddy Proxy
@Test public void test_다이나믹_프록시3_bytebuddy() throws Exception { /* 상속을 통해 proxy >> 상속을 하지 못하는 클래스는 bytebuddy를 통해 못함. - final class >> 상속을 막음 - private 생성자 >> 하위 클래스에서 부모클래스 생성자 호출을 막음 */ Class<? extends BookService> proxyClass = new ByteBuddy().subclass(BookService.class) .method(named("rent")).intercept(InvocationHandlerAdapter.of(new InvocationHandler() { @Override public Object invoke(Object o, Method method, Object[] args) throws Throwable { BookService bookService = new RealBookService(); if (method.getName().equals("rent")) { System.out.println("[before]"); Object invoke = method.invoke(bookService, args); System.out.println("[after]"); return invoke; } return method.invoke(bookService, args); } })) .make() .load(BookService.class.getClassLoader()).getLoaded(); BookService bookService = proxyClass.getConstructor(null).newInstance(); bookService.rent(); }
정리
- 런타임에 인터페이스 또는 클래스의 프록시 인스턴스 또는 클래스를 만들어 사용하는 프로그래밍 기법
사용 처 ?
- 스프링 데이터 JPA
- 스프링 AOP
- Mockito
- 하이버네이트 Lazy Initialzation
'Java' 카테고리의 다른 글
[JAVA] 다이나믹 프록시 - 1 (0) 2020.09.23 [Java] 리플렉션 - 5 (정리) (0) 2020.07.26 [Java] 리플렉션 - 4 (DI 프레임워크) (0) 2020.07.26 [Java] 리플렉션 - 3 (클래스 정보 수정 또는 실행) (0) 2020.07.26 [Java] 리플렉션 - 2 (어노테이션) (0) 2020.07.25 댓글