ホームページ Java &#&チュートリアル Java での動的プロキシの実装に関するチュートリアル

Java での動的プロキシの実装に関するチュートリアル

Jun 30, 2017 am 09:52 AM
invoke 質問

以下の内容は一部インターネット上の内容を元にしています。原作者様に感謝の意を表します。

Java での動的プロキシの実装の鍵は、Proxy と InvocationHandler の 2 つです。InvocationHandler インターフェイスの invoke メソッドから始めて、Java が動的プロキシを実装する方法を簡単に説明します。まず、Invoke メソッドの整合性は次のとおりです。 java コード

Public Object Invoke (Object Proxy, Method Method, Object [] ARGS)
Throws Throwable
Java での動的プロキシの実装に関するチュートリアル
{
  1. method.invoke(obj, args);

    return
  2. null;まず、Method が呼び出しメソッド、つまり実行する必要があるメソッドであると推測します。メソッドのパラメータ、プロキシ、このパラメータは何ですか?上記の invoke() メソッドの実装は比較的標準的な形式であり、ここでは proxy パラメーターが使用されていないことがわかります。次のように、JDK ドキュメントでプロキシの説明を参照してください。
  3. Java コード
  4. プロキシ インターフェイスの 1 つを介したプロキシ インスタンスのメソッド呼び出しは、次のようになります。プロキシ インスタンス、呼び出されたメソッドを識別する java.lang.reflect.Method オブジェクト、および引数を含む Object 型の配列を渡して、インスタンスの呼び出しハンドラーの invoke メソッドにディスパッチされます。 by このことから、上記の推測が正しいことがわかり、プロキシ パラメータがプロキシ クラスのインスタンスに渡されていることもわかります。

  5. 説明の便宜上、動的プロキシを実装する簡単な例を以下に示します。

public インターフェース Subject {

public
void request();
Java での動的プロキシの実装に関するチュートリアル




Javaコード

  1. //実際の役割: Subject の request() メソッドを実装しました

  2. public class RealSubject implements Subject{

  3. パブリック void request(){

  4. System.out.println("実際の主題から。");

  5. }

  6. }

Java コード
//実装された InvocationHandler

public Java での動的プロキシの実装に関するチュートリアルclass DynamicSubject implements In vocationHandler
  1. {

  2. プライベート オブジェクト obj;//これは動的プロキシの利点です。カプセル化されたオブジェクトはオブジェクト型であり、あらゆる種類のオブジェクトを受け入れます。 public DynamicSubject(オブジェクトオブジェクト)

    {
  3. this.obj = ob j;
  4. }

  5. // このメソッドは私たちが作ったものではありません

  6. を明示的に呼び出しますpublic Object invoke(オブジェクトプロキシ, メソッドメソッド, Object[] args)

    throws Throwable
  7. {

  8. System.out.println(

    "" + メソッドを呼び出す前);

    Method.invoke(obj, args); //-----> このステップの詳細については、次の記事を参照してください。各クラスのメソッドを読むと理解できます。 。
  9. System.out.println("呼び出し後" + メソッド);

  10. )

    1. //クライアント: プロキシインスタンスを生成し、 request() メソッドを呼び出しました

    2. public class Client {

    3. public static void main(String [ ] args) throws Throwable{

    4. Subject rs=new RealSubject();//ここにプロキシを指定します Class

    5. InvocationHandler ds=
    6. new DynamicSubject(rs); class<>

      インターフェース()、ds); /ここでは、サブジェクトが Proxy のインスタンスであることを実行結果を通じて証明できます。

    7. System.out .println(subject in​​stanceof Proxy);

    8. //ここで、この $Proxy0 クラスが Proxy を継承し、Subject インターフェースを実装していることがわかります。
    9. toString());

    10. System.out.print(

      "件名の属性は次のとおりです: "); () .getDeclaredFields();

    11. System.out.print("n"+" 件名のメソッドは次のとおりです: ") ().getDeclaredMethods( );

    12. System.out.println(

      "n"+"サブジェクトの親クラスは: "+subject.getClass().getSuperclass());

    13. システム。インターフェース=subject.getClass().getInterfaces();
    14. }

    15. System.out.println("nn"+"演算結果は次のとおりです: ");

    16. )
    17. 実行結果は次のとおりです: ここではパッケージ名は省略しています。 * **
    18. tru​​eの代わりに

subjectのClassクラスは次のとおりです: class $Proxy0 subjectの属性: m1、m3、m0、m2、
サブジェクト内のメソッド: request 、 hashCode、equals、toString、
subject の親クラス: class java.lang.reflect.Proxy

subject 実装インターフェイス: cn.edu.ustc.dynamicproxy.Subject、
Java での動的プロキシの実装に関するチュートリアル
実行結果は次のとおりです: public abstract void ***.Subject.request() を呼び出す前に
  1. From real subject.
  2. public abstract void ***.Subject.re Quest( ) を呼び出した後
  3. PS: この結果の情報は、少なくとも私にとっては非常に重要です。 。動的プロキシに関する私の混乱の根本的な原因は、私が上記の subject.request() を誤解していたことにあるため、少なくとも、前回の呼び出しで絡まったサブジェクトとプロキシの関係がわかりませんでした。 request() の は invoke() と接続されていますが、invoke はどのようにしてリクエストの存在を認識するのでしょうか。実際、上記の true とクラス $Proxy0 は、以下に示す $Proxy0 のソース コードと合わせて、動的プロキシに関する疑問を完全に解決できます。

  4. 上記のコードと結果からわかるように、invoke() メソッドを明示的に呼び出していませんが、このメソッドは実際に実行されました。プロセス全体を分析してみましょう:
  5. クライアントのコードから、突破口として newProxyInstance メソッドを使用できます。まず、Proxy クラスの newProxyInstance メソッドのソース コードを見てみましょう:
  6. Javaコード

  1. public static Object newProxyInstance(ClassLoader loader,

  2. Class>[] interfaces,

  3. InvocationHandler h )

  4. スロー IllegalArgumentException

  5. {

  6. if (h == null) {

  7. throw new NullPointerException();  

  8. }

  9. /*

  10. * 指定されたプロキシを検索または生成しますクラス。 

  11. */

  12. クラス cl = getProxyClass(loader, interfaces);  

  13. /*

  14. * 指定された 呼び出しハンドラーを使用して その コンストラクター を呼び出します。 

  15. */

  16. お試しください {

  17. /*

  18. * プロキシソースコード始まりにはこの定義があります:

  19. * private final static Class [] constructorParams = { InvocationHandler.class }; 

  20. * 短所は、InvocationHandler 型に参加する構築メソッド

  21. */

  22. コンストラクター cons = cl.getConstructor(constructorParams);  

  23. return (Object) cons.newInstance(new Object[] { h });  

  24. }

    catch (NoSuchMethodException e) {

  25. throw new InternalError(e.toString());  

  26. }

    catch (IllegalAccessException e) {

  27. throw new InternalError(e.toString());  

  28. }

    catch (InstantiationException e) {

  29. throw new InternalError(e.toString());  

  30. }

    catch (InvocationTargetException e) {

  31. throw new InternalError(e.toString());  

  32. }

  33. }



Proxy.newProxyInstance(ClassLoaderloader,Class>[]interfaces,InvocationHandler h) は以下のことを行います。
(1) パラメータローダーとインターフェイスの呼び出しメソッドに従ってgetProxyClass(loader,interfaces) は、プロキシ クラス $Proxy0 を作成します。$Proxy0 クラスは、interfaces インターフェイスを実装し、Proxy クラスを継承します (2) $Proxy0 をインスタンス化し、コンストラクターで DynamicSubject を渡し、$Proxy0 コンストラクターを呼び出します。親クラスの Proxy は、次のように h に値を割り当てます。
クラス プロキシ{
InvocationHandler h=
null;
protected Proxy(InvocationHandler h) {

Java での動的プロキシの実装に関するチュートリアル }
    ...
  1. }

  2. Proxy を継承する $Proxy0 のソース コードを見てみましょう。
  3. Javaコード

    1. public final class $Proxy0 extends Proxy implements Subject {

    2. private static Method m1;  

    3. private static メソッド m0;  

    4. private static メソッド m3;  

    5. private static メソッド m2;  

    6. 静的 {

    7. 試してみる {

    8. m1 = Class.forName("java.lang.Object").getMethod("equals",

    9. new Class[] { Class.forName("java.lang.Object") });  

    10. m0 = Class.forName("java.lang.Object").getMethod("hashCode",

    11. 新しい クラス[0]);  

    12. m3 = Class.forName("***.RealSubject").getMethod("request",

    13. 新しい クラス[0]);  

    14. m2 = Class.forName("java.lang.Object").getMethod("toString",

    15. 新しい クラス[0]);  

    16. } catch (NoSuchMethodException no suchmethodException) {

    17. throw new NoSuchMethodError(no suchmethodException.getMessage());  

    18. } catch (ClassNotFoundException classnotfoundException) {

    19. throw new NoClassDefFoundError(classnotfoundException.getMessage() );  

    20. }

    21. } //static

    22. public $Proxy0(InvocationHand) ler invocationhandler) {

    23. super(invocationhandler);  

    24. }

    25. @Override

    26. public final boolean equals(Object obj) {

    27. 試してください {

    28. return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();  

    29. } catch (Throwable スロー可能) {

    30. throw new UndeclaredThrowableException(throwable);  

    31. }

    32. }

    33. @オーバーライド

    34. public final int hashCode() {

    35. try {

    36. return ((Integer) super.h.invoke(this, m0, null)).intValue();  

    37. } catch (Throwable スロー可能) {

    38. throw new UndeclaredThrowableException(throwable);  

    39. }

    40. }

    41. public final void request() {

    42. 試してください {

    43. super.h。 invoke(this, m3, null);  

    44. 戻る;  

    45. } catch (エラーe) {

    46. } catch (Throwable throwable) {

    47. throw new UndeclaredThrowableException(throwable);  

    48. }

    49. }

    50. @オーバーライド

    51. public final String toString() {

    52. try {

    53. return (String) super.h.invoke(this, m2, null);  

    54. } catch (Throwable スロー可能) {

    55. throw new UndeclaredThrowableException(throwable);  

    56. }

    57. }

    58. }



次に、取得した $Proxy0 インスタンスを Subject にキャストし、subject への参照を割り当てます。 subject.request() メソッドが実行されると、$Proxy0 クラスの request() メソッドが呼び出され、次に親クラス Proxy の h の invoke() メソッド、つまり InvocationHandler.invoke() が呼び出されます。

追記: 1. 説明する必要があるのは、Proxy クラスの getProxyClass メソッドが Proxy Class クラスを返すということです。なぜこんなことを説明したかというと、最初に私が返ってきたものを「代理クラスのクラス」だと思ってしまうというレベルの低い間違いを犯したからです――! getProxyClass のソース コードを確認することをお勧めします。これは非常に長いです。 =
2. $Proxy0 のソース コードから、動的プロキシ クラスは、明示的に定義されたインターフェイス内のメソッドをプロキシするだけでなく、Java ルート クラス オブジェクト内の継承されたquals() および hashcode() もプロキシすることがわかります。 . 、toString()、およびこれら 3 つのメソッドのみです。

Q: これまでのところ、invoke メソッドの最初のパラメータは Proxy のインスタンス (正確には $Proxy0 のインスタンスが使用されます) ですが、その用途は何ですか?言い換えれば、プログラムはどのように効果を発揮するのでしょうか?
A: 私の現在のレベルでは、このプロキシ パラメーターは動的プロキシ メカニズム全体で効果がありません。InvocationHandler の呼び出しメソッドのプロキシ パラメーターは使用されません。渡されるパラメータは、実際にはプロキシ クラスのインスタンスです。おそらくプログラマが invoke メソッドでリフレクションを使用してプロキシ クラスに関する情報を取得できるようにするためだと思います。

以上がJava での動的プロキシの実装に関するチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

C++ コードで発生する「エラー: クラス 'ClassName' の再定義」問題を解決する C++ コードで発生する「エラー: クラス 'ClassName' の再定義」問題を解決する Aug 25, 2023 pm 06:01 PM

C++ コードの「error:redefiningofclass'ClassName'」問題を解決する C++ プログラミングでは、さまざまなコンパイル エラーが頻繁に発生します。よくあるエラーの 1 つは、「error:redefiningofclass 'ClassName'」 (クラス 'ClassName' の再定義エラー) です。このエラーは通常、同じクラスが複数回定義されている場合に発生します。この記事では、

クラスタリングアルゴリズムにおけるクラスタリング効果評価問題 クラスタリングアルゴリズムにおけるクラスタリング効果評価問題 Oct 10, 2023 pm 01:12 PM

クラスタリング アルゴリズムのクラスタリング効果評価問題には、特定のコード例が必要です クラスタリングは、データをクラスタリングすることによって、類似したサンプルを 1 つのカテゴリにグループ化する教師なし学習手法です。クラスタリングアルゴリズムでは、クラスタリングの効果をどのように評価するかが重要な問題となります。この記事では、一般的に使用されるいくつかのクラスタリング効果評価指標を紹介し、対応するコード例を示します。 1. クラスタリング効果評価指標 シルエット係数 シルエット係数は、サンプルの近さや他のクラスタとの分離度を計算することでクラスタリング効果を評価します。

Windows 10 で Steam をダウンロードできない場合はどうすればよいですか? Windows 10 で Steam をダウンロードできない場合はどうすればよいですか? Jul 07, 2023 pm 01:37 PM

Steam は高品質のゲームが数多くある非常に人気のあるゲーム プラットフォームですが、一部の Win10 ユーザーが Steam をダウンロードできないと報告しています。何が起こっているのでしょうか?ユーザーの IPv4 サーバー アドレスが正しく設定されていない可能性があります。この問題を解決するには、Steam を互換モードでインストールし、DNS サーバーを手動で 114.114.114.114 に変更すると、後でダウンロードできるようになります。 Win10 で Steam をダウンロードできない場合の対処法: Win10 では、互換モードでインストールを試みることができます。更新後、互換モードをオフにする必要があります。オフにしないと、Web ページが読み込まれません。プログラム インストールのプロパティをクリックして、互換モードでプログラムを実行します。再起動してメモリと電力を増やす

iPhone の一般的な問題を診断する方法を教えます iPhone の一般的な問題を診断する方法を教えます Dec 03, 2023 am 08:15 AM

強力なパフォーマンスと多彩な機能で知られる iPhone は、複雑な電子機器によく見られる、時折起こる問題や技術的な困難を免れません。 iPhone の問題が発生するとイライラすることもありますが、通常は警報を発する必要はありません。この包括的なガイドでは、iPhone の使用に関連して最も一般的に遭遇する課題のいくつかをわかりやすく説明することを目的としています。当社の段階的なアプローチは、これらの一般的な問題の解決に役立つように設計されており、機器を最高の動作状態に戻すための実用的な解決策とトラブルシューティングのヒントを提供します。不具合やより複雑な問題に直面している場合でも、この記事はそれらを効果的に解決するのに役立ちます。一般的なトラブルシューティングのヒント 具体的なトラブルシューティング手順を詳しく説明する前に、役立つ情報をいくつか紹介します。

PHP エラーの解決: 親クラスの継承時に問題が発生しました PHP エラーの解決: 親クラスの継承時に問題が発生しました Aug 17, 2023 pm 01:33 PM

PHP エラーの解決: 親クラスの継承時に発生する問題 PHP では、継承はオブジェクト指向プログラミングの重要な機能です。継承により、元のコードを変更することなく、既存のコードを再利用し、拡張および改善できます。継承は開発で広く使用されていますが、親クラスから継承するときにエラーの問題が発生することがあります。この記事では、親クラスから継承するときに発生する一般的な問題の解決に焦点を当て、対応するコード例を示します。質問 1: 親クラスが見つかりません。親クラスの継承処理中に、システムが親クラスを見つからない場合、

jQueryがform要素の値を取得できない問題の解決方法 jQueryがform要素の値を取得できない問題の解決方法 Feb 19, 2024 pm 02:01 PM

jQuery.val() が使用できない問題を解決するには、具体的なコード例が必要です フロントエンド開発者にとって、jQuery の使用は一般的な操作の 1 つです。その中でも、.val() メソッドを使用してフォーム要素の値を取得または設定する操作は、非常に一般的な操作です。ただし、特定のケースでは、.val() メソッドを使用できないという問題が発生する可能性があります。この記事では、いくつかの一般的な状況と解決策を紹介し、具体的なコード例を示します。問題の説明 jQuery を使用してフロントエンド ページを開発する場合、時々次のような問題が発生します。

弱教師学習におけるラベル取得問題 弱教師学習におけるラベル取得問題 Oct 08, 2023 am 09:18 AM

弱教師あり学習におけるラベル取得問題には、特定のコード例が必要です はじめに: 弱教師あり学習は、トレーニングに弱いラベルを使用する機械学習手法です。従来の教師あり学習とは異なり、弱教師あり学習では、各サンプルに正確なラベルが必要ではなく、より少ないラベルを使用してモデルをトレーニングするだけで済みます。しかし、弱教師あり学習では、弱いラベルから有用な情報をいかに正確に取得するかが重要な問題となります。この記事では、弱教師あり学習におけるラベル取得問題を紹介し、具体的なコード例を示します。弱教師学習におけるラベル獲得問題の紹介:

Linux システムで頻繁に発生するサーバー負荷の問題に対処する方法 Linux システムで頻繁に発生するサーバー負荷の問題に対処する方法 Jun 29, 2023 pm 11:56 PM

Linux システムで頻繁に発生する高サーバー負荷の問題に対処する方法 概要: この記事では、Linux システムで頻繁に発生する高サーバー負荷の問題に対処する方法を紹介します。システム構成の最適化、サービス リソース割り当ての調整、問題のあるプロセスの検出、およびパフォーマンス チューニングの実行により、負荷を効果的に軽減し、サーバーのパフォーマンスと安定性を向上させることができます。 1. はじめに 過剰なサーバー負荷は、Linux システムでよく見られる問題の 1 つであり、サーバーの動作が遅くなったり、応答が遅れたり、さらには正常に動作しなくなる可能性があります。この問題に直面した私は、

See all articles