예시
Proxy : RealSubject를 대리하는 요소(추가적인 부가기능을 정의하는 클래스)
Client : proxy를 이용하는 요소
/**
* Subject
* */
public interface GameService {
void startGame();
}
/**
* 인터페이스가 있는 경우(Proxy)
*/
public class GameServiceProxy implements GameService {
private GameService gameService;
public GameServiceProxy(GameService gameService) {
this.gameService = gameService;
}
@Override
public void startGame() {
long before = System.currentTimeMillis();
gameService.startGame();
System.out.println("시간 = " + (System.currentTimeMillis() - before));
}
/**
* Lazy initialization( 지연 초기화 )
* 이때는 생성자가 없어야댐
* */
/*@Override
public void startGame() {
long before = System.currentTimeMillis();
if (this.gameService == null) {
this.gameService =new DefaultGameService();
}
gameService.startGame();
System.out.println("시간 = " + (System.currentTimeMillis() - before));
}*/
}
/**
* 인터페이스가 없는 경우
*/
public class GamsServiceProxy extends GameService {
@Override
public void startGame() throws InterruptedException {
long before = System.currentTimeMillis();
super.startGame();
System.out.println(System.currentTimeMillis() - before);
}
}
/**
* RealSubject
* */
public class DefaultGameService implements GameService {
@Override
public void startGame() {
System.out.println("이 자리에 오신 여러분들을 환영합니다.");
}
}
public class Client {
public static void main(String[] args) throws InterruptedException {
GameService gameService = new GameServiceProxy(new DefaultGameService());
gameService.startGame();
}
}
public class Java {
public static void main(String[] args) {
ProxyInJava proxyInJava = new ProxyInJava();
proxyInJava.dynamicProxy();
}
private void dynamicProxy() {
GameService gameServiceProxy = getGameServiceProxy(new DefaultGameService());
// 다음과 같이 메서드 명으로 호출 해주면 Reflection을 통해서 해당메서드가 사용됌.
gameServiceProxy.startGame();
gameServiceProxy.endGame();
}
/**
* 공통 부가기능은 모든메서드를 오버라이드할 필요없이 reflection을 이용해서 사용하면 간단하게 만들수 있다.
*
* @param target
* @return
*/
private GameService getGameServiceProxy(GameService target) {
return (GameService) Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[]{GameService.class}, (proxy, method, args) -> {
System.out.println("start");
method.invoke(target, args);
System.out.println("end");
return null;
});
}
}
/* 결과
start
이 자리에 오신 여러분들을 환영합니다.
end
start
안녕히 가세요
end
*/
@Aspect
@Component
public class PerfAspect {
/**
* 시간을 측정하는 메서드
* 여기서 ProceedingJoinPoint는 실행되는 메서드
*
* @param point
* @throws Throwable
*/
@Around("bean(gameService)")
public void timestamp(ProceedingJoinPoint point) throws Throwable {
long before = System.currentTimeMillis();
point.proceed();
System.out.println("point.getSignature().getName() = " + point.getSignature().getName());
System.out.println(System.currentTimeMillis() - before);
}
@Around("bean(exService)")
public void timestamp(ProceedingJoinPoint point) throws Throwable {
long before = System.currentTimeMillis();
point.proceed();
System.out.println("point.getSignature().getName() = " + point.getSignature().getName());
System.out.println(System.currentTimeMillis() - before);
}
}
@Service
public class GameService {
public void startGame() {
System.out.println("이 자리에 오신 여러분을 진심으로 환영합니다.");
}
public void endGame() {
System.out.println("안녕히 가세요");
}
}
출처 : 백기선님의 디자인패턴