프록시 모드에서 $ProxyX.class 파일을 보는 방법

Proxy의 구현 원리를 학습할 때 $Proxy0.class의 코드를 확인해야 하는데 $Proxy0.class는 메모리에 있으므로 로컬에서 작성해야 합니다. 말도 안되는 방법은 다음과 같습니다.

동적 프록시를 호출하는 기본 메서드에서 다음을 추가합니다.

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");    
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);//这个不对

이와 같이 코드 실행 시 프로젝트의 루트 디렉토리에 com.sun.proxy.$ProxyX.class가 생성되며, 디컴파일을 통해 Proxy의 과정을 이해할 수 있다.

물론 도 가능하다.

Proxy.getProxyClass(真正用到的类.class.getClassLoader(), 真正用到的类.class)); 

바이트 코드를 가져와서 로컬로 작성합니다.

참고: 위의 매개변수는 부울 값이 아니라 문자열 "true"입니다. System.getProperties를 보면 분명히 이것이 시스템 속성이라고 생각할 것입니다. 궁금하지 않게 시스템 속성이 무엇인지 살펴보겠습니다.

public class Main {

    public static void main(String[] args) {
        Set set = System.getProperties().keySet();
        if (!set.isEmpty()) {
            Iterator iterator = set.iterator();
            Object key = null;
            while (iterator.hasNext()) {
                key = iterator.next();
                System.out.println(key + " : " + System.getProperties().get(key));
            }
        }
    }
}

인쇄된 결과는 다음과 같습니다.

java.runtime.name : Java(TM) SE Runtime Environment
sun.boot.library.path : D:\Program Files\Java8\jdk1.8.0.181\jre\bin
java.vm.version : 25.181-b13
java.vm.vendor : Oracle Corporation
。。。

결과가 너무 길어서 여기서는 일부만 가로챈다. 그러나 시스템 속성에 sun.misc.ProxyGenerator.saveGeneratedFiles가 없음을 알 수 있습니다. 그럼 이 속성은 어디에서 오는 걸까요? 소스가 없으면 마법의 값입니다. 앞으로 시스템이 변경되면 알 수 없습니다. Proxy 코드에서 이 값의 소스를 찾아보고 문자열이 true인 이유는 무엇입니까? 부울 대신 true .

Proxy의 유일한 항목이기도 한 Proxy를 사용할 때 다음 코드 줄을 사용해야 하므로 sun.misc.ProxyGenerator.saveGeneratedFiles도 이 클래스와 관련되어야 합니다.

Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
            .getClass().getInterfaces(), handler);

newProxyInstance에 대한 후속 조치를 취하고 반환 코드를 찾으십시오.

여기에 이미지 설명 삽입

반환값이 Constructor를 통해 인스턴스화되는 것을 볼 수 있는데, 리플렉션을 사용해 본 적이 있다면 이 클래스에 대해 잘 알고 있을 것입니다. 그런 다음 이 인스턴스의 유형은 c1의 유형이고 c1은 getProxyClass0을 통해 획득한 후 후속 작업을 계속합니다.

여기에 이미지 설명 삽입

코드를 통해 ProxyClassCache가 WeakCache 유형임을 알 수 있으므로 getProxyClass0의 반환 값은 ProxyClassCache에 있고 키-값 쌍을 통해 얻으므로 ProxyClassCache가 어떻게 구현되는지 살펴보겠습니다.

여기에 이미지 설명 삽입

따라서 반환 값은 ProxyClassFactory 유형이므로 후속 조치를 계속하십시오.

여기에 이미지 설명 삽입

ProxyClassFactory의 구조 다이어그램에서 볼 수 있듯이 이 팩토리 모드에서는 모든 인스턴스가 apply 메서드를 통해 반환됩니다.

여기에 이미지 설명 삽입

주석과 코드를 통해 ProxyGenerator.generateProxyClass를 통해 프록시 클래스가 생성되었음을 확인할 수 있습니다. 후속 작업을 계속합니다.

여기에 이미지 설명 삽입

여기서 파일의 소스코드를 설정하지 않았고, 클래스 파일을 통해 디컴파일 하였기 때문에 별도의 설명은 없지만, 변수명과 던져진 I/O 예외를 보면 이런 논리임을 짐작할 수 있다. 프록시 클래스 파일의 생성 여부를 제어하므로 saveGeneratedFiles가 정의된 방법을 살펴보겠습니다.

private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));

이것이 기사의 시작 부분에서 작성한 속성임을 알 수 있습니다. 이는 올바른 속성을 찾았음을 증명하고 계속해서 GetBooleanAction을 추적합니다.

public class GetBooleanAction implements PrivilegedAction<Boolean> {
    private String theProp;

    public GetBooleanAction(String var1) {
        this.theProp = var1;
    }

    public Boolean run() {
        return Boolean.getBoolean(this.theProp);
    }
}

이 클래스는 매우 간단합니다.그냥 PrivilegedAction 인터페이스를 구현합니다.PrivilegedAction에는 하나의 run 메서드와 많은 주석만 있습니다.우리는 대담한 추측을 할 수 있습니다.이 인터페이스를 구현하는 목적은 해당 값을 run 메서드와 함께 제공하는 것입니다. Boolean.getBoolean을 계속 추적합니다.

public static boolean getBoolean(String name) {
    boolean result = false;
    try {
        result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
}

parseBoolean의 매개변수는 문자열 유형이므로 기사 시작 부분에서 부울 유형이 아닌 이유를 설명합니다.

추천

출처blog.csdn.net/niuzhucedenglu/article/details/82970897