리플렉션은 실체가 아닌 모습이 비추어져 있는 거울을 보고 기술을 사용하는 것. 즉, 프로그래밍 단에서는 구체적인 클래스 타입을 모르더라도 **런타임 시점에서 해당 클래스의 메서드, 타입, 어노테이션을 알고 접근(메서드 호출, 조회, 변경 등)**할 수 있도록 하는 프로그래밍 기법이다.
리플렉션을 활용하면 런타임 시점에서 특정 클래스나 메서드를 호출할 수 있기 때문에 유연성과 확장성을 높일 수 있다. JinService
클래스를 불러와서 런타임에서 인스턴스를 생성할 뿐만 아니라 메서드와 멤버에 대해 조회/수정하는 예시를 보자.
public class JinService {
protected String name = "jin";
private String company = "soma";
private String say(String name) {
return "Hello, " + name;
}
public String getName() {
return name;
}
}
먼저, 거울이 필요하다. Java는 Class<T>
를 통해 클래스에 대한 거울을 보고 수정할 수 있도록 API를 제공한다. 여기서 Class<T>는 흔히 말하는 클래스 키워드가 아님을 유의한다.
// 방법 1.
Class<?> jinServiceClass = Class.forName("inflearn.reflection.JinService");
// 방법 2.
Class<JinService> jinServiceClass = JinService.class;
// 방법 3.
JinService jinService = new JinService();
Class<? extends JinService> jinServiceClass = jinService.getClass();
Class<T> 클래스
이 거울을 통해 런타임 시점에서 클래스 내의 메서드를 확인해 호출하고, 필드, 어노테이션 등을 확인할 수 있다. 유의할 점은 리플렉션은 접근제어자를 무시할 수 있다는 것이다.
인스턴스 생성
필드 정보 얻기
메서드를 조회하고 동적으로 실행한다. 조회는 가능하지만 실행 시에는 .setAccessible(true)
를 통해서 권한을 열고 .invoke()
로 실행한다.
어노테이션 확인
스프링 컨테이너가 컴포넌트들을 스캔하고 의존성을 주입하는 과정이다. 한 단계씩 앞서 리플렉션 예제에서 본 메서드들이 어디에 어떻게 쓰이는지 본다.
<aside>
컴포넌트 스캔