はじめに:セキュリティ担当者として、エージェントが人々使用の多くあり、その中に動的プロキシのJava何ですか?実際には、「ダイナミック」でのJavaは、リフレクションを使用することを意味し、そのエージェントは、代理店モデルの動的反射に基づいています。
要約:
演技は、その目的は、他のオブジェクトへのオブジェクトへのアクセスを制御するプロキシを提供することであり、一般的なデザインパターンです。委譲クラスは、以降の処理を実行した後、前処理メッセージ、メッセージのフィルタリングおよび転送メッセージ、およびメッセージの責任委譲クラスのクラスの薬剤が行われます。行動の一貫性を維持するためには、プロキシクラスとデリゲートクラスは通常、同じインタフェースを実装し、それはわずかな差がない場合の両方の訪問者です。デザインの多くを得られるように、プロキシクラスによって中間層は、効果的に、うまく隠され、委譲クラスのオブジェクトによって保護するだけでなく、異なる制御戦略の実施のためのスペースを脇に設定することができますデリゲートオブジェクトへの直接アクセスを制御することができます柔軟性。完璧に近いデザインエージェンシーモデルを実践する巧妙な方法でJavaの動的プロキシメカニズム。
パブリック インターフェース被写体{ ボイドsimpleSubject(); }
realSubject実装クラス
パブリック クラスrealSubjectは、被験者{実装 公共 ボイドsimpleSubject(){ システム。アウト .println(" これはsimpleSubjectあります" ); } }
各オブジェクトは、このsimpleSubjectインタフェースrealSubjectを持っていますが、あなたは、動的実行時にオブジェクトをしたい場合は、いくつかのhardSubject機能を添付し、どのようにそれを行うには?我々hardSubjectと追加機能(または追加情報の一部)は、プロキシオブジェクトのプロキシオブジェクトを実装することによって達成されます。すなわちオブジェクト(のInvocationHandlerの)コールハンドラプロセッサハンドラを結合するためにプロキシオブジェクトを生成しながらたとえば、Proxy.newProxyInstance実装は、プロキシオブジェクトによってプロキシオブジェクトが生成されます。
まず、hardSubject機能を追加するために、元のインターフェースメソッドのまたは前後ににproxyHandlerを達成するために、(正確ではないかもしれないここで関数)
輸入java.lang.reflect.InvocationHandler。 輸入java.lang.reflect.Methodオブジェクト。 パブリック クラスにproxyHandlerはのInvocationHandler {実装 プライベートrealSubjectの対象を、 公的にproxyHandler(realSubject対象){ この .subject = 主題; } パブリックオブジェクトを呼び出し(オブジェクトプロキシ、メソッドの方法は、[]引数オブジェクト)のThrowable {スロー
システム。(out.printlnを" 追加hardSubject1 I'am ")。 method.invoke(被写体) システム。アウト .println(" 追加hardSubject2 I'am ")。 リターン ヌル。 } }
ビューのInvocationHandlerインタフェースのソースコード注釈は、それが関数であることを知ることができます。元のオブジェクトがプロキシインタフェースのメソッドが呼び出されたときに、定義されたのInvocationHandlerの実行方法をバインドします。
その後、我々は、プロキシオブジェクトをインスタンス化するテストクラスを書きます
proxyTestテストクラス
輸入java.lang.reflect.InvocationHandler。 輸入java.lang.reflect.Proxyの; パブリック クラスproxyTest { 公共 静的 ボイドメイン(文字列[]引数){ realSubject RS = 新しいrealSubject()。 InvocationHandlerさh = 新たにproxyHandler(RS)。 クラスclazz = rs.getClass()。 被写体S = (被写体)たとえば、Proxy.newProxyInstance(clazz.getClassLoader()、clazz.getInterfaces()、H)。 s.simpleSubject(); システム。アウト.println(s.getClass()); } }
プロキシ方法newProxyInstance三つのパラメータ、すなわちrealSubjectクラスローダ、インターフェイス、我々は、オブジェクトのインスタンスにproxyHandlerを定義
ソースコードを見てください:
パブリック 静的オブジェクトnewProxyInstance(クラスローダローダ、 クラス <?> []インターフェイス、 のInvocationHandler hは) はIllegalArgumentExceptionスロー { Objects.requireNonNull(時間)。 最終的なクラス <?> [] intfs = interfaces.clone()。 最終的なセキュリティマネージャSM = System.getSecurityManager()。 もし(!SM = NULL ){ checkProxyAccess(Reflection.getCallerClass()、ローダ、intfs)。 } / * *見上げまたは指定されたプロキシクラスを生成します。 * / クラス CL = <?> getProxyClass0(ローダー、intfs)。 / * *指定された呼び出しハンドラとそのコンストラクタを呼び出します。 * / してみてください{ 場合(!SM = nullを{) checkNewProxyPermission(Reflection.getCallerClass()、CL); } 最終的なコンストラクタ <?>短所= cl.getConstructor(constructorParams)。 最終のInvocationHandler IH = H; もし(!Modifier.isPublic(cl.getModifiers())){ AccessController.doPrivilegedの((にInvocationTargetException電子){新たPrivilegedAction <ボイド> (){ 公共ボイドラン(){ cons.setAccessible(真)。 リターン ヌル。 } })。 } 戻り cons.newInstanceを(新しいオブジェクト[] {H})。 } キャッチ(IllegalAccessExceptionが| ないInstantiationException電子){ スロー 新しいInternalError(e.toString()、e)を、 } キャッチ のThrowable T = e.getCause()。 もし(TのRuntimeExceptionのinstanceof){ スロー(のRuntimeException)T。 } 他{ スロー 新しいInternalError(t.toString()、t)を。 } } キャッチ(ないNoSuchMethodException電子){ スロー 新しいInternalError(e.toString()、e)を、 } }
私は、これが唯一のクラスローダを使用するために知っておく必要がありともかく生成されたプロキシクラスがプロキシクラスがどのようである(ClassはCLプロキシクラスをオブジェクトを取得するためにリフレクションを使用するための最初のステップの重要な一部であり、コードの一部を太字反射インタフェースがダウンコードが最後のコンストラクタによって反射された、プロキシクラスCLクラス・オブジェクトによってここProxyGenerator.generateProxyClassプロキシクラス、コードのみ分析)コンストラクタgetConstructor再取得して生成する必要が深いと。実施しますプロキシクラスのオブジェクトを取得するには、我々はにproxyHandlerオブジェクトhを通過したときのnewInstanceを持つオブジェクトは、プロキシクラスを生成見ることができます
それは、このプロキシオブジェクトが参照インターフェイスクラスの対象であることを言及する価値がある、このオブジェクトは、実際にrealSubjectとにproxyHandlerの一部ではありませんが、対象への参照の安全なタイプに変換することができますので、それは、対象インタフェースを実装しているため。しかし、実際には、我々は、このコードを実行し、出力s.getClassが()されます
それは私たちが見てきたどのクラスにも属していないが、それは親クラスに属することをプロキシクラスがあります
最後に、我々は、動的なエージェントを達成するための手順を要約したものです。
独自のコールプロセッサを作成するためのインタフェースを実装することにより、1のInvocationHandler。
2.インタフェースオブジェクトとプロキシクラスとしてクラスローダのセットを指定することにより、動的プロキシクラスを作成します。
3.動的プロキシクラスのコンストラクタは、唯一のパラメータのタイプは、呼プロセッサインタフェースタイプである反射することによって得られます。
4.ハンドラを呼び出すように構成された動的プロキシクラスのコンストラクタ・オブジェクトがパラメータとして渡される介してインスタンスを作成します。