리플렉션

박찬우·2024년 2월 15일
0

스프링

목록 보기
44/88

리플렉션

  • 리플렉션 기술을 사용하면 클래스나 메서드의 메타정보를 동적으로 획득하고, 코드도 동적으로 호출할 수 있다.
  • 런타임에 동작하기 때문에, 컴파일 시점에 오류를 잡을 수 없다
  • 매우 중요한 공통작업이 필요한 경우에만 사용

예)

  • 정적인 target.callA() , target.callB() 코드를 리플렉션을 사용해서 Method 라는 메타정보로 추상화했다. 덕분에 공통 로직을 만들 수 있게 되었다.
@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 종료
    }

	// 메타정보 이용
    @Test
    void reflection1() throws Exception {
        Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");

        Hello target = new Hello();

        Method methodCallA = classHello.getMethod("callA");
        Object result1 = methodCallA.invoke(target);
        log.info("result1={}", result1);

        Method methodCallB = classHello.getMethod("callB");
        Object result2 = methodCallB.invoke(target);
        log.info("result1={}", result1);
    }

	// 메타정보를 이용하여 공통 로직을 개발함
    @Test
    void reflection2() throws Exception {
        Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");

        Hello target = new Hello();

        Method methodCallA = classHello.getMethod("callA");
        dynamicCall(methodCallA, target);

        Method methodCallB = classHello.getMethod("callB");
        dynamicCall(methodCallB, target);
    }

    private void dynamicCall(Method method, Object target) throws Exception {
        log.info("start");
        Object result = method.invoke(target);
        log.info("result={}", result);
    }

    @Slf4j
    static class Hello {
        public String callA() {
            log.info("callA");
            return "A";
        }

        public String callB() {
            log.info("callB");
            return "B";
        }
    }
}
  • Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello") : 클래스 메타정보를 획득한다. 참고로 내부 클래스는 구분을 위해 $ 를 사용한다.
  • classHello.getMethod("call") : 해당 클래스의 call 메서드 메타정보를 획득한다.
  • methodCallA.invoke(target) : 획득한 메서드 메타정보로 실제 인스턴스의 메서드를 호출한다. 여기서 methodCallA 는 Hello 클래스의 callA() 이라는 메서드 메타정보이다. methodCallA.invoke(인스턴
    스) 를 호출하면서 인스턴스를 넘겨주면 해당 인스턴스의 callA() 메서드를 찾아서 실행한다. 여기서는 target 의 callA() 메서드를 호출한다.
profile
진짜 개발자가 되어보자

0개의 댓글