프록시 모드:Proxy 모드

1. 프록시 모드 프록시 모드의 역할은 대상에게 프록시를 제공하여 이 대상에 대한 접근을 제어하는 것이다.어떤 상황에서 한 고객이 다른 대상을 원하지 않거나 직접 인용할 수 없으며 대리 대상은 클라이언트와 목표 대상 사이에 중개 역할을 할 수 있다.대리 모델은 일반적으로 세 가지 역할과 관련된다. 추상적인 역할: 진실 대상과 대리 대상의 공동 인터페이스를 성명한다.프록시 역할: 프록시 대상 역할 내부에 실제 대상에 대한 인용이 포함되어 있어 실제 대상을 조작할 수 있고 프록시 대상은 실제 대상과 같은 인터페이스를 제공하여 언제든지 실제 대상을 대체할 수 있다.또한 프록시 대상은 실제 대상 작업을 수행할 때 다른 조작을 추가할 수 있어 실제 대상을 봉인하는 것과 같다.실제 역할: 대리 역할이 대표하는 실제 대상은 우리가 최종적으로 인용할 대상이다.다음은 Java 및 모드의 예입니다.
//    :
abstract public class Subject{      
      abstract public void request();
}

 
//    :   Subject request()  。
public class RealSubject extends Subject{
      public void request(){
            System.out.println("From real subject.");
      }
} 

 
//    :
public class ProxySubject extends Subject{
      private RealSubject realSubject; //               

      public void request(){ //           request   
          preRequest(); 
          if( realSubject == null ){
                realSubject = new RealSubject();
          }
          realSubject.request(); //         request   
          postRequest(); 
       }
      private void preRequest(){       
      }
      private void postRequest(){ 
      }
}

 
//     :
Subject sub=new ProxySubject();
Sub.request(); 

위 코드에서 알 수 있듯이 고객이 실제적으로 필요로 하는 것은 RealSubject 클래스의 Request () 방법입니다. 현재는 ProxySubject로 RealSubject 클래스를 대리하고 같은 목적을 달성하는 동시에 다른 방법(preRequest (),postRequest () 을 봉하여 다른 문제를 처리할 수 있습니다.또한 상술한 방법에 따라 대리 모델을 사용하려면 실제 역할은 사전에 존재하고 이를 대리 대상의 내부 속성으로 해야 한다.그러나 실제적으로 사용할 때 하나의 실제 역할은 반드시 하나의 대리 역할에 대응해야 한다. 만약에 대량으로 사용하면 유형의 급격한 팽창을 초래할 수 있다.또 실제 캐릭터를 미리 몰랐다면 대리인을 어떻게 사용해야 하는가?이 문제는 자바의 동적 프록시 클래스를 통해 해결할 수 있습니다.2. Dynamic Agent Java Dynamic Agent 클래스는 Java에 있습니다.lang.reflect 패키지 아래에는 일반적으로 다음과 같은 두 가지 종류가 관련된다. (1) Interface Invocation Handler: 이 인터페이스에는 하나의 방법만 정의되어 있다. Object: invoke(Object obj, Method method, Object[] args).실제적으로 사용할 때 첫 번째 매개 변수obj는 일반적으로 에이전트 클래스를 가리키며method는 에이전트된 방법입니다. 예를 들어 상례의request ()와args는 이 방법의 매개 변수 그룹입니다.이 추상적인 방법은 대리류에서 동태적으로 실현된다.(2) Proxy: 이 클래스는 동적 프록시 클래스로 전례의 ProxySubject와 유사하며 주로 다음과 같은 내용을 포함한다. Protected Proxy(Invocation Handler h): 구조 함수로 내부의 h에 값을 부여하는 데 사용된다.Static Class get Proxy Class(Class Loader loader, Class []interfaces): 에이전트 클래스를 얻습니다. 그 중에서 loader는 클래스 마운트기고interfaces는 실제 클래스가 가지고 있는 모든 인터페이스의 그룹입니다.Static Object new Proxy Instance(ClassLoader loader, Class[] interfaces, Invocation Handler h): 프록시 클래스의 예를 되돌려줍니다. 프록시 클래스는 프록시 클래스로 사용할 수 있습니다. (프록시 클래스가 Subject 인터페이스에서 설명한 방법을 사용할 수 있습니다.)Dynamic Proxy란 다음과 같은 class입니다.
이것은 실행할 때 생성된class입니다. 생성할 때 인터페이스 그룹을 제공해야 합니다. 그리고 이 클라이언트는 이인터페이스가 실현되었다고 발표합니다.너는 당연히 이class의 실례를 이 인터페이스 중의 어떤 것으로 사용해도 된다.물론, 이 다이나믹 Proxy는 사실 하나의 Proxy입니다. 이 다이나믹 Proxy는 당신을 대신해서 실질적인 일을 하지 않습니다. 이 다이나믹 Proxy의 실례를 만들 때handler를 제공해서 실제 일을 맡아야 합니다.동적 프록시 클래스를 사용할 때는 첫 번째 섹션의 예를 들어 InvocationHandler 인터페이스를 구현해야 합니다.
 
    (      ,       ): 

public   interface  Subject  { 
    abstract   public   void  request(); 
}  

    RealSubject:
public   class  RealSubject  implements  Subject {

   public  RealSubject() {}

   public   void  request() {
    System.out.println( " From real subject. " );
  }

} 

 
//    :
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler{
      private Object sub; 
      public DynamicSubject(Object sub){            
            this.sub = sub;
      }
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          System.out.println("before calling " + method); 
          method.invoke(sub,args); 
          System.out.println("after calling " + method); 
          return null; 
      }
}

이렇게 할 수도 있다.
import java.lang.reflect.Method;   
import java.lang.reflect.InvocationHandler;   
import java.lang.reflect.Proxy;
public class DynamicSubject implements InvocationHandler{   
      private Object sub;    
      public Object createProxyInstance(Object sub){               
            this.sub = sub; 
            return Proxy.newProxyInstance(this.sub.getClass().getClassLoader(), this.sub.getClass().getInterfaces(), this);
      //           
}   
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
          System.out.println("before calling " + method);    
          method.invoke(sub,args);    
          System.out.println("after calling " + method);    
          return null;    
      }   
}  

 
이 프록시 클래스의 내부 속성은 Object 클래스이며, 실제 사용 시 해당 클래스의 구조 함수인 DynamicSubject(Object obj)를 통해 값을 부여합니다.그 밖에 이 종류에서 invoke 방법을 실현했고 이 방법 중의
method.invoke(sub,args);
사실은 피대리 대상을 호출하여 실행할 방법입니다. 방법 매개 변수sub는 실제 피대리 대상이고args는 피대리 대상의 상응하는 조작을 수행하기 위해 필요한 매개 변수입니다.동적 프록시 클래스를 통해 우리는 호출하기 전이나 이후에 관련 작업을 수행할 수 있다.
클라이언트:
public   class  Client  { 

static   public   void  main(String[] args)  throws  Throwable  { 

   RealSubject rs  =   new  RealSubject();  //           
   InvocationHandler ds  =   new  DynamicSubject(rs); 
   Class cls  =  rs.getClass(); 

    //           
   Subject subject  =  (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds ); 
   subject.request(); 
}  

 
 
이를 통해 프록시된 객체(Real Subject)는 런타임 시 동적으로 변경할 수 있고, 제어가 필요한 인터페이스(Subject 인터페이스)는 런타임 시 변경할 수 있으며, 제어 방식(Dynamic Subject 클래스)도 동적으로 변경할 수 있어 매우 유연한 동적 프록시 관계를 실현할 수 있다.
3. 프록시 모드의 사용 원인과 응용
(1) 권한 수여 메커니즘이 서로 다른 등급의 사용자는 같은 대상에 대해 서로 다른 접근 권리를 가진다. 예를 들어 Jive 포럼 시스템에서 Proxy를 사용하여 권한 수여 메커니즘을 제어한다. 방문 포럼에는 두 가지 사람이 있는데 그것이 바로 가입 사용자와 관광객(미등록 사용자)이다. Jive에서는ForumProxy와 같은 에이전트를 통해 이 두 가지 사용자가 포럼에 대한 접근 권한을 제어한다.
(2) 어떤 클라이언트가 특정한 대상에게 직접 조작할 수 없지만 그 대상과 상호작용을 해야 한다.
두 가지 구체적인 예를 들다.
만약 그 대상이 매우 큰 그림이라면 매우 오랜 시간이 걸려야 표시할 수 있다. 그러면 이 그림이 문서에 포함될 때 편집기나 브라우저를 사용하여 이 문서를 열면 문서를 빨리 열어야 한다. 큰 그림 처리가 끝날 때까지 기다릴 수 없기 때문에 진정한 그림 대신 그림 Proxy를 만들어야 한다.
    
만약 그 대상이 인터넷의 어느 원격 서버에 있다면, 이 대상을 직접 조작하는 것은 네트워크 속도 때문에 비교적 느릴 수 있기 때문에, 우리는 먼저 Proxy로 그 대상을 대체할 수 있다.
    
한 마디로 하면 비용이 많이 드는 대상은 그것을 사용할 때만 만들 수 있다는 원칙이다. 이 원칙은 우리에게 많은 귀중한 자바 메모리를 절약할 수 있다.그래서 어떤 사람들은 자바가 자원 메모리를 소모한다고 생각하는데 이것은 프로그램 작성의 사고방식과도 일정한 관계가 있다고 생각한다.
(3) 현실에서 Proxy의 응용 범위가 매우 넓고 현재 유행하는 분포 계산 방식인 RMI와 Corba 등은 모두 Proxy모드의 응용이다.
참조:
http://www.blogjava.net/baoyaer/articles/84080.html
http://zhangli-lisa.iteye.com/blog/399417
프록시 모드, JDK 동적 프록시, SpringAOP 경위http://fruitking.iteye.com/blog/601106(중요 참조)

좋은 웹페이지 즐겨찾기