자바 jdk 동적 에이전트 상세 설명

jdk 동적 대 리 는 하나의 종 류 를 대리 해 야 합 니 다.대리 되 는 종 류 는 최소한 하나의 인 터 페 이 스 를 실현 해 야 하고 인터페이스 에 있 는 방법 만 대리 할 수 있 습 니 다.
jdk 구현 동적 대 리 는 일반적으로 세 단계 로 나 뉜 다.
1.인터페이스 와 구현 클래스 를 작성 합 니 다.
2.프로 세 서 를 작성 합 니 다.이 프로 세 서 는 Invocation Handler 인 터 페 이 스 를 실현 합 니 다.이 인 터 페 이 스 는 하나의 방법 만 있 습 니 다.Public Object invoke(Object proxy,Method method,Object[]args)throws Throwable 로 서명 합 니 다.이 프로세서 의 실현 방법 에 서 는 방법 호출 전과 호출 후 자신의 코드 를 추가 하여 동적 차단 을 할 수 있 습 니 다.주의해 야 할 것 은 proxy 가 생 성 하기 위 한 동적 프 록 시 클래스 입 니 다.실제 프 록 시 클래스 가 아 닙 니 다.따라서 프로세서 에 Object 형식의 구성원 변 수 를 추가 할 수 있 습 니 다.프 록 시 클래스(즉,첫 번 째 단계 의 실현 클래스)를 가리 키 고 있 습 니 다.
3.java.lang.reflect.Proxy 류 의 newProxyInstance 방법 으로 동적 프 록 시 클래스 를 생 성 합 니 다.모든 프 록 시 방법 에 대한 호출 은 생 성 된 동적 프 록 시 클래스 를 직접 호출 하 는 방법 이면 되 지만,먼저 그것 에 대해 강제 형식 변환 을 하여 우리 가 호출 할 방법의 인터페이스 로 전환 해 야 합 니 다.
JDK 원리 분석:Proxy 의 소스 코드 를 분석 하면 동적 에이전트 류 의 상세 한 생 성 을 볼 수 있 습 니 다.new Proxy Instance 방법 은 먼저 동적 프 록 시 클래스 의 Class 인 스 턴 스 를 생 성 한 다음 에 그 매개 변수 유형 을 Invocation Handler 의 구조 함수 로 호출 하여 동적 프 록 시 클래스 를 생 성하 고 되 돌려 줍 니 다.동적 프 록 시 클래스 의 Class 인 스 턴 스 는 어떻게 생 성 되 었 습 니까?ProxyGenerator 클래스 를 통 해 동적 프 록 시 클래스 의 class 바이트 흐름 을 생 성하 여 방법 영역 에 불 러 옵 니 다.클 라 스 바이트 흐름 생 성 을 분석 하 는 과정 에서 프 록 시 를 부모 클래스 로 사용 하여 모든 프 록 시 인 터 페 이 스 를 실현 하 는 방법 을 볼 수 있 습 니 다.모든 방법의 실현 체 에 서 는 프로세서 의 invoke 방법 을 호출 합 니 다.
class 바이트 흐름 의 생 성 과정의 주요 코드 는 다음 과 같 습 니 다.
 
  
private byte[] generateClassFile()
    {
        addProxyMethod(hashCodeMethod, java/lang/Object);
        addProxyMethod(equalsMethod, java/lang/Object);
        addProxyMethod(toStringMethod, java/lang/Object);
        for(int i = 0; i < interfaces.length; i++)
        {
            Method amethod[] = interfaces[i].getMethods();
            for(int k = 0; k < amethod.length; k++)
                addProxyMethod(amethod[k], interfaces[i]);

        }

        List list;
        for(Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list))
            list = (List)iterator.next();

        try
        {
            methods.add(generateConstructor());
            for(Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();)
            {
                List list1 = (List)iterator1.next();
                Iterator iterator2 = list1.iterator();
                while(iterator2.hasNext())
                {
                    ProxyMethod proxymethod = (ProxyMethod)iterator2.next();
                    fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                    methods.add(proxymethod.generateMethod());       

 
  
        } 
    } 

    methods.add(generateStaticInitializer()); 

catch(IOException ioexception) 

    throw new InternalError("unexpected I/O Exception"); 

if(methods.size() > 65535) 
    throw new IllegalArgumentException("method limit exceeded"); 
if(fields.size() > 65535) 
    throw new IllegalArgumentException("field limit exceeded"); 
cp.getClass(dotToSlash(className)); 
cp.getClass("java/lang/reflect/Proxy"); 
for(int j = 0; j < interfaces.length; j++) 
    cp.getClass(dotToSlash(interfaces[j].getName())); 

cp.setReadOnly(); 
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); 
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); 
try 

    dataoutputstream.writeInt(-889275714); 
    dataoutputstream.writeShort(0); 
    dataoutputstream.writeShort(49); 
    cp.write(dataoutputstream); 
    dataoutputstream.writeShort(49); 
    dataoutputstream.writeShort(cp.getClass(dotToSlash(className))); 
    dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy")); 
    dataoutputstream.writeShort(interfaces.length); 
    for(int l = 0; l < interfaces.length; l++) 
        dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName()))); 

    dataoutputstream.writeShort(fields.size()); 
    FieldInfo fieldinfo; 
 
  
//
for(Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream))

fieldinfo = (FieldInfo)iterator3.next();
            //
            dataoutputstream.writeShort(methods.size());
            MethodInfo methodinfo;
            for(Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream))
                methodinfo = (MethodInfo)iterator4.next();

            dataoutputstream.writeShort(0);
        }
        catch(IOException ioexception1)
        {
            throw new InternalError("unexpected I/O Exception");
        }
        return bytearrayoutputstream.toByteArray();
    }


주:코드 에 빨 간 부분 추가
proxymethod.generateMethod()는 모든 방법 으로 방법 체 를 생 성 합 니 다.원본 코드 를 보면 Invocation Handler 인 터 페 이 스 를 호출 하 는 프로세서 의 invoke 방법 임 을 알 수 있 습 니 다.

좋은 웹페이지 즐겨찾기