자바 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 방법 임 을 알 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.