구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 필드들에 접근할 수 있도록 해주는 자바 API
런타임에 지금 실행되고 있는 클래스를 가져올 수 있습니다.
일단 설명만 들어봤을 떄는 사용하기가 좀 매우 꺼림칙한 설명이긴 합니다 ㅎㅎ
런타임 시에 클래스 타입을 모르는 상태로 클래스를 사용한다?? 너무 리스크가 큰 API 기능이라고 생각했었습니다
생각 외로 이 Reflection API를 사용한 기능들이 많아서 놀랐습니다.
심지어 이 기능들을 자주 사용해서 더욱더 놀란 것 같습니다.
Reflection 사용법은 되게 간단합니다.
다만 저한테는 평소에 사용한 적이 거의 없어서 생소하긴 했네요 ㅎㅎ
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
public String value() default "";
}
@TestAnnotation("Test Value")
public class Account {
private String name = "신한";
private Long value;
public Account() {
}
private void printValue () {
System.out.println(value);
}
public void deposit(long value) {
this.value += value;
System.out.println("value : " + this.value);
}
}
Class clazz = Class.forName("Account");
// Class clazz = Account.class; 이 방법이 오타도 안나고 훨씬 좋지 않을까요?
Constructor constructor = clazz.getDeclaredConstructor();
Class clazz = Account.class;
Method[] methods = clazz.getDeclaredMethods();
methods[0].invoke(clazz.newInstance()) // printValue 함수 실행
Annotation[] annos = Account.class.getAnnotations();
for (Annotation anno : annos) {
System.out.println(anno.toString());
// 특정 어노테이션을 구분할 수 도 있습니다.
if (anno.annotationType() == TestAnnotation.class) {
TestAnnotation testAnno = (TestAnnotation) anno;
System.out.println(a.value());
}
}
Reflection을 사용해서 특정 어노테이션을 구분하는 하는 기능을 최근에 자주 쓰고 있습니다.
Class clazz = Account.class;
Field[] field = clazz.getDeclaredFields();
Account account = new Account();
field[1].set(account, 1000); // 거의 Setter 느낌이네요.
System.out.println(field[1].get(account)); // Getter 느낌 , 1000 출력
Reflection을 공부하려고 마음먹게 된 계기는 강남언니 블로그에서 레거시한 코드로 인한 어떠한 문제가 발생하였는데 해당 문제를 해결하려고 Reflection을 적극 사용하여 해결한 글을 보고 공부하고 싶다는 마음을 얻었습니다.
그리고 최근에 Reflection을 사용하여 특정 어노테이션에 대한 처리를 한다던가
스프링부트에서 매 Request의 로깅처리를 위해 AOP를 사용해 로깅처리를 하는 과정에서 사용해 보았습니다.
공부하기 전에는 진짜 막상 쓸일도 딱히 없었는데 딱 공부하는 타이밍 쯤에 Reflection을 사용할 일들이 생기네요 ㅎㅎ
Reflection을 공부하게 된 계기를 가지게 된 강남언니 블로그 링크를 남깁니다.
강남언니 블로그