자바에서 Reflection 과 Proxy

kmb·2023년 5월 18일
0

자바

목록 보기
30/31
post-thumbnail

리플렉션(Reflection)

실행중인 자바 프로그램내에서 클래스, 인터페이스, 메서드, 필드의 정보를 동적으로 검사하고 접근할 수 있는 기능.

주로 런타임시 동적으로 클래스를 로드하고 메서드를 호출하는 작업에 사용.

자바에서 Reflection을 활용하려면 java.lang.reflect 패키지에 있는 클래스를 사용해야한다.
예를들어 Class 클래스는 클래스의 메타데이터를 의미하고 Method 클래스는 메소드의 메타데이터를 의미한다.

 

  • Reflection 예시
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) {
        // 클래스 정보 가져오기
        Class<?> myClass = MyClass.class;

        // 클래스 이름 출력
        System.out.println("Class Name : " + myClass.getName());

        // 클래스의 메소드 정보 출력
        Method[] methods = myClass.getMethods();
        System.out.println("Methods :");
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        // 클래스의 필드 정보 출력
        Field[] fields = myClass.getDeclaredFields();
        System.out.println("Fields :");
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }
}

class MyClass {
    private int myField;
    public void myMethod() {
        System.out.println("Hello, Reflection!");
    }
}


// 결과
Class Name : MyClass

Methods :
myMethod
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

Fields :
myField

프록시(Proxy)

대리자 또는 대리객체로서 다른 객체에 대한 접근을 제어하는 기능.
실제 객체에 대한 호출을 가로채고 필요한 작업을 수행한 다음 결과를 반환하거나 호출을 전달.
이를 통해 객체의 동작변경, 접근제어, 로깅, 캐싱이 가능하다.

자바에서 프록시를 활용하려면 java.lang.reflect 패키지에 있는 Proxy 클래스와 InvocationHandler 인터페이스를 사용해야한다.

Proxy 클래스는 동적으로 프록시 객체를 생성하는 데 사용.
InvocationHandler 인터페이스는 프록시 객체에서 호출을 처리하는 메서드를 정의.

 

  • Proxy 예시
interface Image {
    void display();
}

class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image from disk : " + filename);
    }

    public void display() {
        System.out.println("Displaying image : " + filename);
    }
}

class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;

    public ImageProxy(String filename) {
        this.filename = filename;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

public class ProxyExample {
    public static void main(String[] args) {
        Image image = new ImageProxy("image.jpg");

        // 첫 번째 호출은 실제 이미지를 로딩하고 출력합니다.
        image.display();

        // 두 번째 호출부터는 이미지가 캐싱되어 바로 출력됩니다.
        image.display();
    }
}


// 결과
Loading image from disk : test_image.jpg

Displaying image : test_image.jpg

Displaying image : test_image.jpg

ImageProxy 클래스의 display() 메서드가 처음 호출되면
RealImage 객체를 생성하고 출력하며, 이후 호출부터는 Image가 캐싱되어 바로 출력된다.

profile
꾸준하게

0개의 댓글