리플렉션(Reflection) 이란

리플렉션은 실체가 아닌 모습이 비추어져 있는 거울을 보고 기술을 사용하는 것. 즉, 프로그래밍 단에서는 구체적인 클래스 타입을 모르더라도 **런타임 시점에서 해당 클래스의 메서드, 타입, 어노테이션을 알고 접근(메서드 호출, 조회, 변경 등)**할 수 있도록 하는 프로그래밍 기법이다.

리플렉션을 활용하면 런타임 시점에서 특정 클래스나 메서드를 호출할 수 있기 때문에 유연성과 확장성을 높일 수 있다. 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> 클래스

                                                 Class<T> 클래스

이 거울을 통해 런타임 시점에서 클래스 내의 메서드를 확인해 호출하고, 필드, 어노테이션 등을 확인할 수 있다. 유의할 점은 리플렉션은 접근제어자를 무시할 수 있다는 것이다.

  1. 인스턴스 생성

    image.png

  2. 필드 정보 얻기

    image.png

  3. 메서드를 조회하고 동적으로 실행한다. 조회는 가능하지만 실행 시에는 .setAccessible(true) 를 통해서 권한을 열고 .invoke() 로 실행한다.

    image.png

  4. 어노테이션 확인

    image.png

그래서 리플렉션이 Spring DI에는 어떻게 쓰일까

스프링 컨테이너가 컴포넌트들을 스캔하고 의존성을 주입하는 과정이다. 한 단계씩 앞서 리플렉션 예제에서 본 메서드들이 어디에 어떻게 쓰이는지 본다.

<aside>

  1. 컴포넌트 스캔
  2. 빈(Bean) 생성 및 등록
  3. 의존성 주입
  4. 들어오는 HTTP 요청에 따라 필요할 때 객체 사용 </aside>

컴포넌트 스캔