2021 05 17
2021-05-17
리플렉션
- 공식 문서
- 리플렉션은 자바 코드로 부터 하여금 로드된 클래스의 필드/메서드/생성자를 찾을 수 있도록 함
- 또한 보안 규제를 준수하면서 리플렉트된 필드/메서드/생성자를 변화+실행시킴
- 리플렉션은 JVM에서 실행중인 어플리케이션의 런타임 행동을 변화시키기 위해 주로 사용됨
- JAVA 잘 아는 사람만 써야함...ㅎ
- 굉장히 강력한 도구들을 제공해줌
- 장점
- Extensibility Features
- Class Browser and Visual Development Environments
- Debuggers and Test Tools
- 단점
- Performance Overhead
- JVM 최적화 포기해야함
- Security Restrictions
- 런타임 permission이 필요함
- Exposure of Internals
- 예상 못한 사이드이펙트 발생 가능
- 정의
- "구체적인 클래스 타입"을 알지 못해도, 해당 클래스의 메서드/타입/변수들에 접근할 수 있도록 하는 자바 API
- 사용될 클래스가 어떤 타입인지 모르지만, 리플렉션을 이용하여 코드 작성하고 실행 시점에 확인하여 활용
- 객체를 통해 클래스의 정보를 분석해내는 프로그램 기법
- 실행중인 자바 프로그램 내부를 검사하고, 내부의 속성을 수정할 수 있도록 함
- 필요성
- 동적으로 클래스를 사용해야 할때 필요
- 작성 시점에는 어떤 클래스를 사용하는지 모르는 경우
- 런타임에 클래스 가져와서 실행해야 하는 경우
- 스프링의 BeanFactory (Spring Container)
- 어플리케이션이 실행한 후, 객체가 호출될 때 객체의 인스턴스 생성... 이때 Reflection 사용
- 따라서 사용하는 사람이 어떤 클래스 만들지 모르는 프레임워크, 라이브러리에서 많이 씀
- 컴파일 타임에 클래스의 이름들을 모를때 매우 유용
- 생성자를 검사하고, 런타임에 클래스를 객체화 시킬 수 있음
- 런타임에 메서드를 실행할 수 있음
- 방법
- 딱히 외부 jar 같은거 넣을 필요 X
- JDK가 java.lang.reflect 제공해줌
- Java 클래스 파일은 바이트 코드로 컴파일 되어 Static 영역에 위치함
- 클래스 이름만 알고 있으면 해당 영역 뒤져서 정보 가져오기 가능
- Reflection Class를 사용하기 위해서는 다음 스텝들이 필요
1. 수정하기 원하는 java.lang.Class 객체 얻기
2. getDeclaredMethods와 같은 메서드를 Call 해서, 클래스에 정의된 모든 메서드의 리스트 얻음
3. 정보 수정을 위해 Reflection API 사용
public class ReflectionTest {
@Test
public void getFields() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Class<Article> article = Article.class;
final Article articleObj = article.getConstructor().newInstance();
System.out.println("article.id= " + articleObj.id);
Field[] articleDeclaredFields = article.getDeclaredFields();
for (Field field : articleDeclaredFields) {
System.out.println("field.getType() = " + field.getType());
System.out.println("field.getName() = " + field.getName());
System.out.println("---------");
field.setAccessible(true);
if (field.getType().isPrimitive()) {
field.set(articleObj, 10);
}
}
System.out.println("article.id= " + articleObj.id);
}
}
class Article {
public int id;
public String title;
public Article() {
}
}
/*
[결과]
article.id= 0
field.getType() = int
field.getName() = id
---------
field.getType() = class java.lang.String
field.getName() = title
---------
article.id= 10
*/