Java での動的プロキシの実装に関するチュートリアル
以下の内容は一部インターネット上の内容を元にしています。原作者様に感謝の意を表します。
Java での動的プロキシの実装の鍵は、Proxy と InvocationHandler の 2 つです。InvocationHandler インターフェイスの invoke メソッドから始めて、Java が動的プロキシを実装する方法を簡単に説明します。まず、Invoke メソッドの整合性は次のとおりです。 java コード
-
method.invoke(obj, args);
return null;まず、Method が呼び出しメソッド、つまり実行する必要があるメソッドであると推測します。メソッドのパラメータ、プロキシ、このパラメータは何ですか?上記の invoke() メソッドの実装は比較的標準的な形式であり、ここでは proxy パラメーターが使用されていないことがわかります。次のように、JDK ドキュメントでプロキシの説明を参照してください。 - Java コード
-
プロキシ インターフェイスの 1 つを介したプロキシ インスタンスのメソッド呼び出しは、次のようになります。プロキシ インスタンス、呼び出されたメソッドを識別する java.lang.reflect.Method オブジェクト、および引数を含む Object 型の配列を渡して、インスタンスの呼び出しハンドラーの invoke メソッドにディスパッチされます。 by このことから、上記の推測が正しいことがわかり、プロキシ パラメータがプロキシ クラスのインスタンスに渡されていることもわかります。
- 説明の便宜上、動的プロキシを実装する簡単な例を以下に示します。
public インターフェース Subject {
//実際の役割: Subject の request() メソッドを実装しました public class RealSubject implements Subject{ パブリック void request(){ System.out.println("実際の主題から。"); } } Java コード { プライベート オブジェクト obj;//これは動的プロキシの利点です。カプセル化されたオブジェクトはオブジェクト型であり、あらゆる種類のオブジェクトを受け入れます。 public DynamicSubject(オブジェクトオブジェクト) } // このメソッドは私たちが作ったものではありません を明示的に呼び出しますpublic Object invoke(オブジェクトプロキシ, メソッドメソッド, Object[] args) "" + メソッドを呼び出す前); System.out.println("呼び出し後" + メソッド); ) //クライアント: プロキシインスタンスを生成し、 request() メソッドを呼び出しました public class Client { public static void main(String [ ] args) throws Throwable{ Subject rs=new RealSubject();//ここにプロキシを指定します Class インターフェース()、ds); /ここでは、サブジェクトが Proxy のインスタンスであることを実行結果を通じて証明できます。 System.out .println(subject instanceof Proxy); toString()); "件名の属性は次のとおりです: "); () .getDeclaredFields(); System.out.print("n"+" 件名のメソッドは次のとおりです: ") ().getDeclaredMethods( ); "n"+"サブジェクトの親クラスは: "+subject.getClass().getSuperclass()); } System.out.println("nn"+"演算結果は次のとおりです: "); subjectのClassクラスは次のとおりです: class $Proxy0 subjectの属性: m1、m3、m0、m2、 public static Object newProxyInstance(ClassLoader loader, スロー IllegalArgumentException if (h == null) { throw new NullPointerException(); /* * 指定されたプロキシを検索または生成しますクラス。 */ /* * 指定された 呼び出しハンドラーを使用して その コンストラクター を呼び出します。 */ お試しください { /* * プロキシソースコード始まりにはこの定義があります: * private final static Class [] constructorParams = { InvocationHandler.class }; * 短所は、InvocationHandler 型に参加する構築メソッド */ return (Object) cons.newInstance(new Object[] { h }); catch (NoSuchMethodException e) { throw new InternalError(e.toString()); catch (IllegalAccessException e) { throw new InternalError(e.toString()); catch (InstantiationException e) { throw new InternalError(e.toString()); catch (InvocationTargetException e) { throw new InternalError(e.toString()); } Proxy を継承する $Proxy0 のソース コードを見てみましょう。 Javaコード public final class $Proxy0 extends Proxy implements Subject { private static Method m1; private static メソッド m0; private static メソッド m3; private static メソッド m2; 静的 { 試してみる { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", 新しい クラス[0]); m3 = Class.forName("***.RealSubject").getMethod("request", 新しい クラス[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", 新しい クラス[0]); } catch (NoSuchMethodException no suchmethodException) { throw new NoSuchMethodError(no suchmethodException.getMessage()); } catch (ClassNotFoundException classnotfoundException) { throw new NoClassDefFoundError(classnotfoundException.getMessage() ); } } //static public $Proxy0(InvocationHand) ler invocationhandler) { super(invocationhandler); } @Override public final boolean equals(Object obj) { 試してください { return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue(); } catch (Throwable スロー可能) { throw new UndeclaredThrowableException(throwable); } } @オーバーライド public final int hashCode() { try { return ((Integer) super.h.invoke(this, m0, null)).intValue(); } catch (Throwable スロー可能) { throw new UndeclaredThrowableException(throwable); } } public final void request() { 試してください { super.h。 invoke(this, m3, null); 戻る; } catch (エラーe) { } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } @オーバーライド public final String toString() { try { return (String) super.h.invoke(this, m2, null); } catch (Throwable スロー可能) { throw new UndeclaredThrowableException(throwable); } } }
Javaコード
//実装された InvocationHandler
サブジェクト内のメソッド: request 、 hashCode、equals、toString、subject の親クラス: class java.lang.reflect.Proxy
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) { ...
次に、取得した $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 サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック









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

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

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

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

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

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

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

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