-
다이내믹 프록시백기선(인프런 강의)/더 자바, 코드를 조작하는 다양한 방법 2020. 6. 16. 19:27반응형
다이나믹 프록시란?
런타임에 인터페이스 또는 클래스의 프록시 인스턴스 또는 클래스를 만들어 사용하는 프로그래밍 기법
Java는 Interface가 아닌 class타입으로 다이나믹 프록시를 만들 수가 없다.
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html
다이나믹 프록시 사용처
- 스프링 데이터 JPA
- 스프링 AOP
- Mockito
- 하이버네이트 lazy initialzation
프록시 인스턴스 만들기
Object Proxy.newProxyInstance(ClassLoader, Interfaces, InvocationHandler)
예제
package com.example.demo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class BookServiceTest { // 코드가 실행하는 시점에 생성 // getClassLoader - 클래스 읽기 // new Class[] {BookService.class} - 프록시 인스턴스가 어떤 프록시의 인스턴스냐 // invocationHandler - 프록시의 메소드를 어떻게 처리할 것인가? 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 { Object invoke = null; if (method.getName().equals("rent")) { System.out.println("여기는 전자임니당"); invoke = method.invoke(bookService, args); System.out.println("여기는 후자입니다."); } return invoke; } }); @Test public void di() { Book book = new Book(); book.setTitle("spring"); bookService.rent(book); bookService.returnBook(book); } }
public interface BookService { void rent(Book book); void returnBook(Book book); }
public class Book { String title = "clean code"; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; }
@Service public class DefaultBookService implements BookService { @Override public void rent(Book book) { System.out.println("전 "); System.out.println("rent : " + book.getTitle()); System.out.println("이후 "); } @Override public void returnBook(Book book) { System.out.println("여기는 returnBook : " + book.getTitle()); } }
TestCode
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class BookServiceTest { // 코드가 실행하는 시점에 생성 // getClassLoader - 클래스 읽기 // new Class[] {BookService.class} - 프록시 인스턴스가 어떤 프록시의 인스턴스냐 // invocationHandler - 프록시의 메소드를 어떻게 처리할 것인가? 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 { Object invoke = null; if (method.getName().equals("rent")) { System.out.println("여기는 전자임니당"); invoke = method.invoke(bookService, args); System.out.println("여기는 후자입니다."); } return invoke; } }); @Test public void di() { Book book = new Book(); book.setTitle("spring"); bookService.rent(book); bookService.returnBook(book); } }
참고
반응형'백기선(인프런 강의) > 더 자바, 코드를 조작하는 다양한 방법' 카테고리의 다른 글
ExceptionHandler (0) 2020.06.16 클래스의 프록시 (0) 2020.06.16 리플렉션 정리 (0) 2020.06.14 리플렉션 API 1부: 클래스 정보 수정 또는 실행 (0) 2020.06.14 애노테이션과 리플랙션 (0) 2020.06.14