런타임시에 동작을 검사하거나 수정하는 것이다.
자바와 같은 정적언어에서 사용하면 컴파일 타임에 클래스의 정보를 구체적으로 알지 못해도 실행 중에 클래스에 접근할 수 있다.
Spring BeanFactory같은 곳에서 사용된다.
예시
public class ContainerService { public static <T> T getObject(Class<T> classType) { // 기본생성자를 통해서 인스턴스를 만든다. T instance = createInstance(classType); // 클래스의 모든 필드를 불러온다. Stream.of(classType.getDeclaredFields()) .filter(field -> field.isAnnotationPresent(AutoWired.class)) // 어노테이션에 AutoWired를 갖는 필드만 필터 .forEach(field -> { try { // 필드의 인스턴스 생성 Object fieldInstance = createInstance(field.getType()); // 필드의 접근제어자가 private인 경우 수정가능하게 설정 field.setAccessible(true); // 인스턴스에 생성된 필드 주입 field.set(instance, fieldInstance); } catch (IllegalAccessException e) { throw new RuntimeException(e); } }); return instance; } private static <T> T createInstance(final Class<T> classType) { try { // 해당 클래스 타입의 기본생성자로 인스턴스 생성 return classType.getConstructor().newInstance(); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException(e); } } }
- 리플렉션의 시작은 항상 Class<T> 에서 시작된다.
접근 방법
- "className.class"
- "인스턴스.getClass()"
- Class.ForName("classPath+클래스명")
- getAnnotations : 상속받은 어노테이션까지 조회
- getDeclaredAnnotations : 자기자신에게 붙어있는 어노테이션만 조회