티스토리 뷰

Spring

[Spring] 리플렉션(Reflection)

hyuuny 2022. 5. 15. 19:39

리플렉션

리플렉션은 클래스나 메서드의 메타정보를 동적으로 획득하고, 코드도 동적으로 호출할 수 있도록 하는 API이다.


리플렉션 적용 전

@Slf4j
public class ReflectionTest {

  @Test
  void reflection0() {
    Hello target = new Hello();

    // 공통 로직1 시작
    log.info("start");
    String result1 = target.callA(); // 호출하는 메서드가 다름, 동적 처리 필요
    log.info("result={}", result1);
    // 공통 로직1 종료

    // 공통 로직2 시작
    log.info("start");
    String result2 = target.callB(); // 호출하는 메서드가 다름, 동적 처리 필요
    log.info("result={}", result2);
    // 공통 로직2 종료
  }

    @Slf4j
  static class Hello {

    public String callA() {
      log.info("callA");
      return "A";
    }

    public String callB() {
      log.info("callB");
      return "B";
    }
  }

}

위와 같이 공통 로직1과 공통 로직2는 호출하는 메서드만 다르고 전체 코드 흐름은 동일하다.
공통되는 메서드를 뽑아내어 하나의 메서드로 합치는 것은 상당히 어려운 일이다.


리플렉션은 클래스나 메서드의 메타정보를 사용해서 호출하는 메서드를 동적으로 변경할 수 있다고 한다. 한번 적용해보자!


리플렉션 적용

  @Test
  void reflection2() throws Exception {
    // 클래스 정보
    Class classHello = Class.forName("com.hyuuny.advanced.blog.jdkdynamic.ReflectionTest$Hello");

    Hello target = new Hello();

    // callA 메서드 정보
    Method methodCallA = classHello.getMethod("callA");
    dynamicCall(methodCallA, target);

    // callB 메서드 정보
    Method methodCallB = classHello.getMethod("callB");
    dynamicCall(methodCallB, target);
  }

  // 동적으로 변동되는 method를 파라미터로 받아 호출
  private void dynamicCall(Method method, Object target) throws Exception {
    log.info("start");
    Object result = method.invoke(target);
    log.info("result={}", result);
  }
}
  • Class.forName() : 클래스 메타정보를 획득한다.
  • classHello.getMethod() : 해당 클래스의 메서드 메타정보를 획득한다.
  • methodCallA.invoke() : 획득한 메서드 메타정보로 실제 인스턴스의 메서드를 호출한다


기존의 target.callA(), target.callB()메서드를 직접 호출하는 부분이 getMethod()로 대체되었다.
getMethod()를 사용해서 Method라는 메타 정보로 추상화하였기 때문에 공통 로직을 만들 수 있게 되었다.


주의사항

리플렉션을 사용하면 클래스와 메서드의 메타정보를 사용해서 애플리케이션을 동적으로 유연하게 만들 수 있다. 허나, 리플렉션 기술은 런타임에 동작하기 때문에, 컴파일 시점에 오류를 잡을 수 없다.


위의 예제에서 getMethod("callA")로 작성해야 하지만, 실수로 getMethod("callAAAAA")라고 작성되었고, 컴파일 오류가 발생하지 않았기 때문에 사용자가 사용중에 해당 메서드를 호출하면 런타임 오류가 발생하게 된다.


가장 좋은 오류는 컴파일 오류이고, 가장 무서운 오류는 런타임 오류다.



Reference
김영한. 스프링 핵심 원리 - 고급편. 인프런.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8#

'Spring' 카테고리의 다른 글

[Spring] 포인트컷(Pointcut)  (0) 2022.05.19
[Spring] Advice 만들어보기  (0) 2022.05.17
[Spring] ThreadLocal을 사용해보자!  (0) 2022.05.07
[Spring] 트랜잭션 AICD  (0) 2022.04.20
[Spring] JDBC(Java Database Connectivity)  (0) 2022.04.17
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함