Springboot

java리플렉션

25G 2023. 8. 14. 18:07

리플랙션

리플렉션이라는 말의 사전적의미는 투영 같은 느낌의 단어입니다.
이 리플렉션을 통해서 어떠한 요청이 온 파라미터값이나 클래스나 객체에있는 정보들을 쏙쏙 빼갈수 있습니다.
자바가 기본으로 제공하는 JDK동적 프록시 기술이나 CGLIB같은 프록시 생성 오픈소스 기술을활용하면
프록시 객체를 동적으로 만들어 낼 수 있다.
리플랙션 기술을 사용하면 클래스나 메서드의 메타정보를 동적으로 획등하고 코드도 동적으로 호출 할 수 있다.
정적인 코드를 리플랙션을 사용해서 Method라는 메타정보로 추상화한후 공통로직을 만들 수 있게 된다.

package hello.proxy.jdkdynamic;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
public class ReflectionTest {

    @Test
    void reflection0() throws NoSuchMethodException, ClassNotFoundException {
        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);
        // 공통로직 1과 2는 내용 이 같지만 호출내용이 다르기때문에 메서드로 뽑아내거나 하기가 쉽지 않다
        // 이럴땐 리플랙션을 사용하면 해결할 수 있다.

    }
    @Test
    void reflection() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //클래스 정보 가져오기
        Class classHello =  Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");

        Hello target = new Hello();
        // callA 메서드정보
        Method methodCallA = classHello.getMethod("callA");
        Object result1 =methodCallA.invoke(target);
        log.info("result1={}",result1);

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

    }

    @Test
    void reflection2() throws Exception{

        Class classHello =  Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");

        Hello target = new Hello();
        // callA 메서드정보
        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 result1 =method.invoke(target);
        log.info("result={}",result1);
    }

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

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

주의

리플렉션을 사용하면 클래스와 메서드의 메타정보를 사용해서 애플리케이션을 동적으로 유연하게 만들수 있다 하지만
리플렉션 기술은 런타임에 동작하기 때문에 컴파일시에 오류를 잡을 수 없다.
리플랙션은 프레임워크 개발이나 또는 매우 일반적인 공통처리가 필요할때 부분적으로 주의해서 사용한다.

'Springboot' 카테고리의 다른 글

프록시 팩토리  (0) 2023.08.14
JDK동적프록시/CGLIB  (0) 2023.08.14
탬플릿 메서드 패턴  (0) 2023.08.14
Springboot/ ThreadLocal  (0) 2023.08.14
Spring Data ElasticSearch NativeSearchQuery Paging 처리  (0) 2022.12.07