ジャワのInvocationHandlerと動的エージェントプロキシのコメント

Proxyクラス

この方法newProxyInstanceプロキシはプロキシオブジェクトのクラスを返します。

パブリック静的オブジェクトnewProxyInstance(クラスローダローダ、
                                          クラス<?> []インターフェイス、
                                          のInvocationHandler hは)
        IllegalArgumentExceptionをスロー
  • ローダー:クラスローダは、nullを使用して、デフォルトのクラスローダを使用します。
  • インターフェース:オブジェクトのクラスのアレイは、各要素が実装する必要があります。
  • H:呼プロセッサ。

他の2つの方法:

  • パブリック静的クラスgetProxyClass(<?>クラスローダーローダー、クラス...インタフェース)<?>:プロキシクラスのインタフェースを返します。
  • パブリック静的ブールisProxyClass(クラスCL <?>):CLがある場合は、プロキシクラスはtrueを返します。

InvocationHandlerインタフェース

第三のパラメータは、このインターフェイスが唯一の方法である、のInvocationHandler newProxyInstance方法です。

パブリックオブジェクトを呼び出し(オブジェクトプロキシ、メソッドのメソッド、オブジェクト[]引数)が
        Throwableをスローします。

呼プロキシクラスの任意の方法、メソッドを呼び出す最初に呼び出されるとき、この方法は、引数は、メソッドの元のパラメータであり、本来の目的である方法。

ここでは、実際にプロキシnewInstanceメソッドの戻りで、そのオブジェクトは、彼が実際のオブジェクトは、プロキシオブジェクトの(つまり、私たちはプロキシオブジェクトにしたい)で、最初の引数プロキシです。通常の状況下で、我々は、実際のオブジェクトのメソッドは、我々は継続的にプロキシオブジェクトの呼び出し(チェーンコール)は、あなたがオブジェクトを返すことができますする必要がある場合、呼び出し()メソッドを呼び出した結果を返します。

(実際のオブジェクトのターゲット)の下で一般的な混乱:

パブリックオブジェクトを呼び出し(オブジェクトプロキシ、方法方法、[]引数オブジェクト)が
        Throwableを{スロー
    リターンmethod.invoke(ターゲット、引数)。
}

連続通話時間が必要:

パブリックオブジェクトを呼び出し(オブジェクトプロキシ、メソッドの方法は、[]引数オブジェクト)
        のThrowable {スロー
    method.invoke(ターゲット、引数)を、
    プロキシを返します。
}

動的プロキシ簡単な実装

さて、攻撃()メソッドが含まれているヒーロー・インターフェースを作成して、ダイナミックプロキシを使用して、インタフェースのいずれかの実装では、「手ぶれをキャストする前に、」英雄ヒーロープリントされ、攻撃の呼び出しの前と後に「手ぶれを鋳造後」。

パッケージcloud.proxy。

パブリックインターフェースヒーロー{ 
    ボイド攻撃(); 
}

その後、ゼウスのキャストサンダーの怒りを作成します。

パッケージcloud.proxy。

インポート静的なJavaの .lang.System.out。

パブリッククラスZuesはヒーロー{実装
    @Override 
    ます。public void攻撃(){ 
        ( "雷神之怒!")out.printlnをします。
    } 
}

最後に、プロキシオブジェクトHeroProxyカテゴリを作成します。

パッケージcloud.proxy。

輸入java.lang.reflect.Proxyの; 

輸入静的java.lang.System.out。

パブリッククラスHeroProxy { 
    の前にプライベート無効(){ 
        out.printlnを( "准备施法..."); 
    } 

    (後プライベートボイド){ 
        out.printlnを( "完成施法。"); 
    } 

    公共ヒーローのnewInstance(<?ヒーロー延び>最終的なクラスtargetClass)がThrowableを{スロー
        。ヒーロー目標= targetClass.getConstructor()のnewInstanceを(); 
        リターン(ヒーロー)たとえば、Proxy.newProxyInstance(Hero.class.getClassLoader()、新しいクラスは、[] {Hero.class}、 プロキシ、メソッド、引数) - > { 
                    ()の前に、 
                    オブジェクト結果= method.invoke(ターゲット、引数);
                    後に(); 
                    戻り値の結果。
                } 
        ); 
    } 
}

あなたはのnewInstance()メソッドHeroProxyを呼び出すと、プロキシクラスを介してプロキシオブジェクトを取得するには、元のオブジェクトのターゲットを作成し、そして、このエンティティクラスがのInvocationHandlerを実装していますが、匿名クラス(ラムダ式)を使用して作成していません。

テストカテゴリ:

パッケージcloud.proxy。

輸入org.junit.Test; 

パブリッククラスHeroProxyTest { 

    @Test 
    公共ボイドGetProxyObjectの呼び出しは、()のThrowable {スロー
        =新しいHeroProxy()HeroProxyプロキシ。
        //创建Zues的代理对象
        ヒーローヒーロー= proxy.newInstance(Zues.class)。
        hero.attack(); 
    } 
}

結果:

com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 cloud.proxy.HeroProxyTest 

キャストする準備ができて... 
サンダー怒り!
キャスティングは完了です。



プロセス終了コード0で終了

ヒント

Proxyクラスは、メソッド呼び出しを追跡するときにプロセスに並べ替えるために多くの時間を見ることができるように、例えば、我々は、いくつかの情報をプリントアウトし、compareToメソッドの呼び出しの前に、Comparableインタフェースのプロキシクラスを作成することができ便利です。

おすすめ

転載: www.linuxidc.com/Linux/2019-08/160011.htm