プロキシ モードは、プロキシ オブジェクトを使用してユーザーのリクエストを完了し、ユーザーが実際のオブジェクトにアクセスするのを防ぎます。
プロキシ モードには多くの用途があります。たとえば、セキュリティ上の理由から、クライアントが実際のオブジェクトに直接アクセスできないようにする必要がある場合や、リモート呼び出しで技術的な詳細を処理するためにプロキシ オブジェクトを使用する必要がある場合などです。リモートメソッド; またはシステムを改善するために、実際のオブジェクトがカプセル化され、それによって遅延読み込みの目的が達成されます。
システムの起動時に、プロキシ モードを使用して最も多くのリソースを消費するメソッドを分離すると、システムの起動が高速化され、ユーザーの待ち時間が短縮されます。ユーザーが実際にクエリを作成すると、プロキシ クラスは実際のクラスをロードしてユーザーのリクエストを完了します。これが、プロキシ モードを使用して遅延読み込みを実現する目的です。
1. 静的プロキシの実装:
テーマインターフェイス:
public interface IDBQuery { String request(); }
実際のテーマ:
public class DBQuery implements IDBQuery { public DBQuery(){ try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } } public String request() { return "string request"; } }
エージェントクラス:
public class IDBQueryProxy implements IDBQuery { private DBQuery dbquery; public String request() { if(dbquery==null) dbquery = new DBQuery(); return dbquery.request(); } }
最後に、メイン関数:
public class ProxyText { public static void main(String[] args) { IDBQuery dbquery = new IDBQueryProxy(); System.out.println(dbquery.request()); } }
静的プロキシ 注、プロキシ クラス実クラスは共通インターフェイスを実装し、プロキシ クラスは実クラス オブジェクトを参照し、時間のかかる操作はプロキシ クラスのメソッドで実装されます。
ダイナミック プロキシ:
ダイナミック プロキシは、プロキシ クラスを動的に生成するランタイムです。つまり、プロキシ クラスのバイトコードが生成され、実行時に現在のクラスローダーにロードされます。静的プロキシと比較して、動的プロキシは、実際に注目するために完全に同一のカプセル化クラスをカプセル化する必要はありません。対象となるインターフェイスが多数ある場合、インターフェイスごとにプロキシ メソッドを記述するのは非常に面倒です。エージェント クラスとエージェント クラスを変更する必要がありますが、これはシステムのメンテナンスには役立ちません。第 2 に、いくつかの動的エージェント生成メソッドを使用すると、実行時にエージェント クラスの実行ロジックを指定することもできるため、システムの柔軟性が大幅に向上します。
テーマインターフェース:
public interface IDBQuery { String request(); }
jdkプロキシクラス:
public class JdbDbqueryHandler implements InvocationHandler{ IDBQuery idbquery = null; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(idbquery==null){ idbquery = new DBQuery(); } return idbquery.request(); } public static IDBQuery createJdbProxy(){ IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdbDbqueryHandler()); System.out.println("JdbDbqueryHandler.createJdbProxy()"); return jdkProxy; } }
メイン関数:
public class ProxyText { public static void main(String[] args) { IDBQuery idbQuery = JdbDbqueryHandler.createJdbProxy(); System.out.println(idbQuery.request()); } }
さらに、CGLIBとjavassistを使用することもできます動的プロキシはjdk動的プロキシに似ていますが、作成プロセスはこの組み込み実装の Differentiatedclass() メソッドはネイティブ実装として定義されているため、他のメソッドよりもパフォーマンスが優れています。プロキシ クラスの関数呼び出しに関しては、JDK の動的プロキシは CGLIB や javassist 動的プロキシほど良くはなく、javassist 動的プロキシのパフォーマンス品質は最悪で、JDK の実装よりも劣っています。実際の開発アプリケーションでは、プロキシ クラスのメソッド呼び出し頻度が実際のプロキシ クラスの生成頻度よりもはるかに高いため、動的プロキシのメソッド呼び出しパフォーマンスがパフォーマンスの懸念事項となります。 JDK 動的プロキシは、プロキシ クラスと実際のテーマに統一インターフェイスの実装を強制しますが、javassist 動的プロキシにはそのような要件はありません。
Java では、動的プロキシの実装にはクラスローダーの使用が含まれます。CGLIB を例として、動的クラスの読み込みプロセスについて簡単に説明します。 CGLIB を使用して動的プロキシを生成するには、まず Enhancer クラスのインスタンスを生成し、プロキシ サービスを処理するためのコールバック クラスを作成する必要があります。 Enhancer.create() メソッドでは、DefaultGeneratorStrategy.Generate() メソッドを使用してプロキシ クラスのバイトコードを生成し、それをバイト配列に保存します。次に、reflectUtils.defineClass() メソッドを呼び出し、リフレクションを通じて ClassLoader.defineClass() メソッドを呼び出してバイトコードをクラスローダーにロードし、クラスのロードを完了します。最後に、reflectUtils.newInstance() メソッドを通じて、リフレクションを通じて動的クラス インスタンスが生成され、そのインスタンスが返されます。その他のプロセスの詳細は異なりますが、生成ロジックは同じです。
以上がこの記事の全内容です、皆様の学習のお役に立てれば幸いです。
Java 設計最適化のプロキシ モードに関連するその他の記事については、PHP 中国語 Web サイトに注目してください。