1. Reflection이란?
구체적인 클래스 타입을 알지 못해도, 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API
- 컴파일 시간 (Compile Time)이 아니라 실행 시간(Run Time)에 동적으로 특정 클래스의 정보를 객체화를 통해 분석 및 추출해낼 수 있는 프로그래밍 기법
- 클래스 로더가 클래스를 로딩 시킨다. (클래스 파일 JVM위에 올라감)
- 또 다른 클래스로 동적으로 로딩(Dynamic Loading)한다.
“구체적인 클래스 타입을 알지 못해도 클래스 정보 접근 가능”
⇒ 구체적인 클래스 타입을 알지 못해도, 클래스 정보에 접근이 가능하다는 것이 무슨 뜻인지 알아보자.
Example
- obj라는 이름의 객체는 컴파일 타임에 Object로 타입이 결정됐기 때문에 Object 클래스의 인스턴스 변수와 메서드만 사용할 수 있다.
- 자바는 컴파일러를 사용한다. 즉 컴파일 타임에 타입이 결정된다.
- 생성된 obj라는 객체는 Object 클래스라는 타입만 알 뿐, Customer 클래스라는 구체적인 타입을 모른다.
결국 컴파일러가 있는 자바는 구체적인 클래스를 모르면 해당 클래스의 정보에 접근할 수 없다는 것을 알 수 있다. ⇒ Reflection을 사용하면 구체적인 클래스 타입을 알지 못해도 클래스 정보에 접근할 수 있게 해준다.
- obj라는 객체는 Object 클래스라는 타입이지만 Customer 클래스의 printIndex 메서드에 접근하고 실행시킬 수 있다.
2. Reflection의 클래스 정보 접근
클래스에 선언된 생성자, 메서드, 필드
getMethods VS getDeclaredMethods getMethods public 접근지정자 메서드만 접근 가능하다. getDeclaredMethods 접근지정자와 상관없이 class 안의 모든 메서드에 접근 가능하다.
Reflection을 이용해서 Private 필드, 메서드 접근
- 기본 생성자만 있다면 setter, getter 없어도 심지어 private 변수와 메서드에도 접근가능하다.
3. Reflection 원리
자바에서는 JVM이 실행되면 사용자가 작성한 자바 코드가 컴파일러를 거쳐 바이트 코드로 변환되어 static 영역에 저장된다.
Reflection API는 이 정보를 활용한다.
그래서 클래스 이름만 알고 있다면 언제든 static 영역을 뒤져서 정보를 가져올 수 있다.
4. Reflection의 단점
- 성능 오버헤드
- 컴파일 타임이 아닌 런타임에 동적으로 타입을 분석하고 정보를 가져오므로 JVM을 최적화 할 수 없다.
- 추상화
- 직접 접근할 수 없는 private 인스턴스 변수, 메서드에 접근하기 때문에 내부를 노출하면서 추상화가 깨진다.
애플리케이션 개발보다는 프레임워크나 라이브러리에서 많이 사용된다. 어떤 클래스를 만들지 예측할 수 없기 때문에 동적으로 해결해주기 위해 Reflection을 사용한다.
5. Reflection의 활용
1. BeanFactory (Spring Container)
- Bean은 애플리케이션이 실행한 후 런타임에 객체가 호출될 때 동적으로 객체의 인스턴스를 생성하는데 이때 BeanFactory에서 Reflection을 사용한다.
2. Spring JPA
- “JPA의 Entity 객체에는 기본 생성자가 있어야 한다.”
- JPA에서 Entity에 대한 객체를 생성하기 위해서 Java Reflection을 사용한다.
3. @Requestbody
- @RequestBody을 사용하면 ObjectMapper가 JSON Field와 Java Field (Dto)를 매칭 시킨다.
- 이때 Reflection을 사용해서 값을 주입해준다.
⇒ Dto의 setter는 필요없다, Dto에 기본 생성자가 필요하다.
Parameter로 생성자를 가져올 수 있다. Reflection API로 가져올 수 없는 정보 중 하나가 생성자의 인자(Parameter 정보) 그래서 기본 생성자가 반드시 있어야 객체를 생성할 수 있다. 기본 생성자로 객체를 생성하고 필드 값 등은 Reflection으로 넣어준다.
private 메서드를 테스트 코드 작성하기 위해서는 어떻게 해야 할까??
리플렉션 사용 가능 → 이게 맞을까??