ホームページ  >  記事  >  Java  >  Javaのプロキシパターンの詳しい説明とサンプルコード

Javaのプロキシパターンの詳しい説明とサンプルコード

高洛峰
高洛峰オリジナル
2017-02-07 13:08:031429ブラウズ

Java プロキシ パターンの詳細な説明

前書き:

場合によっては、クライアントがオブジェクトを直接参照したくない、または参照できない場合があります。この場合、「プロキシ」と呼ばれるサードパーティを介して間接参照を実現できます。プロキシ オブジェクトは、クライアントとターゲット オブジェクトの間の仲介者として機能し、クライアントが表示できないコンテンツやサービスを削除したり、クライアントが必要とするサービスをプロキシ オブジェクトを通じて追加したりできます。

簡単に言えば、プロキシ モードは、プロキシ オブジェクトを通じて実際のオブジェクトにアクセスし、デコレーション モードと同様にオブジェクトにいくつかの機能を追加できます。

静的プロキシ

いわゆる静的プロキシは、プログラムが実行される前にプロキシ クラスがすでに存在していることを意味します。つまり、コードを作成するときにプロキシ クラスのコードがすでに記述されているのに対し、動的プロキシは自動的にプロキシ クラスのコードを作成します。プログラムの実行時に生成される。

説明が抽象的すぎます。コードを見れば何が起こっているか理解できます

インターフェース

public class Main {
 
  public static void main(String[] args) {
    Water water = new Water();
    WaterProxy waterProxy = new WaterProxy(water);
    waterProxy.drink();
  }
 
}

エージェントクラス

//代理类与被代理类共同实现的接口
public interface Drink {
  void drink();
}

実行結果

れーれー

動的プロキシ

時々、プロキシクラスによって表されるクラスを変更したいだけですが、プロキシオブジェクトは、よく言われるように、実際のオブジェクトのメソッドを実行する前後で同じことを行います。クラス、フローエージェントクラス。静的プロキシでは、同じインターフェイスを実装するクラスのみをプロキシできます。任意のクラスをプロキシしたい場合は、重複したプロキシ クラスを多数記述する必要があります。現時点では、動的プロキシを使用できます。Java は、動的プロキシを実装するための便利なツールのセットを提供しています。

プロキシ オブジェクトを動的に生成できる java.lang.reflect.Proxy クラスのメソッド

//被代理的类
public class Water implements Drink {
 
  @Override
  public void drink() {
    System.out.println("drink water");
  }
 
}

InvocationHandler インターフェース

//代理类
//与被代理类实现同一个接口
public class DrinkProxy implements Drink {
   
  private Drink drinkImpl;
   
  //通过构造函数传入Water对象
  public DrinkProxy(Drink drinkImpl) {
    this.drinkImpl = drinkImpl;
  }
   
  @Override
  public void drink() {
    //在执行被代理对象的方法前做一些事情
    System.out.println("before drink");
    //执行被代理对象的方法
    drinkImpl.drink();
    //在执行被代理对象的方法后做一些事
    System.out.println("after drink");
  }
 
}

説明は常に抽象的なので、見て理解する方が良いです実際の例

InvocationHandlerインターフェース実装クラス

before drink
drink water
after drink

Main

/**
   *返回实现了指定接口的对象,调用代理对象的方法会调用
   *InvocationHandler的invoke方法
   *
   * @param  loader 获取代理类所使用的类加载器
   * @param  interfaces 代理类所要实现的接口
   * @param  h 实现了InvocationHandler接口的对象
   * @return 代理对象
   */
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)

出力結果

/**
 *每个代理类都有一个关联的InvocationHandler
 *当代理对象执行一个方法的时候会直接执行invoke方法
 */
public interface InvocationHandler {
 
  /**
   * @param  调用该方法的代理对象
   * @param  method 代理对象所调用的方法
   * @param  args 调用的方法的参数
   * @return 调用的方法的返回值
   */
  public Object invoke(Object proxy, Method method, Object[] args)
}

特定のプロキシ オブジェクトですが、それは対応するインターフェイス (インターフェイスの実装なし。クラスは cglib を使用して動的プロキシを実装できます) を使用して、プロキシ オブジェクトを動的に取得します。たとえば、最近人気のある Retrofit は、動的プロキシを使用して、宣言されたインターフェイスを通じてネットワーク リクエストを直接作成します。

レトロフィットの簡単なシミュレーション

POSTアノテーション

public class CommonInvocationHandler implements InvocationHandler {
   
  //被代理的对象
  private Object proxied;
   
  public CommonInvocationHandler(Object proxied) {
    this.proxied = proxied;
  }
   
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //在调用被代理对象的方法前做一些事情
    System.out.println("before doing something");
    //调用被代理对象的方法
    Object result = method.invoke(proxied, args);
    //在调用被代理对象的方法后做一些事情
    System.out.println("after doing something");;
    return result;
  }
 
}

クエリアノテーション

public class Main {
 
  public static void main(String[] args) {
    //被代理的对象
    Water water = new Water();
    //动态获取代理对象
    Drink waterProxy =
        (Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(),
            water.getClass().getInterfaces(),
            new CommonInvocationHandler(water));
    //通过代理对象调用方法
    waterProxy.drink();
  }
 
}

サービスインターフェース

before doing something
drink water
after doing something

メイン

//Post请求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface POST {
 String value() default "";
}

読んでいただきありがとうございます、皆様のお役に立てれば幸いです。このサイトのご支援に感謝いたします。

Java のプロキシ モードに関する詳細な説明とサンプル コード関連記事については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。