-
Reflection API ?☕️ java 2023. 2. 9. 19:43
📌 Reflection API
💡 구체적인 클래스 타입을 알지 못해도 그 클래스의 정보(메서드, 타입, 변수 등등)에 접근할 수 있게 해주는 자바 API
📌 Reflection API 기능
Person.java
public class Person { private String name; protected String address; public int age; }
필드 접근
- Class<T> 클래스의 getFields() 메서드
- public으로 선언된 필드만 조회가 가능
- Class<T> 클래스의 getDeclaredFields() 메서드
Test
@Test void get_field() { Object person = new Person(); Field[] getFields = person.getClass().getFields(); Field[] getDeclaredFields = person.getClass().getDeclaredFields(); System.out.println("-- getFields() --"); for (Field field : getFields) { System.out.println(field.getName()); } System.out.println("-- getDeclaredFields() --"); for (Field field : getDeclaredFields) { System.out.println(field.getName()); } List<String> fieldNames = getFieldNames(getFields); List<String> declaredFieldNames = getFieldNames(getDeclaredFields); assertTrue(declaredFieldNames .containsAll(Arrays.asList("name", "address", "age"))); assertFalse(fieldNames .containsAll(Arrays.asList("name", "address", "age"))); assertTrue(fieldNames .containsAll(Arrays.asList("age"))); }
결과
-- getFields() -- age -- getDeclaredFields() -- name address age
인스턴스 생성
- getConstructor()
- 타입을 명시해 원하는 생성자 조회
- 해당하는 생성자가 없을 수도 있기 때문에 try-catch 문을 사용해야 한다.
- newInstance()
- 가져온 생성자의 newInstance() 메서드를 사용해 인스턴스를 생성할 수 있다.
Person.java
public class Person { private String name; protected String address; public int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public Person(String name, String address, int age) { this.name = name; this.address = address; this.age = age; }
Test
@Test void new_instance() { Class<Person> clazz = Person.class; try { Constructor<Person> constructor = clazz.getConstructor(String.class, int.class); Person beomsic = constructor.newInstance("beomsic", 20); assertNotNull(beomsic); assertEquals("beomsic", beomsic.getName()); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { e.printStackTrace(); } }
메소드 접근
- getMethod()
- public 메서드에만 접근 가능
- getDeclaredMethod()
Person.java
public class Person { private String name; protected String address; public int age; public Person(String name, String address, int age) { this.name = name; this.address = address; this.age = age; } public String getName() { return name; } }
Test
@Test void get_method() { Class<Person> clazz = Person.class; try { Constructor<Person> constructor = clazz.getConstructor(String.class, String.class, int.class); Person person = constructor.newInstance("beomsic", "서울", 10); Method getName = person.getClass().getMethod("getName"); Method getNameByDeclaredMethod = person.getClass().getDeclaredMethod("getName"); assertNotNull(getName); assertNotNull(getNameByDeclaredMethod); // invoke() : 메소드 실행 assertEquals("beomsic", (String) getName.invoke(person)); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { e.printStackTrace(); } }
사용
Spring Container의 BeanFactory
- Bean은 애플리케이션이 실행한 후 런타임에 객체가 호출될 때 동적으로 객체의 인스턴스를 생성한다.
- 이때, Spring Container의 BeanFactory에서 리플렉션을 사용
Spring Data JPA
- Entity에 기본 생성자가 필요한 이유
- 동적으로 객체 생성 시 Reflection API를 활용하기 때문
- Reflection API로는 생성자의 인자 정보를 가져올 수 없다.
- 따라서, 기본 생성자가 반드시 있어야 객체를 생성할 수 있다.
- 기본 생성자로 객체를 생성만 하면 필드 값등은 Reflection API로 넣어줄 수 있다.
참고자료
https://www.baeldung.com/java-reflection
https://blog.gangnamunni.com/post/Annotation-Reflection-Entity-update/
https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/
'☕️ java' 카테고리의 다른 글
[Java] String / StringBuffer / StringBuilde (0) 2023.03.03 [Java] Static 과 Final (0) 2023.03.03 커스텀 validation 만들기 (0) 2023.01.28 equals / hashCode (0) 2022.12.07 CheckedException 과 UncheckedException (0) 2022.10.10 - Class<T> 클래스의 getFields() 메서드