리플렉션(Reflection)

종원유·2022년 3월 15일
0

Java

목록 보기
11/11

리플렉션(Reflection)

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

리플렉션 적용 전 코드

@Slf4j
public class ReflectionTest {
    @Test
    public void reflection0(){
        Hello target = new Hello();

        //공통 로직1 시작
        log.info("start");
        String result1 = target.callA();
        log.info("result={}", result1);
        //공통 로직2 시작
        String result2 = target.callB();
        log.info("result={}", result2);
    }
    
    @Slf4j
    static class Hello{
        public String callA(){
            log.info("call A");
            return "A";
        }
        public String callB(){
            log.info("call B");
            return "B";
        }
    }
}
  • 공통 로직
        //공통 로직1 시작
        log.info("start");
        String result1 = target.callA();
        log.info("result={}", result1);
        //공통 로직2 시작
        String result2 = target.callB();
        log.info("result={}", result2);

리플렉션 적용

@Slf4j
public class ReflectionTest {
  @Test
    void reflection1() throws Exception {
        //클래스 정보, 내부 클래스는 구분을 위해 $를 사용한다.
        Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");

        Hello target = new Hello();
        //callA 메서드 정보
        Method methodCallA = classHello.getMethod("callA");//callA의 메서드 정보(메타 정보)
        Object result1 = methodCallA.invoke(target);//target(인스턴스)의 methodCallA(메타정보)를 실행해라
        log.info("result1={}", result1);

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

    }
    
    @Slf4j
    static class Hello{
        public String callA(){
            log.info("call A");
            return "A";
        }
        public String callB(){
            log.info("call B");
            return "B";
        }
    }
}
Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello")

클래스 정보를 가져온다. 내부 클래스는 구분을 위해 $를 사용한다.

Method methodCallA = classHello.getMethod("callA");

callA의 메타 정보(메서드)를 가져온다.

Object result1 = methodCallA.invoke(target);

메타 정보(메서드)를 가지고 target이라는 인스턴스를 파라미터로 전달해서 인스턴스의 메타 정보(메서드)를 실행한다.

공통 로직 적용

@Slf4j
public class ReflectionTest {
    @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);

    }
    
    //Method 메타정보를 통해서 공통 로직을 작성할 수있다.
    private void dynamicCall(Method method, Object target) throws Exception{
        log.info("start");
        Object result = method.invoke(target);
        log.info("result={}", result);
        log.info("end");
    }
    
    @Slf4j
    static class Hello{
        public String callA(){
            log.info("call A");
            return "A";
        }
        public String callB(){
            log.info("call B");
            return "B";
        }
    }
}
private void dynamicCall(Method method, Object target) throws Exception

메타 정보와 target을 동적으로 전달받아서 동적으로 코드를 실행할 수 있다.

주의할 점

  • 리플렉션은 가급적 사용하지 않는 것이 좋다.
    런타임에 동작하기 때문에 컴파일 시점에 오류를 잡을 수가 없기 때문이다.(해당 코드를 실행할 경우 오류가 발생, 런타임 에러).
    프로그래밍 언어가 발달하면서 타입 정보를 기반으로 컴파일 시점에 오류를 잡을 수 있어 편하게 개발할 수 있는데, 리플렉션은 이를 역행하는 방식이다.

리플렉션은 프레임워크 개발이나 또는 매우 일반적인 공통 처리가 필요할 때 부분적으로 주의하여 사용하여야 한다.

profile
개발자 호소인

0개의 댓글