BackEnd/Java&Kotilin
[Java] 다이나믹 프록시 (Dynamic Proxy)
Hero_O
2022. 7. 29. 12:10
다이나믹 프록시 ( Dynamic Proxy )
💡 목적
Proxy 패턴
디자인 패턴에는 프록시 패턴이라는 것이 있는데 이 프록시 패턴은 어떤 특정 로직 전•후에 부가적인 작업을 진행하기 위한 방법이다.
다만 이 프록시 패턴을 구현을 통해 위 코드에서 문제점을 확인할 수 있다.
- 다른 구현체가 생성될 때 마다. ProxyHero와 같은 새로운 프록시 클래스가 매번 생성돼야 한다.
- fight()와 defend() 메서드 모두 같은 기능을 하고 있음에도 불구하고 중복된 코드를 작성해야 한다.
이 문제를 해결하기 위해 JDK에는 java.lang.reflection.Proxy (프록시 팩토리)가 런타임 시점에 Dynamic 하게 인터페이스에 대한 구현체를 생성해주는 기능을 제공한다.
📖 사용 예시
public class Main {
public static void main(String[] args) {
Hero hero = (Hero) Proxy.newProxyInstance(
Hero.class.getClassLoader(),
new Class[]{Hero.class},
new InvocationHandler() {
Hero basicHero = new RealHero();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().contains("fight")) {
System.out.print("정의를 위해");
Object invoke = method.invoke(basicHero);
return invoke;
} else {
System.out.print("지구를 ");
Object invoke = method.invoke(basicHero);
return invoke;
}
}
}
);
hero.fight();
hero.defend();
}
}
/**
* 결과
* 정의를 위해싸우다.
* 지구를 지키다.
**/
- Proxy 정적 팩터리메서드를 통해 Dynamic Proxy를 생성한다.
- 정적 팩터리 메서드에 매개변수로 InvacationHandler를 구현체를 전달한다.
- Proxy 객체 메서드를 호출하면 InvocationHandler의 invoke()를 호출한다.
- 이 때 매개변수중 Method는 Real Object의 메서드를 의미한다.
Dynamic Proxy는 InvationHandler의 구현체를 통해 부가로직을 구현한다.
⬆️ 장점
1. 각각의 프록시 클래스를 미리 생성해둘 필요 없다.
2. 여러 프록시 클래스에 존재하는 중복 코드를 줄일 수 있다.
⬇️ 한계
1. 인터페이스에 대한 프록시만을 생성할 수 있어서 적용이 제한적이다.
2. 모든 메서드에 InvocationHandler에 invoke를 공통 적용하기 때문에 메서드별로 적용하기 위해서는 분기처리가 필요하다.