Dev 달팽이 @_''

Java - 다이나믹 프록시 본문

Java&Spring/더 자바, 코드를 조작하는 다양한 방법

Java - 다이나믹 프록시

다본죽 2022. 1. 9. 23:12

Java - 다이나믹 프록시

다이나믹 프록시

  • 런타임에 특정 인터페이스들을 구현하는 클래스 또는 인스턴스를 만드는 기술
  • Object Proxy.newProxyInstance(ClassLoader, Interfaces, InvocationHandler)

Book.java

public class Book {

    public String title;

    public Book() {
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

 

BookService.java

public interface BookService {

    void rent(Book book);

    void returnBook(Book book);
}

 

DefaultBookService.java

public class DefaultBookService implements BookService{

    @Override
    public void rent(Book book) {
        System.out.println("rent : "+ book.getTitle());
    }

    @Override
    public void returnBook(Book book) {
        System.out.println("return : "+ book.getTitle());
    }
}

 

BookServiceTest.java

public class BookServiceTest {

    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 {
                    return method.invoke(bookService,args);
                }
            });

    @Test
    public void di(){
        Book book = new Book();
        book.setTitle("Spring");
        bookService.rent(book);
        bookService.returnBook(book);
    }
}
  • Object를 반환하므로 알맞는 타입으로 캐스팅해줘야 함
  • ClassLoader와 interface를 지정해줘야 함
  • invoke 안에서 프록시에서 할 부가적인 기능을 구현

 

다이나믹 프록시를 이용하여 "This is 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 {
			System.out.println("This is Proxy");
			return method.invoke(bookService,args);
		}
	});

 

 

rent 함수만 프록시를 적용하고 싶다면?

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("This is Proxy");
			return method.invoke(bookService,args);
		}
	});
  • if 문을 통하여 처리

 

자바 다이나믹 프록시의 문제

  • if문을 통하여 따로 처리해줘야함
  • 유연한 구조가 아님
  • 그래서 스프링AOP가 등장
  • Interface에 대한 프록시만 가능(Class에 대한 프록시 불가)