[우아한테크코스] 9월 8일 TIL
[Java] Reflection
객체를 통해 클래스의 정보를 가지고 오는 프로그램 기법으로 Spring에서 Bean Factory가 사용한다.
Bean Factory는 객체가 호출될 때 객체의 인스턴스를 생성한다.
이렇게 동적으로 컴파일한 클래스의 정보를 분석해 인스턴스를 생성해 다룰 수 있도록 하는 것이 Reflection이다.
-
클래스를 바탕으로 Class 객체 찾기
// 같은 패키지 내에 Question 클래스 있는 경우 데려옴 final Class<Question> clazz = Question.class;
-
클래스의 이름을 통해 Class 객체 찾기
// 같은 패키지 내에 reflection 패키지 안에 Question 클래스 있는 경우 데려옴 final Class<?> clazz = Class.forName("reflection.Question");
-
객체로부터 선언된 필드/함수/생성자 찾기
// Student 객체를 찾아 선언된 필드를 데려옴 final Object student = new Student(); // getDeclaredFields 하면 선언된 모든 fields 데려옴 final Field[] fields = student.getClass().getDeclaredFields(); // getFields 하면 publicFields 데려옴 final Field[] fields = student.getClass().getFields(); // field 이름 전달하면 해당 필드 가져와 타입 얻기, 값 얻기 가능 final Field field = questionClass.getDeclaredField("questionId"); final List<String> actualFieldNames = Arrays.stream(fields) .map(Field::getName) .collect(Collectors.toList()); // Student 객체를 찾아 선언된 함수를 가져옴 // Object로 만들어 getClass().getDeclaredMethods도 가능 final Class<?> animalClass = Student.class; final Method[] methods = animalClass.getDeclaredMethods(); final List<String> actualMethods = Arrays.stream(methods) .map(Method::getName) .collect(Collectors.toList()); // 객체를 찾아 생성자들 가져옴 final Constructor<?>[] constructors = questionClass.getConstructors();
-
여러 생성자를 가진 객체 가져와서 새로운 인스턴스 만들어 생성
final Class<?> questionClass = Question.class; final Constructor<?> firstConstructor = questionClass.getConstructors()[0]; final Constructor<?> secondConstructor = questionClass.getConstructors()[1]; final Question firstQuestion = (Question) firstConstructor.newInstance("gugu", "제목1", "내용1"); final Question secondQuestion = (Question) secondConstructor.newInstance(1, "gugu", "제목2", "내용2", Date.valueOf(LocalDate.now()), 0);
-
객체를 찾아서 하나 만들고 필드 세팅하기
final Class<?> studentClass = Student.class; final Student student = (Student) studentClass.getConstructor().newInstance(); final Field field = student.getClass().getDeclaredField("age"); field.setAccessible(true); field.set(student, 99);
-
함수 찾아 실행하기
Class<Junit3Test> clazz = Junit3Test.class; Junit3Test junit3Test = clazz.getConstructor().newInstance(); Method[] methods = clazz.getMethods(); for (Method method : methods) { if (method.getName().startsWith("test")) { //test로 시작하는 함수를 찾아 method.invoke(junit3Test); // 실행한다, 클래스를 변수로 전달해야함 } }
-
메서드에서 어노테이션 찾아서 특정 어노테이션 가진 것만 실행
Method[] methods = clazz.getMethods(); for (Method method : methods) { Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { if (annotation.annotationType() == MyTest.class) { method.invoke(junit4Test); } } }
-
입력받은 변수의 패키지를 바탕으로 Controller 어노테이션 가진 클래스들 찾기
Reflections reflections = new Reflections("examples"); Set<Class<?>> controllers = reflections.getTypesAnnotatedWith(Controller.class);