Java Reflection은 런타임에 클래스, 인터페이스, 필드, 메소드에 대한 정보를 조회하고 조작할 수 있게 해주는 Java API이다.
이를 통해 개발자는 컴파일 시점에는 알 수 없는 클래스의 객체를 조사하고, 동적으로 접근할 수 있다.
Class<?> stringClass = Class.forName("java.lang.String");
System.out.println(stringClass.getName()); // 출력: java.lang.String
String s = "example";
Class<?> classObj = s.getClass();
System.out.println(classObj.getName()); // 출력: java.lang.String
Method toUpperCaseMethod = String.class.getMethod("toUpperCase");
String result = (String) toUpperCaseMethod.invoke("hello");
System.out.println(result); // 출력: HELLO
class Example {
private String hidden = "initial";
}
Example example = new Example();
Field hiddenField = Example.class.getDeclaredField("hidden");
hiddenField.setAccessible(true); // private 필드 접근을 위해 필요
hiddenField.set(example, "modified");
System.out.println(hiddenField.get(example)); // 출력: modified
private으로 선언된 메서드를 테스트하는데 Reflection 이 이용될 수 있다.
public class SampleClass {
private String secretMethod() {
return "Secret Message";
}
}
public class ReflectionTest {
void test() {
SampleClass sample = new SampleClass();
Method method = SampleClass.class.getDeclaredMethod("secretMethod");
// 메서드 접근 가능하게 설정
method.setAccessible(true);
// 메서드 호출 및 결과 출력
String result = (String) method.invoke(sample);
assertThat(result).isEqualTo("Secret Message");
}
}
클래스나 메소드가 런타임에 결정되는 경우, Reflection을 사용하여 해당 클래스의 인스턴스를 생성하고 메소드를 호출할 수 있다.
의존성 주입
public class MyService {
@Autowired
private MyRepository repository; // Spring이 리플렉션을 사용하여 이 필드에 MyRepository의 인스턴스를 주입
}
Spring은 Reflection을 사용하여 클래스의 의존성을 런타임에 주입한다.
@Autowired 애너테이션이 붙은 필드에 대해 Spring 컨테이너는 해당 타입의 빈(bean)을 찾아 필드에 할당하고,
이 과정에서 리플렉션을 사용하여 필드에 접근하고, 해당 필드에 객체를 할당한다.
AOP
Spring AOP 에서 프록시 패턴을 통해 AOP를 구현하게 되면,
타깃 객체를 감싸는 프록시 객체가 생성되고 이 객체는 타깃 객체와 동일한 인터페이스를 갖는다.
이 때, 프록시 객체의 메서드가 실행되면 Reflection을 통해 타깃 객체의 메서드를 얻어 호출하고,
AOP를 통한 부가기능(로깅, 트랜잭션)을 삽입한다.
ORM
@Entity
public class User {
@Id
private Long id;
private String name; // Hibernate는 리플렉션을 사용하여 이 필드를 데이터베이스 컬럼과 매핑
}
Hibernate는 리플렉션을 사용하여 Java 객체와 데이터베이스 테이블 간의 매핑을 구현한다.
Java 클래스의 필드 이름과 데이터베이스 테이블의 컬럼 이름을 매핑하여 객체를 데이터베이스에 저장하거나,
데이터베이스에서 데이터를 조회하여 객체로 변환하는 과정에서 리플렉션을 활용합니다.