포스트

10. reflection

10. reflection

Reflection(23. 11. 30)

reflection을 이용한 객체 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
    try {
        Class userClass = Class.forName(User.class.getName());
        Constructor<?> constructor = userClass.getConstructor();
        User user = (User) constructor.newInstance();
        System.out.println(user);
    } catch (ClassNotFoundException | NoSuchMethodException e){
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}
  • Class.forName(className)
    • 물리적인 클래스 파일명을 인자로 넘겨주면 이에 해당하는 클래스를 반환합니다.
  • Class.getConstructor()
    • public 접근자를 가진 생성자를 반환합니다.
    • Class.forName(User.class.getName()).getConstructor(String.class ,Integer.TYPE); 이런식으로 타입을 지정 할 수 도있다.
  • getDeclaredMethod
    • method를 복사하는 기능
    • getter 를 복하
    • ``Method setUserNameMethod =clazz.getDeclaredMethod(“setUserName”,String.class);`
    • private 도 접근이 가능할까? → userAgeField.setAccessible(true); 로 가능!

의존성 주입

  • 의존성 주입을 위한 @Autowired annotation 를 이용한다.
  • UserRepository.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      public class UserRepository {
          private List<User> users = new ArrayList<>();
          public User findByName(String userName){
          	return users.stream()
              	.filter(o->o.getUserName().equals(userName)).findFirst().orElse(null);
          }
        
          public void save(User user){
         		this.users.add(user);
          }
      }
    
  • UserService.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      public class UserService {
        
       @Autowired
       private UserRepository userRepository;
        
       public User getUser(String userName){
       	return userRepository.findByName(userName);
       }
       public void addUser(User user){
      	 userRepository.save(user);
       }
    
  • InjectUtil

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
      public final class InjectUtil {
        
          public static <T> T getObject(Class<T> classType){
              T instance = createInstance(classType);
              Field[] fields = classType.getDeclaredFields();
          for(Field field : fields){
              if (field.getAnnotation(Autowired.class) != null) {
                  Object fieldInstance = createInstance(field.getType());
                  field.setAccessible(true);
                  try {
                      field.set(instance, fieldInstance);
                  } catch (IllegalAccessException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
          return instance;
      }
        
      private static <T> T createInstance(Class<T> classType) {
          try {
              return classType.getConstructor(null).newInstance();
          } catch (InstantiationException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          } catch (InvocationTargetException e) {
              e.printStackTrace();
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          }
          return null;
      }
    
    • UserServiceUserRepository 를 자동으로 주입해주는 class
    • UserService 의 Reflection API를 이용해 모든 Fields를 조회 Field[] 배열로 반환
    • 배열 순회하면서 @Autosired annotaion 이 있는 field를 조회 createInstance() 를 통해 객체 생성
    • 객체의 생성을 프로그램에 의해서 컨트롤 → InjectUtil이 객체 의존성을 제어한다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.