동적 프록시 - (1) 리플렉션

Drumj·2023년 2월 8일
0

오늘의 학습

프록시를 사용하는 프록시 패턴, 데코레이터 패턴을 배운 이후

프록시 클래스들의 소스 코드는 거의 동일한 모양을 하고 있는데 이 프록시를 적용하기 위해서
계속 프록시 클래스들을 만들어야 하는 문제점이 있었다.

동적 프록시 기술을 이용해서 쉽게 적용시켜보자!

  1. 리플렉션
  2. JDK 동적 프록시
  3. CGLIB

1. 리플렉션

JDK 동적 프록시를 이해하기 위해 먼저 자바의 리플렉션 기술을 이해해야 한다고 한다.

이 기술을 사용하면 클래스나 메서드의 메타정보를 동적으로 획득하고, 코드도 동적으로 호출 할 수 있다.

최소한의 리플렉션 기술을 알아보자

//(생략)
//공통 로직 1 시작
log.info("start");
String result1 = target.callA();
log.info("result ={}", result1);
//공통 로직 1 종료

//공통 로직 2 시작
log.info("start");
String result2 = target.callB();
log.info("result ={}", result2);
//공통 로직 2 종료

위 코드에서 공통되는 코드는 아래와 같다

log.info("start");
String result = xxx(); //호츌 대상이 다름, 동적 처리 필요
log.info("result ={}", result);

이때 동적 처리 필요 부분을 리플렉션을 사용하여 해결할 수 있다고 한다!

참고로 람다를 사용해서 공통화하는 것도 가능하다.하지만 학습을 위해서 람다를 사용하기 어려운 상황이라는 가정하에 리플렉션에 집중해보자

@Test
void reflection1() throws Exception {
	//클래스 정보
	Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello"); //클래스 메타정보 획득
	Hello target = new Hello();
    
	//callA 메서드 정보
	Method methodCallA = classHello.getMethod("callA"); //해당 클래스의 call메서드 메타정보 획득
	Object result1 = methodCallA.invoke(target); //획득한 메서드 메타정보로 실제 인스턴스의 메서드를 호출
	log.info("result1={}", result1);
    
	//callB 메서드 정보
	Method methodCallB = classHello.getMethod("callB");
	Object result2 = methodCallB.invoke(target);
	log.info("result2={}", result2);
}

위 코드를 보면 methodCallA, methodCallB 모두 Method 이다. 이제 공통 로직을 만들 수 있게 되었다.

@Test
void reflection2() throws Exception {
	Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");
	Hello target = new Hello();
	Method methodCallA = classHello.getMethod("callA");
	dynamicCall(methodCallA, target);
	Method methodCallB = classHello.getMethod("callB");
	dynamicCall(methodCallB, target);
}

private void dynamicCall(Method method, Object target) throws Exception {
	log.info("start");
	Object result = method.invoke(target);
	log.info("result={}", result);
}

최종적으로 이렇게 코드가 완성된다.
target.callA(), target.callB() 코드를 리플렉션을 사용해서 Method라는 메타정보로 추상화했다. 덕분에 공통 로직을 만들어서 사용할 수 있게 되었다.

리플렉션을 사용하면 애플레케이션을 동적으로 유연하게 만들 수 있다.
하지만 리플렉션 기술은 런타임에 동작하기 때문에 컴파일 시점에 오류를 잡을 수 없다.


0개의 댓글