자바 에이전트 모델 및 동적 에이전트 메커니즘 깊이 분석

자바 에이전트 모델 및 동적 에이전트 메커니즘 깊이 분석
프 록 시 디자인 모드
       에이 전 트 는 자주 사용 하 는 디자인 모델 로 다른 대상 에 게 에이 전 트 를 제공 하여 특정한 대상 에 대한 접근 을 제어 하 는 것 이 목적 이다.대리 류 는 위탁 류 의 예비 처리 메 시 지 를 여과 하고 메 시 지 를 전달 하 며 메시지 가 위탁 류 에 의 해 실 행 된 후의 후속 처 리 를 책임 집 니 다.
프 록 시 모드 의 역할 은 다른 대상 에 게 이 대상 에 대한 접근 을 제어 하기 위해 프 록 시 를 제공 하 는 것 입 니 다.어떤 경우 에 한 고객 이 다른 대상 을 직접 인용 하고 싶 지 않 거나 인용 할 수 없 으 며 대리 대상 은 클 라 이언 트 와 목표 대상 사이 에서 중개 역할 을 할 수 있다.
프 록 시 모드 에서 일반적으로 언급 되 는 역할 은 다음 과 같다.
추상 적 인 역할:실제 대상 과 대리 대상 의 공동 인 터 페 이 스 를 설명 합 니 다.
대리 역할:대리 대상 역할 내부 에 실제 대상 에 대한 인용 이 포함 되 어 있어 실제 대상 을 조작 할 수 있 고 대리 대상 은 실제 대상 과 같은 인 터 페 이 스 를 제공 합 니 다.
언제나 진실 한 대상 을 대체 할 수 있다.또한 대리 대상 은 실제 대상 조작 을 수행 할 때 다른 조작 을 추가 할 수 있어 실제 대상 을 봉인 하 는 것 과 같다.
실제 역할:대리 역할 이 대표 하 는 진실 한 대상 은 우리 가 최종 적 으로 인용 해 야 할 대상 이다.
그림 1.프 록 시 모드 도표

행위 의 일치 성 을 유지 하기 위해 대리 류 와 의뢰 류 는 보통 같은 인 터 페 이 스 를 실현 하기 때문에 방문 자 들 이 보기에 두 가 지 는 조금도 차이 가 없다.대리 류 와 같은 중간 층 을 통 해 의뢰 류 대상 에 대한 직접적인 방문 을 효과적으로 통제 할 수 있 고 의뢰 류 대상 을 잘 숨 기 고 보호 할 수 있 으 며 서로 다른 통제 전략 을 실시 하기 위해 공간 을 미리 남 겨 디자인 에 있어 더욱 큰 유연성 을 얻 었 다.자바 동적 대리 체 제 는 교묘 한 방식 으로 대리 모델 의 디자인 이념 을 완벽 하 게 실천 했다.
자바 동적 에이전트
관련 클래스 와 인터페이스
자바 동적 에이전트 의 메커니즘 을 이해 하려 면 먼저 다음 과 같은 클래스 나 인 터 페 이 스 를 알 아야 합 니 다.
・java.lang.reflect.Proxy:이것 은 자바 동적 에이전트 의 주 클래스 입 니 다.인터페이스 에 프 록 시 클래스 와 대상 을 동적 으로 생 성 하 는 정적 방법 을 제공 합 니 다.
목록 1.Proxy 의 정적 방법 

//    1:                        
 
static InvocationHandler getInvocationHandler(Object proxy)  
 
//    2:                                
 
static Class getProxyClass(ClassLoader loader, Class[] interfaces)  
 
//    3:                       
 
static boolean isProxyClass(Class cl)  
 
//    4:            、                    
 
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,  
 
  InvocationHandler h)  
java.lang.reflect.InvocationHandler:프로세서 인 터 페 이 스 를 호출 합 니 다.동적 에이전트 대상 에 집중 적 으로 처리 하 는 방법 으로 invoke 방법 을 사용자 정의 합 니 다.보통 이 방법 에서 의뢰 류 에 대한 프 록 시 접근 을 실현 합 니 다.
목록 2.Invocation Handler 의 핵심 방법

//                       。            ,               
 
//           。                                
 
Object invoke(Object proxy, Method method, Object[] args)  
동적 프 록 시 클래스 대상 을 만 들 때마다 이 인 터 페 이 스 를 실현 하 는 호출 프로세서 대상 을 지정 해 야 합 니 다(프 록 시 정적 방법 4 의 세 번 째 매개 변 수 를 참조).
・java.lang.ClassLoader:클래스 로 더 클래스 입 니 다.클래스 의 바이트 코드 를 자바 가상 머 신(JVM)에 불 러 오고 클래스 대상 을 정의 해 야 사용 할 수 있 습 니 다.Proxy 정적 방법 으로 동적 프 록 시 클래스 를 생 성 하 는 것 도 클래스 로 더 를 통 해 불 러 와 야 사용 할 수 있 습 니 다.일반 클래스 와 의 유일한 차이 점 은 바이트 코드 가 JVM 이 실 행 될 때 동적 으로 생 성 되 는 것 이지 미리 저장 하 는 것 이 아 닙 니 다.class 파일 에 있 습 니 다.
동적 프 록 시 클래스 대상 을 생 성 할 때마다 클래스 로 더 대상 을 지정 해 야 합 니 다(프 록 시 정적 방법 4 의 첫 번 째 인자 참조)
대리 메커니즘 및 그 특징
우선 자바 동적 대 리 를 어떻게 사용 하 는 지 알 아 보 겠 습 니 다.구체 적 으로 다음 과 같은 네 가지 절차 가 있다.
1.InvocationHandler 인 터 페 이 스 를 통 해 호출 프로 세 서 를 만 듭 니 다.
2.프 록 시 클래스 에 ClassLoader 대상 과 interface 를 지정 하여 동적 프 록 시 클래스 를 만 듭 니 다.
3.반사 체 제 를 통 해 동적 에이전트 류 의 구조 함 수 를 얻 을 수 있 습 니 다.유일한 매개 변수 유형 은 프로세서 인터페이스 유형 을 호출 하 는 것 입 니 다.
4.구조 함 수 를 통 해 동적 프 록 시 클래스 인 스 턴 스 를 만 들 고 구조 시 프로세서 대상 을 매개 변수 로 호출 합 니 다.
목록 3.동적 에이전트 생 성 과정

// InvocationHandlerImpl     InvocationHandler   ,                      
 
//                  ,                  
 
InvocationHandler handler = new InvocationHandlerImpl(..);  
 
 
//    Proxy     Interface                      
 
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });  
 
 
//                     
 
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });  
 
 
//                   
 
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });  
실제 사용 과정 은 더욱 간단 합 니 다.Proxy 의 정적 방법 인 new Proxy Instance 는 2 단계 에서 4 단계 까지 의 과정 을 패키지 해 주 었 기 때문에 간단 한 과정 은 다음 과 같 습 니 다.
목록 4.동적 에이전트 생 성 과정 간소화

// InvocationHandlerImpl     InvocationHandler   ,                      
 
InvocationHandler handler = new InvocationHandlerImpl(..);  
 
//    Proxy             
 
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,  
 
 new Class[] { Interface.class },  
 
 handler );  
다음은 동적 대 리 를 간단하게 실현 하 는 예 를 살 펴 보 겠 습 니 다.
1.프 록 시 클래스 와 실제 클래스 인터페이스:

public interface Subject 
 
{ 
 
public void request(); 
 
} 
2.진실 클래스:

public class RealSubject implements Subject 
 
{ 
 
public void request() 
 
{ 
 
System.out.println("From real subject!"); 
 
}} 
3.구체 적 인 대리 클래스:

import java.lang.reflect.InvocationHandler; 
 
import java.lang.reflect.Method; 
 
public class DynamicSubject implements InvocationHandler 
 
{ 
 
private Object sub; 
 
public DynamicSubject(Object obj) 
 
{ 
 
this.sub = obj; 
 
} 
 
public Object invoke(Object proxy, Method method, Object[] args) 
 
throws Throwable 
 
{ 
 
System.out.println("before calling: " + method); 
 
method.invoke(sub, args);  
 
System.out.println(args == null);  
 
System.out.println("after calling: " + method); 
 
return null; 
 
} 
주:이 프 록 시 클래스 의 내부 속성 은 Object 형식 으로 실제 사용 할 때 이 유형의 구조 방법 을 통 해 대상 에 게 전 달 됩 니 다.그 밖 에 이 종 류 는 invoke 방법 도 실현 했다.이 방법 중의 method.invoke 는 피 대리 대상 을 호출 하여 실행 할 방법 이다.방법 매개 변 수 는 sub 로 이 방법 은 sub 에 속 하고 동적 대리 류 를 통 해 우 리 는 실제 대상 을 실행 하 는 방법 전후 에 자신의 추가 방법 을 추가 할 수 있다 는 것 을 나타 낸다.
4.클 라 이언 트 호출 예시:

import java.lang.reflect.InvocationHandler; 
 
import java.lang.reflect.Proxy; 
 
public class Client 
 
{ 
 
public static void main(String[] args) 
 
{ 
 
RealSubject realSubject = new RealSubject(); 
 
InvocationHandler handler = new DynamicSubject(realSubject); 
 
Class<?> classType = handler.getClass(); 
 
//              
 
Subject subject = (Subject) Proxy.newProxyInstance(classType 
 
.getClassLoader(), realSubject.getClass().getInterfaces(), 
 
handler); 
 
subject.request(); 
 
System.out.println(subject.getClass()); 
 
} 
 
} 
다음은 자바 동적 에이전트 프 록 시의 구조 방법 을 알 아 보 겠 습 니 다.
목록 6.프 록 시 구성 방법

//    Proxy             ,   private             
 
private Proxy() {}  
 
 
//    Proxy             ,   protected             
 
protected Proxy(InvocationHandler h) {this.h = h;}  
이 어 new Proxy Instance 방법 을 빠르게 찾 아 볼 수 있 습 니 다.아주 간단 하기 때 문 입 니 다.
목록 7.프 록 시 정적 방법 newProxyInstance

public static Object newProxyInstance(ClassLoader loader,  
 
      Class<?>[] interfaces,  
 
      InvocationHandler h)  
 
      throws IllegalArgumentException {  
 
   
 
  //    h    ,      
 
  if (h == null) {  
 
    throw new NullPointerException();  
 
  }  
 
  //                          
 
  Class cl = getProxyClass(loader, interfaces);  
 
 
  //                      
 
  try {  
 
    Constructor cons = cl.getConstructor(constructorParams);  
 
    return (Object) cons.newInstance(new Object[] { h });  
 
  } catch (NoSuchMethodException e) { throw new InternalError(e.toString());  
 
  } catch (IllegalAccessException e) { throw new InternalError(e.toString());  
 
  } catch (InstantiationException e) { throw new InternalError(e.toString());  
 
  } catch (InvocationTargetException e) { throw new InternalError(e.toString());  
 
  }  
} 
     이 를 통 해 알 수 있 듯 이 동적 에이전트 의 진정한 관건 은 getProxyClass 방법 이다.이 방법 은 인터페이스 에 프 록 시 유형 대상 을 동적 으로 생 성 하 는 것 을 책임 진다.
     클 라 스 대리 에 대한 필요 성 을 부정 할 수 있 는 여러 가지 이유 가 있 지만 클 라 스 동적 대 리 를 지원 하 는 것 이 더 좋 을 것 이 라 고 믿 는 이유 도 있다.인터페이스 와 클래스 의 구분 은 원래 뚜렷 하지 않 고 자바 에 가서 야 이렇게 세분 화 되 었 다.만약 에 방법의 성명 과 정 의 된 여부 만 고려 하면 두 가지 혼합 체 가 있 는데 그 이름 은 추상 류 이다.추상 류 에 대한 동적 대 리 를 실현 하 는 것 도 내재 적 가치 가 있다 고 믿는다.그 밖 에 역사 에 남 겨 진 유형 도 있 는데 그들 은 어떠한 인터페이스 도 실현 하지 못 했 기 때문에 동태 대리 와 영원히 인연 이 없 을 것 이다.이런 저런 것들 은 어 쩔 수 없 이 작은 유감 이 라 고 말 할 수 밖 에 없다.
그러나 완벽 하지 않 은 것 은 위대 하지 않 은 것 과 같 지 않다.위대 함 은 본질 이 고 자바 동적 대 리 는 좌 례 이다.
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기