14

動的プロキシが通常のプロキシよりも役立つシナリオについてアドバイスが必要です。

私は、動的プロキシを効果的に使用する方法を学ぶことに多大な努力を払ってきました。この質問では、AspectJ のようなフレームワークが基本的に動的プロキシで達成しようとするすべてのことを実行できること、または動的プロキシのいくつかの欠点に対処するために CGLIB を使用できることは脇に置いておいてください。

ユースケース

  • デコレータ - たとえば、メソッド呼び出しのロギングを実行したり、複雑な操作の戻り値をキャッシュしたりします
  • 契約を維持する - つまり、パラメーターが許容範囲内にあり、戻り値の型が許容値に準拠していることを確認します。
  • アダプター - これがどのように役立つかを説明する巧妙な記事をどこかで見ました。ただし、このデザインパターンに出くわすことはめったにありません。

他は?

動的プロキシの利点

  • デコレーター: すべてのメソッド呼び出しをログに記録します。

public Object invoke(Object target, Method method, Object[] arguments) {
         System.out.println("before method " + method.getName());
         return method.invoke(obj, args);
     }
}

デコレータ パターンは、すべてのプロキシ メソッドに副作用を与えることができるため、間違いなく便利です (ただし、この動作はアスペクトを使用する本の例です)。

  • コントラクト: 通常のプロキシとは対照的に、完全なインターフェイスを実装する必要はありません。例えば、

public Object invoke(Object target, Method method, Object[] arguments) {
     if ("getValues".equals(method.getName()) {
         // check or transform parameters and/or return types, e.g., 
         return RangeUtils.validateResponse( method.invoke(obj, args) );
     }

     if ("getVersion".equals(method.getName()) {
         // another example with no delegation
         return 3;
     }
} 

一方、コントラクトには、完全なインターフェイスを実装する必要がなくなるという利点しかありません。繰り返しますが、プロキシされたメソッドをリファクタリングすると、動的プロキシが暗黙のうちに無効になります。

結論

ここで私が目にするのは、実際の使用例と疑わしい使用例の 1 つです。あなたの意見は何ですか?

4

3 に答える 3

13

あなたが説明したものを超えて、動的プロキシには多くの潜在的な用途があります-

  1. イベント発行 - メソッド x() で、透過的に y() を呼び出すか、メッセージ z を送信します。
  2. トランザクション管理 (データベース接続またはその他のトランザクション操作用)
  3. スレッド管理 - コストのかかる操作を透過的にスレッド化します。
  4. パフォーマンスの追跡 - たとえば、CountdownLatch によってチェックされるタイミング操作。
  5. 接続管理 - サービスのクライアントが操作を実行する前にセッションを開始する必要がある、Salesforce の Enterprise API のような API を考えてみてください。
  6. メソッド パラメータの変更 - null のデフォルト値を渡したい場合。

これらは、上記で説明した検証とログ記録に加えて、いくつかのオプションにすぎません。FWIW、Bean 検証仕様である JSR 303 には、Hibernate Validator に AOP スタイルの実装があるため、データ オブジェクトに対して特に実装する必要はありません。Spring フレームワークにはバリデーションも組み込まれており、ここで説明するいくつかの機能について AspectJ との統合が非常に優れています。

于 2010-09-12T20:46:47.933 に答える
11

実際、AOP はほとんどの動的プロキシにメリットをもたらします。これは、事前にわからないオブジェクトの周りに動的プロキシを作成できるためです。

動的プロキシのもう 1 つの便利な側面は、すべてのメソッドに同じ操作を適用する場合です。静的プロキシを使用すると、多くの重複したコードが必要になり (プロキシ化された各メソッドで、メソッドへの同じ呼び出しが必要になり、プロキシ化されたオブジェクトにデリゲートする必要があります)、動的プロキシはこれを最小限に抑えます。

また、Adapter と Decorator は別のパターンであることに注意してください。これらは (オブジェクト構成によって) 実装される方法ではプロキシ パターンに似ていますが、異なる目的を果たします。

  • デコレータ パターンを使用すると、複数の具体的なデコレータを使用できるため、実行時に機能を追加できます
  • アダプター パターンは、オブジェクトを一致しないインターフェイスに適合させることを目的としています。私が考えることができる最良の例は、インターフェイスEnumetationIteratorに適応します。EnumerationIterator
于 2010-09-12T18:51:44.113 に答える
0

私が考えることができるもう 1 つの使用例は、実行時にインターフェイスを動的に実装することです。これは、一部のフレームワークが機能する方法です。

たとえば、REST サービスを利用するための Java ライブラリであるRetrofitを考えてみましょう。REST API で使用可能な操作を反映する Java インターフェースを定義し、メソッドをアノテーションで装飾して、リクエストの詳細を構成します。この場合、インターフェースで定義されたすべてのメソッドが何らかのサーバーに対して HTTP 要求を実行し、メソッド引数を要求パラメーターに変換する必要があることは簡単にわかります。次に、メソッドの戻り値の型として定義された Java オブジェクトに応答を解析します。

于 2014-11-25T23:25:30.237 に答える