Javaダイナミックプロキシの応用例を詳しく解説

黄舟
リリース: 2016-12-19 14:28:42
オリジナル
1275 人が閲覧しました

動的プロキシは、実際には、指定したすべてのインターフェースに基づいてクラスを動的に生成する java.lang.reflect.Proxy クラスです。 バイトの場合、このクラスは Proxy クラスを継承し、指定したすべてのインターフェイス (パラメーターで渡すインターフェイス配列) を実装し、指定したクラスローダーを使用します。 クラス バイトがシステムにロードされ、最終的にそのようなクラスのオブジェクトが生成され、invocationHandler、つまりすべてのインターフェイスに対応するメソッド メンバーなど、オブジェクトのいくつかの値が初期化されます。 初期化後、オブジェクトは呼び出し側クライアントに返されます。このようにして、クライアントはすべてのインターフェイスを実装する Proxy オブジェクトを取得します。分析例を参照してください:

package com.fans.common.proxy;
public interface BusinessProcessor {
  public void processBusiness();
}
ログイン後にコピー
package com.fans.common.proxy;
/**
 * 业务处理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorImpl implements BusinessProcessor {
 @Override
 public void processBusiness() {
  System.out.println("processing business.....");
 }
}
ログイン後にコピー
package com.fans.common.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * 业务代理类
 * @author fanshadoop
 *
 */
public class BusinessProcessorHandler implements InvocationHandler {
 private Object target = null;
 BusinessProcessorHandler(Object target) {
  this.target = target;
 }
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  System.out
    .println("You can do something here before process your business");
  Object result = method.invoke(target, args);
  System.out
    .println("You can do something here after process your business");
  return result;
 }
}
ログイン後にコピー
package com.fans.common.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
public class Test {
 /**
  * @param args
  */
 public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
    bpimpl.getClass().getClassLoader(), bpimpl.getClass()
      .getInterfaces(), handler);
  bp.processBusiness();
  System.out.println(bp.getClass().getName());
  printClassDefinition(bp.getClass());
 }
 public static String getModifier(int modifier) {
  String result = "";
  switch (modifier) {
  case Modifier.PRIVATE:
   result = "private";
  case Modifier.PUBLIC:
   result = "public";
  case Modifier.PROTECTED:
   result = "protected";
  case Modifier.ABSTRACT:
   result = "abstract";
  case Modifier.FINAL:
   result = "final";
  case Modifier.NATIVE:
   result = "native";
  case Modifier.STATIC:
   result = "static";
  case Modifier.SYNCHRONIZED:
   result = "synchronized";
  case Modifier.STRICT:
   result = "strict";
  case Modifier.TRANSIENT:
   result = "transient";
  case Modifier.VOLATILE:
   result = "volatile";
  case Modifier.INTERFACE:
   result = "interface";
  }
  return result;
 }
 public static void printClassDefinition(Class clz) {
  String clzModifier = getModifier(clz.getModifiers());
  if (clzModifier != null && !clzModifier.equals("")) {
   clzModifier = clzModifier + " ";
  }
  String superClz = clz.getSuperclass().getName();
  if (superClz != null && !superClz.equals("")) {
   superClz = "extends " + superClz;
  }
  Class[] interfaces = clz.getInterfaces();
  String inters = "";
  for (int i = 0; i < interfaces.length; i++) {
   if (i == 0) {
    inters += "implements ";
   }
   inters += interfaces[i].getName();
  }
  System.out.println(clzModifier + clz.getName() + " " + superClz + " "
    + inters);
  System.out.println("{");
  Field[] fields = clz.getDeclaredFields();
  for (int i = 0; i < fields.length; i++) {
   String modifier = getModifier(fields[i].getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String fieldName = fields[i].getName();
   String fieldType = fields[i].getType().getName();
   System.out.println("    " + modifier + fieldType + " " + fieldName
     + ";");
  }
  System.out.println();
  Method[] methods = clz.getDeclaredMethods();
  for (int i = 0; i < methods.length; i++) {
   Method method = methods[i];
   String modifier = getModifier(method.getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String methodName = method.getName();
   Class returnClz = method.getReturnType();
   String retrunType = returnClz.getName();
   Class[] clzs = method.getParameterTypes();
   String paraList = "(";
   for (int j = 0; j < clzs.length; j++) {
    paraList += clzs[j].getName();
    if (j != clzs.length - 1) {
     paraList += ", ";
    }
   }
   paraList += ")";
   clzs = method.getExceptionTypes();
   String exceptions = "";
   for (int j = 0; j < clzs.length; j++) {
    if (j == 0) {
     exceptions += "throws ";
    }
    exceptions += clzs[j].getName();
    if (j != clzs.length - 1) {
     exceptions += ", ";
    }
   }
   exceptions += ";";
   String methodPrototype = modifier + retrunType + " " + methodName
     + paraList + exceptions;
   System.out.println("    " + methodPrototype);
  }
  System.out.println("}");
 }
}
ログイン後にコピー

操作結果:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.fans.common.proxy.BusinessProcessor
{
    java.lang.reflect.Method m1;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m2;
    boolean equals(java.lang.Object);
    java.lang.String toString();
    int hashCode();
    void processBusiness();
}
ログイン後にコピー

BusinessProcessorHandler クラスは、InvocationHandler インターフェイスの呼び出しメソッドを実装します。このクラスは、Proxy が最終的に呼び出す固定インターフェイス メソッドです。


明らかに、Proxy.newProxyInstance メソッドは次のことを行います:
1. 渡された 2 番目のパラメーター インターフェイスに基づいてクラスを動的に生成し、インターフェイスにインターフェイスを実装します。この例では、BusinessProcessor インターフェイスの processBusiness メソッドです。そしてProxyクラスを継承し、hashcode、toString、equalsの3つのメソッドを書き換えます。具体的な実装については、以下を参照してください。 ProxyGenerator.generateProxyClass(...); この例では、$Proxy0 クラス
2 が生成され、最初のパラメーターに渡された classloder を通じて新しく生成されたクラスが jvm にロードされます。 $Proxy0 クラスをロードしようとしています
3、3 番目のパラメーターを使用して $Proxy0 の $Proxy0 (InvocationHandler) コンストラクターを呼び出し、$Proxy0 のオブジェクトを作成し、interfaces パラメーターを使用してそのすべてのインターフェイスのメソッドを走査し、 Method オブジェクトを使用してオブジェクトを初期化します。メソッド メンバー変数
4、$Proxy0 のインスタンスをクライアントに返します。
もう大丈夫です。クライアントがそれをどのように調整するかを見てみましょう。そうすれば明らかになるでしょう。
1. クライアントが取得するのは$Proxy0のインスタンスオブジェクトです。 $Proxy0はBusinessProcessorを継承しているのでBusinessProcessorに変換しても問題ありません。 S BusinessProcessor BP = (BusinessProcessor) Proxy.newproxyinstance (...);
2, bp.processBusiness (); $ proxy0.processBusines () の実装は、InvocationHandler を介して invoke メソッドを呼び出します

以上が詳細な説明です。 Java ダイナミック プロキシ アプリケーションの詳細については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート