자바 리플렉션의 기본 원리와 사용 예
1. 리플렉션이란?
리플렉션(Reflection)은 Java에서 런타임에 클래스의 메타데이터를 조회하거나 수정할 수 있는 강력한 기능입니다.
이를 통해 개발자는 실행 중인 Java 애플리케이션 내부의 클래스, 메서드, 변수 등에 대한 정보를 동적으로 액세스하고 조작할 수 있다.
2. Person 클래스를 통한 리플렉션 사용 예
Person 클래스는 구성은 아래와 같습니다.
속성 : name, age
메서드 : sayHello
생성자 : 전부
public class Person {
private String name;
private int age;
public Person(String name) {
this.name = name;
}
public Person(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void seyHello() {
System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
리플렉션을 사용하여 이 클래스의 정보를 런타임에 조회해볼겁니다
아래와 같이 해보겠습니다
1. 클래스 이름 조회
2. 생성자 정보 조회
3. 메서드 정보 조회
4. 필드 정보 조회
public class ReflectionExam {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> personClass = Class.forName("com.smsoft.blogsamplecode.reflection.Person");
System.out.println("1. 클래스 이름 조회 : " + personClass.getName());
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("2. 생성자 정보 조회 : " + constructor.toString());
}
Method[] methods = personClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println("3. 메서드 정보 조회 : " + method.toString());
}
Field[] fields = personClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("4. 필드 정보 조회 : " + field.toString());
}
}
}
결과는 아래와 같습니다.
리플렉션은 위와 같습니다.
이 리플렉션 원리를 이용하여서
DTO등에 객체를 매핑하는데 사용하는 ModelMapper를 바로 사용해봅시다.
PersonDTO에 Person객체를 복사 할 겁니다.
먼저 ModelMapper dependency를 추가해주고, PersonDTO 클래스를 만들어줍니다.
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.0.0</version>
</dependency>
public class PersonDTO {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "PersonDTO{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ModelMapperExam {
public static void main(String[] args) {
ModelMapper modelMapper = new ModelMapper();
Person person = new Person("sumin", 30);
PersonDTO personDTO = modelMapper.map(person, PersonDTO.class);
System.out.println(personDTO);
}
}
메인에서 .map메서드를 이용합니다
첫번째 인자에 Person객체를 넣고, 두번째인자에 타겟클래스를 넣어주면 타겟객체에 데이터가 복사가 됩니다.
아주 간단하게 데이터를 복사해주는 ModelMapper는 내부적으로 리플렉션을 사용하고 있습니다.
리플렉션은 정말 다양한 부분에 사용됩니다
스프링 핵심기술인 DI(dependency injection)도 리플렉션을 사용하여 구현되고 있습니다.
결론
리플렉션의 장점
1. 유연성: 리플렉션을 사용하면 런타임에 클래스의 메타데이터를 조회하거나 수정할 수 있어, 코드의 유연성이 크게 향상됩니다.
2. 결합도 감소: 리플렉션을 활용하면 구현체에 대한 직접적인 참조 없이 인터페이스를 통한 프로그래밍이 가능해져, 코드의 결합도를 낮출 수 있습니다
3. 구성 유연성: XML이나 애노테이션 기반의 설정 등을 통해 애플리케이션의 구성을 런타임에 변경할 수 있는 능력을 제공합니다.
예를 들어, Spring Framework에서 리플렉션을 사용하여 의존성 주입을 처리하는 것이 이에 해당합니다.
리플렉션의 단점
1. 성능 저하: 리플렉션은 직접적인 메서드 호출이나 필드 접근에 비해 상대적으로 느립니다.
2. 보안 문제: 리플렉션을 사용하면 런타임에 private 메서드나 필드에 접근할 수 있어, 잘못 사용될 경우 보안 취약점이 될 수 있습니다.
3. 복잡성 증가: 리플렉션을 사용하는 코드는 이해하기 어려울 수 있으며, 디버깅이 어려워질 수 있습니다.
잘 사용합시다
참고자료
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html
'자바' 카테고리의 다른 글
[자바] JSON 데이터 파싱후 JUnit5로 테스트 (json/application) (0) | 2024.02.18 |
---|---|
[자바] Form 데이터 파싱후 JUnit5로 테스트 (x-www-form-urlencoded) (2) | 2024.02.17 |
[자바] 레코드(Records) : 코드 간결성과 효율성을 높이는 새로운 방법 (0) | 2024.01.28 |
[자바] Try-with-resources in Java: 코드를 깔끔하게 유지하는 현대적 방법 (0) | 2024.01.21 |
[자바] 클래스 파일 구조, VM명세서 (0) | 2023.11.14 |