본문으로 바로가기

Java Dynamic Proxy

category Back-End/Java 2018. 9. 17. 22:17
반응형

다이나믹 프록시란

메소드 인터셉팅을 통해 부수적인 코드를 삽입할 수 있는 기술, Spring AOP에서도 사용한다.

원래객체에 부수적인코드가 합쳐진 새로운 객체가 프록시 객체가 된다.


사용예)

1. 먼저 Proxy로 사용할 클래스에 대한 인터페이스를 정의한다.

1
2
3
4
5
6
7
class interface Computer {
 
    public void boot();
 
    public void prepareGUI();
 
}
cs


2. 정의한 인터페이스를 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ComputerImpl implements Computer {
 
    @Override
 
    public void boot() {
 
        System.out.println("현재 부팅이 진행중입니다...");
 
    }
 
    
 
    @Override
 
    public void prepareGUI() {
 
        System.out.println("현재 GUI를 로딩중입니다...");
 
    }
 
}
cs


3. InvocationHandler를 통해 프록시를 적용할 클래스의 메소드가 실행될 때 인터셉팅할 내용을 정의

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class MyLogger implements InvocationHandler {
 
    private Object realObject;
 
    public MyLogger(Object realObject) {
 
        this.realObject = realObject;
 
    }
 
    @Override
 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
        Object result = null;
 
        long start = System.currentTimeMillis();
 
    result = method.invoke(realObject, args);
 
        long end = System.currentTimeMillis();
 
        System.out.println("작업명 : "+method.getName()+", 소요시간 : "+(end-start)+"ms");
 
        return result;
 
    }
 
}
cs


4. 프록시 객체 생성

computer는 보통 객체, computerProxy는 로깅기능이 적용된 프록시 객체이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Application {
 
    public static void main(String[] args) {
 
        Computer computer = new ComputerImpl();    // 프록시가 적용되지 않은 객체
 
        Class<?> type = ComputerImpl.class;              // 프록시가 적용될 객체의 타입
 
        Computer computerProxy = (Computer) Proxy.newProxyInstance(type.getClassLoader(),
                                                                   type.getInterfaces(),
                                                                   new MyLogger(new ComputerImpl()));
        computerProxy.boot();
        computerProxy.prepareGUI();
 
    }
 
}
cs


위와같이 하면 boot, prepareGUI 메소드 실행 시 MyLogger에 구현한 대로 소요시간이 찍히는 것을 확인할 수 있다.


주의할 점은 프록시를 적용할 객체, 즉 ComputerImpl과 같은 realObject 역할의 객체 내부에서

자신의 메소드를 호출하는 것은 프록시로 잡히지 않는다.

예를들어

computerProxy.boot(); => 프록시 적용

computerProxy.prepareGUI(); => 프록시 적용

하지만

public void boot() {

    System.out.println("현재 부팅이 진행중입니다...");

    prepareGUI();    => 프록시 미적용

}

이유는 아직까지 모르겠다. 알면 적어야지..


반응형