참고 1. 스프링-핵심-원리-고급편, 김영한
참고 2. 위키백과
아래는 캐시 서버 형태의 프록시 예시 코드이다.
1. 인터페이스를 만들기
아래 사진과 같이 프록시와 실제 서버는 같은 인터페이스를 상속받는다. 따라서, 먼저 가장 큰 틀이 되는 서버 인터페이스를 만들어야 한다.
아래와 같이 인터페이스를 만들어 준다. 이후, 프록시와 실제 클래스에서는 Operation을 상속받아 기능을 구현할 것이다.
public interface Subject {
String operation();
}
2. 실제 클래스와 프록시 만들기
실제 클래스
아래는 실제 서버 클래스이다. 간단히 로그를 출력하고 1초간 정지한다.
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class RealSubject implements Subject{
@Override
public String operation() {
log.info("실제 객체 호출");
sleep(1000);
return "data";
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
캐시 프록시
아래는 캐시형태의 프록시이다. 서버 인터페이스를 상속받아 구현하며, 이후 위 실제 클래스를 생성자 주입으로 받게 된다. 그리고 실제 클래스가 동작 후 해당 결과 값을 내부에 저장 후 이를 캐시로 사용한다.
@Slf4j
public class CacheProxy implements Subject{
private Subject target;
private String cacheValue;
public CacheProxy(Subject subject) {
this.target = subject;
}
@Override
public String operation() {
log.info("프록시 호출");
if (cacheValue == null) {
cacheValue = target.operation();
}
return cacheValue;
}
}
3. 클라이언트
이제 위에서 만든 Subject(Server Instance) 혹은 CacheProxy의 operation을 실행하기 위한 클라이언트를 아래와 같이 정의해야 한다. 클라언트는 실제 서버 객체 혹은 프록시를 생성자로 주입받고, operation을 실행한다.
public class Client {
private Subject subject;
public Client(Subject subject) {
this.subject = subject;
}
public void execute() {
subject.operation();
}
}
사용 예시
아래 2번째 테스트 코드와 같이 중간에 프록시를 거치게 되면, 프록시에 정의한 접근제어가 추가 된다. (아래의 CacheProxy는 최초 1회만 실제 서버 객체의 함수를 호출한다.)
@Test
void noProxyTest() {
RealSubject realSubject = new RealSubject();
Client client = new Client(realSubject);
client.execute();
client.execute();
client.execute();
}
@Test
void ProxyTest() {
RealSubject realSubject = new RealSubject();
CacheProxy cacheProxy = new CacheProxy(realSubject);
Client client = new Client(cacheProxy);
client.execute();
client.execute();
client.execute();
}