본문 바로가기

공부내용 정리/스프링

Reflection API 개념 및 예제

Reflection

- 힙 영역에 로드돼있는 클래스 타입의 객체를 통해 필드/메소드/생성자를 접근제어자 상관없이 사용할 수 있또록 지원하는 API

- 컴파일 시점이 아닌 런타임 시점에 동적으로 특정 클래스의 정보를 추출해 낼 수 있는 프로그래밍 기법

- 주로 프레임워크 또는 라이브러리 개발 시 사용됨

 

Reflection 사용하는 프레임워크 / 라이브러리

- Spring Framework (ex. DI)

- Test Framework (ex.JUnit)

- JSON Serialization/Deserialization 라이브러리 (ex.Jackson)

- 등등

 

 

예제 실습

- 목표 : @Controller, @Service 등 어노테이션이 설정돼있는 모든 클래스를 찾아서 출력한다.

- IDE 는 Intellij 를 사용, 프로젝트 생성 방법은

1. [File] - [New] - [Project] - [Gradle : Java] - [OK]

2. build.gradle

build.gradle

 

3. 패키지 구조

 

4. annotation 패키지

- Controller

 

- Service

 

- RequestMapping

 

- RequestMethod (enum)

 

5. controller 패키지

- HomeController

 

- HealthCheckController

 

- HomeService

 

6. model 패키지

- User

 

7. Test

첫번째 테스트 controllerScan() : 

이번 예제 실습에 목표는

" @Controller, @Service 등 어노테이션이 설정돼있는 모든 클래스를 찾아서 출력한다. " 였다.

먼저, Reflection 클래스로  "org.example" 패키지 아래에 있는 클래스를 검색한다.

getTypesAnntatedWith 에서 인자값으로 annotations 를 받는데 여기에 Controller.class, Service.class 가 들어온다.

그럼 annotations.forEach(annotation -> beans.addAll(reflections.getTypesAnnotatedWith(annotations))) 에서

annotations 값에 Controller.class, Service.class 가 들어가게 되는것이고, 

relfections.getTypesAnnotatedWith(annotations) 는 위에서 @Controller 를 사용한 HomeController.class, HealthCheckController.class 가, @Service 를 사용한 HomeService.class가  검색돼서 beans 에 담기게 된다.

테스트 결과로 HealthCheckController, HomeService, HomeController 가 출력됨.

 

 

두번째 테스트 ShowClass()

"두번째 테스트의 목적은 org.example.model.User 클래스에서 선언된 fields, 생성자, 메소드를 찾기"

45번째 줄 : User 클래스에 대한 Class객체를 가져와서 clazz 변수에 할당 한다.

48번째 줄: User 클래스의 모든 선언된 필드(멤버변수) 정보를 로깅

49번째 줄: User 클래스의 모든 선언된 생성자 정보를 로깅

50번째 줄: User 클래스의 모든 선언된 메소드 정보를 로깅

 

세번째 테스트 load()

- 힙 영역에 로드된 클래스타입 객체를 가져오는 방법 3가지

 

테스트 결과