動的プロキシは実際には、指定したすべてのインターフェイスに基づいてクラス バイトを動的に生成する java.lang.reflect.Proxy クラスです。このクラスは Proxy クラスを継承し、指定したすべてのインターフェイス (パラメータで渡すインターフェイス配列) を実装します。 ) ; 次に、指定したクラスローダーを使用してクラスバイトをシステムにロードし、最後にそのようなクラスのオブジェクトを生成し、すべてのインターフェイスに対応するメソッドメンバーである invocationHandler などのオブジェクトのいくつかの値を初期化します。 。 初期化後、オブジェクトは呼び出し側クライアントに返されます。このようにして、クライアントはすべてのインターフェイスを実装する Proxy オブジェクトを取得します。分析例を参照してください。
パブリック インターフェイス BusinessProcessor {
public void processBusiness();
}
@オーバーライド
public void processBusiness() {
System.out.println("業務を処理中....");
}
}
インポート java.lang.reflect.InvocationHandler;
java.lang.reflect.Methodをインポートします。
/**
※業務代行部門
* @作者ファンシャドゥープ
*
*/
パブリック クラス BusinessProcessorHandler は InvocationHandler を実装します {
プライベートオブジェクトターゲット = null;
BusinessProcessorHandler(オブジェクトターゲット) {
this.target = ターゲット;
}
public Object invoke(オブジェクトプロキシ、メソッドメソッド、Object[] args)
スロー可能 {
システムアウト
.println("ビジネスを処理する前に、ここで何かを行うことができます");
オブジェクトの結果 = method.invoke(target, args);
システムアウト
.println("ビジネスを処理した後、ここで何かを行うことができます");
結果を返します。
}
}
java.lang.reflect.Fieldをインポートします。
java.lang.reflect.Methodをインポートします。
java.lang.reflect.Modifierをインポートします。
java.lang.reflect.Proxyをインポートします。
パブリック クラス テスト {
/**
* @param 引数
*/
public static void main(String[] args) {
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
BusinessProcessorHandler ハンドラー = new BusinessProcessorHandler(bpimpl);
ビジネスプロセッサ bp = (ビジネスプロセッサ) Proxy.newProxyInstance(
bpimpl.getClass().getClassLoader()、bpimpl.getClass()
.getInterfaces()、ハンドラー);
bp.processBusiness();
System.out.println(bp.getClass().getName());
printClassDefinition(bp.getClass());
}
public static String getModifier(int modifier) {
文字列結果 = "";
スイッチ (修飾子) {
case 修飾子.PRIVATE:
結果 = "プライベート";
case 修飾子.PUBLIC:
結果 = "パブリック";
case Modifier.PROTECTED:
結果 = "保護されています";
case Modifier.ABSTRACT:
結果 = "抽象";
case 修飾子.FINAL:
結果 = "最終";
case 修飾子.NATIVE:
結果 = "ネイティブ";
case 修飾子.STATIC:
結果 = "静的";
case 修飾子.SYNCHRONIZED:
結果 = "同期";
case 修飾子.STRICT:
結果 = "厳密";
case 修飾子.TRANSIENT:
結果 = "一時的";
case 修飾子.VOLATILE:
結果 = "揮発性";
case 修飾子.INTERFACE:
結果 = "インターフェイス";
}
結果を返します。
}
public static void printClassDefinition(Class clz) {
文字列 clzModifier = getModifier(clz.getModifiers());
if (clzModifier != null && !clzModifier.equals("")) {
clzModifier = clzModifier + " ";
}
文字列 superClz = clz.getSuperclass().getName();
if (superClz != null && !superClz.equals("")) {
superClz = "拡張" + superClz;
}
クラス[] インターフェイス = clz.getInterfaces();
文字列インター = "";
for (int i = 0; i < インターフェース.length; i++) {
if (i == 0) {
inters += "実装";
}
inters += インターフェイス[i].getName();
}
System.out.println(clzModifier + clz.getName() + " " + superClz + " "
+ インター);
System.out.println("{");
フィールド[] フィールド = clz.getDeclaredFields();
for (int i = 0; i < フィールド.length; i++) {
文字列修飾子 = getModifier(fields[i].getModifiers());
if (modifier != null && !modifier.equals("")) {
修飾子 = 修飾子 + " ";
}
文字列フィールド名 = フィールド[i].getName();
文字列フィールドタイプ = フィールド[i].getType().getName();
System.out.println(" " + 修飾子 + fieldType + " " + fieldName
+ ";");
}
System.out.println();
Method[] メソッド = clz.getDeclaredMethods();
for (int i = 0; i <methods.length; i++) {
メソッドメソッド = メソッド[i];
文字列修飾子 = getModifier(method.getModifiers());
if (modifier != null && !modifier.equals("")) {
修飾子 = 修飾子 + " ";
}
文字列メソッド名 = メソッド.getName();
クラス returnClz = method.getReturnType();
文字列 retrunType = returnClz.getName();
Class[] clzs = method.getParameterTypes();
文字列 paraList = "(";
for (int j = 0; j < clzs.length; j++) {
paraList += clzs[j].getName();
if (j != clzs.length - 1) {
paraList += ", ";
}
}
paraList += ")";
clzs = メソッド.getExceptionTypes();
文字列例外 = "";
for (int j = 0; j < clzs.length; j++) {
if (j == 0) {
例外 += "スロー";
}
例外 += clzs[j].getName();
if (j != clzs.length - 1) {
例外 += ", ";
}
}
例外 += ";";
文字列メソッドプロトタイプ = 修飾子 + retrunType + " " + メソッド名
+ paraList + 例外;
System.out.println(" " + MethodPrototype);
}
System.out.println("}");
}
}
ブール値と等しい(java.lang.Object);
java.lang.String toString();
int hashCode();
void processBusiness();
}
明らかに、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 パラメーターを使用してそのすべてのインターフェイス メソッドを横断し、メソッド オブジェクトを生成して、物体。
4. $Proxy0 のインスタンスをクライアントに返します。
もう大丈夫です。クライアントがそれをどのように調整するかを見てみましょう。そうすれば明らかになるでしょう。
1. クライアントは$Proxy0のインスタンスオブジェクトを取得します。$Proxy0はBusinessProcessorを継承しているため、BusinessProcessorに変換しても問題ありません。
ビジネスプロセッサ bp = (ビジネスプロセッサ)Proxy.newProxyInstance(....);
2. bp.processBusiness();
実際に呼び出されるのは $Proxy0.processBusiness() で、$Proxy0.processBusiness() の実装は InvocationHandler を通じてメソッドを呼び出します。