클래스 구조 정보 획득
리플렉션 API를 사용하면 런타임에 클래스의 구조적 정보를 얻을 수 있습니다. 다음 코드는 주요 메타데이터 조회 방법을 보여줍니다:
public class ReflectionInspector {
public static void main(String[] args) throws Exception {
Class<?> targetClass = Class.forName("com.example.model.Student");
// 클래스 식별자 획득
System.out.println("전체 경로: " + targetClass.getName());
System.out.println("단순 이름: " + targetClass.getSimpleName());
// public 필드만 조회
for (var field : targetClass.getFields()) {
System.out.println("Public 필드: " + field);
}
// 모든 접근 제어자의 필드 조회
for (var field : targetClass.getDeclaredFields()) {
System.out.println("선언된 필드: " + field);
}
// 특정 필드 조회 (private 포함)
Field ageField = targetClass.getDeclaredField("age");
System.out.println("특정 필드: " + ageField);
// public 메서드 목록
System.out.println("--- Public 메서드 ---");
for (var method : targetClass.getMethods()) {
System.out.println(method);
}
// 클래스 내 선언된 모든 메서드
System.out.println("--- 선언된 메서드 ---");
for (var method : targetClass.getDeclaredMethods()) {
System.out.println(method);
}
// 생성자 정보 조회
System.out.println("--- Public 생성자 ---");
for (var constructor : targetClass.getConstructors()) {
System.out.println(constructor);
}
System.out.println("--- 선언된 생성자 ---");
for (var constructor : targetClass.getDeclaredConstructors()) {
System.out.println(constructor);
}
}
}
객체 생성 및 메서드 호출
리플렉션을 통해 클래스의 인스턴스를 동적으로 생성하고 메서드를 호출할 수 있습니다:
public class DynamicInvoker {
public static void main(String[] args) throws Exception {
Class<?> targetClass = Class.forName("com.example.model.Student");
// 기본 생성자로 객체 생성
Object student1 = targetClass.getDeclaredConstructor().newInstance();
System.out.println("기본 생성자 객체: " + student1);
// 매개변수가 있는 생성자 활용
Constructor<?> paramConstructor = targetClass
.getDeclaredConstructor(String.class, int.class, int.class);
Object student2 = paramConstructor.newInstance("alice", 22, 100);
System.out.println("매개변수 생성자 객체: " + student2);
// 필드 값 설정 및 조회
Object student3 = targetClass.getDeclaredConstructor().newInstance();
student3.getClass().getMethod("setAge", int.class).invoke(student3, 25);
int retrievedAge = (int) student3.getClass()
.getMethod("getAge").invoke(student3);
System.out.println("설정된 나이: " + retrievedAge);
// private 메서드 호출을 위한 접근 허용
Method privateMethod = targetClass
.getDeclaredMethod("internalProcess", String.class);
privateMethod.setAccessible(true);
privateMethod.invoke(student3, "테스트 데이터");
}
}
어노테이션 정보 추출
리플렉션을 사용하면 클래스와 필드에 적용된 어노테이션의 메타데이터를 읽을 수 있습니다:
public class AnnotationReader {
public static void main(String[] args) throws Exception {
Class<?> entityClass = Student.class;
// 클래스 레벨 어노테이션 조회
System.out.println("--- 클래스 어노테이션 ---");
for (var annotation : entityClass.getAnnotations()) {
System.out.println(annotation);
}
// 특정 어노테이션의 값 읽기
TableInfo tableInfo = entityClass.getAnnotation(TableInfo.class);
System.out.println("테이블 이름: " + tableInfo.tableName());
// 필드 레벨 어노테이션 분석
Field nameField = entityClass.getDeclaredField("name");
ColumnInfo colAnnotation = nameField.getAnnotation(ColumnInfo.class);
System.out.println("컬럼명: " + colAnnotation.columnName());
System.out.println("데이터 타입: " + colAnnotation.dataType());
System.out.println("길이: " + colAnnotation.maxLength());
}
}
// 어노테이션 정의 예시
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableInfo {
String tableName();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ColumnInfo {
String columnName();
String dataType();
int maxLength();
}
// 어노테이션이 적용된 엔티티 클래스
@TableInfo(tableName = "students")
class Student {
@ColumnInfo(columnName = "full_name", dataType = "varchar", maxLength = 8)
private String name;
@ColumnInfo(columnName = "student_age", dataType = "int", maxLength = 3)
private int age;
@ColumnInfo(columnName = "student_id", dataType = "int", maxLength = 10)
private int id;
public Student() {}
public Student(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
// getter/setter 메서드 생략
}