프록시와 리얼 서브젝트가 공유하는 인터페이스가 있고, 클라이언트는 해당 인터페이스 타입으로 프록시를 사용한다.
클라이언트는 프록시를 거쳐서 리얼 서브젝트를 사용하기 때문에 프록시는 리얼 서브젝트에 대한 접근을 관리거나 부가기능을 제공하거나, 리턴값을 변경할 수도 있다.
리얼 서브젠트는 자신이 해야 할 일만 하면서(SRP) 프록시를 사용해서 부가적인 기능(접근 제한, 로깅, 트랜잭션, 등)을 제공할 때 이런 패턴을 주로 사용한다.
예제
public class Book {
String title = "clean code";
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
public interface BookService {
void rent(Book book);
void returnBook(Book book);
}
@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) {
// TODO Auto-generated method stub
}
}
public class BookServiceProxy implements BookService {
BookService bookService;
public BookServiceProxy(BookService bookService) {
this.bookService = bookService;
}
@Override
public void rent(Book book) {
System.out.println("프록시 테스트 rent");
bookService.rent(book);
}
@Override
public void returnBook(Book book) {
System.out.println("프록시 테스트 return book");
bookService.returnBook(book);
}
}
테스트 코드
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 {
@Autowired BookService bookService;
@Test
public void di() {
Book book = new Book();
book.setTitle("spring");
bookService.rent(book);
}
}
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 {
// @Autowired BookService bookService;
BookService bookService = new BookServiceProxy(new DefaultBookService());
@Test
public void di() {
Book book = new Book();
book.setTitle("spring");
bookService.rent(book);
}
}