ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다이내믹 프록시
    백기선(인프런 강의)/더 자바, 코드를 조작하는 다양한 방법 2020. 6. 16. 19:27
    반응형

    다이나믹 프록시란?

    런타임에 인터페이스 또는 클래스의 프록시 인스턴스 또는 클래스를 만들어 사용하는 프로그래밍 기법

     

    JavaInterface가 아닌 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);
    	}
    }

     

     

    참고

    2020/02/18 - [Spring/Spring AOP] - 다이나믹 프록시 (1)

    반응형
Designed by Tistory.