reflection이란 구체 클래스를 사용하지 않고 메타 정보를 이용하여 해당 클래스의 메소드나 타입에 접근할 수 있도록 도와주는 Java Api이다.
따라서 클래스나 메서드의 메타정보를 동적으로 획득하고, 코드도 접근 제어자와 상관없이 동적으로 호출할 수 있다.
아래와 같은 곳에서 reflection을 사용하고 있다.
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
아래 예를 통해서 확인해보자.
@Test
void test() {
HelloReflection target = new HelloReflection();
log.info("start");
String result1 = target.callA();
log.info("end = ", result1);
log.info("start");
String result2 = target.callB();
log.info("end = ", result2);
}
이렇게 위와 같이 동일한 로직이지만 중간에 호출하는 메서드가 달라 공통화하기가 힘든데, 호출 메서들르 동적으로 처리하기 위해 사용하는 기술이 Reflection이다.
Reflection은 클래스나 메서드의 메타정보를 사용해서 동적으로 호출하는 메서드를 변경할 수 있다.
@Test
void reflection() throws Exception {
Class classHelloReflection = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$HelloReflection");
HelloReflection target = new HelloReflection();
Method methodCallA = classHelloReflection.getMethod("callA");
log.info("start");
Object result1 = methodCallA.invoke(target);
log.info("end = ", result1);
Method methodCallB = classHelloReflection.getMethod("callB");
log.info("start");
Object result2 = methodCallB.invoke(target);
log.info("end = ", result2);
}
기존에 target.callA()나 target.callB() 메서드를 직접 호출하는 부분이 Method로 바뀌었기 때문에 아래와 같이 공통 로직으로 만들 수 있게 되었다.
@Test
void reflection() throws Exception {
Class.forName("hello.proxy.jdkdynamic.ReflectionTest$HelloReflection");
HelloReflection target = new HelloReflection();
Method methodCallA = classHello.getMethod("callA");
dynamicCall(methodCallB, 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);
}
Reflection을 사용하면 클래스와 메서드의 메타정보를 사용해서 Application을 동적으로 유연하게 만들 수 있다.
그러나 Reflection 기술은 런타임에 동작하기 때문에, 컴파일 시점에 오류를 잡기 힘들다.
또한 Refleciton을 사용하면 접근 지시자를 무시할 수 있기에 추상화
최근의 타입 정보를 기반으로 컴파일 시점에 오류를 잡아주는 방식에서 역행하는 방식이기에 일반적으로 사용하기를 지양하도록 한다.