프록시와 리얼 서브젝트가 공유하는 인터페이스가 있고, 클라이언트는 해당 인터페이스 타입으로 프록시를 사용
클라이언트는 프록시를 거쳐서 리얼 서브젝트를 사용 →
프록시는 리얼 서브젝트에 대한 접근 괄니, 부가기능 제공, 리턴값 변경 가능
객체지향의 원칙 중 하나인 SRP를 만족시키기 위해 ( 단일책임원칙 )
자신의 기능만 할 뿐 추가 기능은 프록시에서 ( 접근 제한, 로깅, 트랜젝션 등 )
class BookServiceProxy implements BookService {
BookService bookService;
public BookServiceProxy(BookService bookService) {
this.bookService = bookService;
}
@Override
public void rent(Book book) {
sout("프록시 적용");
bookService.rent("bookName");
}
프록시 패턴을 사용하기 위해 클래스를 만들어줘야함
리얼 서브젝트와 공유하는 인터페이스에 메소드가 여러개인데 하나의 메소드만 추가적 기능 들어가는 경우 나머지 메소드는 리얼 서브젝트의 메소드를 똑같이 복사해서 사용함( 중복 코드 )
다이나믹 프록시 사용 :
런타임에 동적으로 생성하는 방법
자바 리플렉션 패키지에서 제공하는 기능
런타임에 특정 인터페이스를 구현하는 클래스 또는 인스턴스를 만드는 기술
Object Proxy.newProxyInstance( ClassLoader, Interfaces, InvocationHandler )
ex)
BookService bookService = (BookService)Proxy.newProxyInstance(클래스로더,new Class [](BookService.class), new InvocationHandler(){
bookServiceImpl bookServiceImpl = new BookServiceImpl();//리얼 서브젝트
@Override
public Object invoke(Object proxy, Method method, Object[] args)
...
}
구현이 더럽다 -> Spring AOP 등장
클래스 프록시를 만들 수 없다.
서브 클래스를 만들 수 있는 라이브러리를 사용해 프록시 생성
CGlib : 스프링, 하이버네이트가 사용하는 라이브러리
ByteBuddy : 바이트 코드 조작, 다이나믹 프록시 생성에 사용
출처 : https://www.inflearn.com/course/the-java-code-manipulation/dashboard