この記事では主に Java プロキシ メカニズムの詳細な解釈を紹介します。必要な方はぜひ参考にしてください。
動的プロキシは実際には、指定したすべてのインターフェイスに基づいてクラス バイトを動的に生成する java.lang.reflect.Proxy クラスです。このクラスは Proxy クラスを継承し、指定したすべてのインターフェイス (パラメータ)配列); 次に、指定したクラスローダーを使用してクラスバイトをシステムにロードし、最後にそのようなクラスのオブジェクトを生成し、対応するメソッドメンバーである invocationHandler などのオブジェクトのいくつかの値を初期化します。すべてのインターフェースに。 初期化後、オブジェクトは呼び出し元のクライアントに返されます。このようにして、クライアントはすべてのインターフェイスを実装する Proxy オブジェクトを取得します。分析例を参照してください:
1. ビジネスインターフェースクラス
public interface BusinessProcessor { public void processBusiness(); }
2. ビジネス実装クラス
public class BusinessProcessorImpl implements BusinessProcessor { public void processBusiness() { System.out.println("processing business....."); } }
3. ビジネスエージェントクラス
4 人の顧客 アプリケーション クラスの終了
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class BusinessProcessorHandler implements InvocationHandler { private Object target = null; BusinessProcessorHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("You can do something here before process your business"); Object result = method.invoke(target, args); System.out.println("You can do something here after process your business"); return result; } }
次に、印刷結果を見てみましょう:
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); } }
結果を通して、プロキシの役割を簡単に確認できます。コア ビジネス メソッドの後に、ロギングやセキュリティ メカニズムなど、実行したい補助的な作業を追加します。
それでは、上記のクラスがどのように動作するかを分析してみましょう。
カテゴリー 1 と 2 については特に言うことはありません。まずはカテゴリー 3 を見てみましょう。 InvocationHandlerインターフェースのinvokeメソッドを実装します。実際、このクラスは、プロキシによって最終的に呼び出される固定インターフェイス メソッドです。プロキシは、クライアントのビジネス メソッドがどのように実装されているかは関係ありません。クライアントが Proxy を呼び出すときは、InvocationHandler の invoke インターフェイスのみを呼び出すため、実際に実装されたメソッドは invoke メソッドで呼び出す必要があります。関係は次のとおりです:
You can do something here before process your business processing business..... You can do something here after process your business
それでは、bp はどのようなオブジェクトですか? main メソッドを変更して見てみましょう:
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....); bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();
出力結果:
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); }
bp は $Proxy0 クラスのオブジェクトであることがわかります。それで、このクラスはどのようなものですか?わかりましたこのクラスを出力するメソッドをさらに 2 つ書いて、3 つの頭と 6 本の腕がどのようなものか見てみましょう。 main の下に次の 2 つの静的メソッドを記述します。
You can do something here before process your business processing business..... You can do something here after process your business $Proxy0
main メソッドを書き換えます
public static String getModifier(int modifier){ String result = ""; switch(modifier){ case Modifier.PRIVATE: result = "private"; case Modifier.PUBLIC: result = "public"; case Modifier.PROTECTED: result = "protected"; case Modifier.ABSTRACT : result = "abstract"; case Modifier.FINAL : result = "final"; case Modifier.NATIVE : result = "native"; case Modifier.STATIC : result = "static"; case Modifier.SYNCHRONIZED : result = "synchronized"; case Modifier.STRICT : result = "strict"; case Modifier.TRANSIENT : result = "transient"; case Modifier.VOLATILE : result = "volatile"; case Modifier.INTERFACE : result = "interface"; } return result; } public static void printClassDefinition(Class clz){ String clzModifier = getModifier(clz.getModifiers()); if(clzModifier!=null && !clzModifier.equals("")){ clzModifier = clzModifier + " "; } String superClz = clz.getSuperclass().getName(); if(superClz!=null && !superClz.equals("")){ superClz = "extends " + superClz; } Class[] interfaces = clz.getInterfaces(); String inters = ""; for(int i=0; i<interfaces.length; i++){ if(i==0){ inters += "implements "; } inters += interfaces[i].getName(); } System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters ); System.out.println("{"); Field[] fields = clz.getDeclaredFields(); for(int i=0; i<fields.length; i++){ String modifier = getModifier(fields[i].getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String fieldName = fields[i].getName(); String fieldType = fields[i].getType().getName(); System.out.println(" "+modifier + fieldType + " "+ fieldName + ";"); } System.out.println(); Method[] methods = clz.getDeclaredMethods(); for(int i=0; i<methods.length; i++){ Method method = methods[i]; String modifier = getModifier(method.getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String methodName = method.getName(); Class returnClz = method.getReturnType(); String retrunType = returnClz.getName(); Class[] clzs = method.getParameterTypes(); String paraList = "("; for(int j=0; j<clzs.length; j++){ paraList += clzs[j].getName(); if(j != clzs.length -1 ){ paraList += ", "; } } paraList += ")"; clzs = method.getExceptionTypes(); String exceptions = ""; for(int j=0; j<clzs.length; j++){ if(j==0){ exceptions += "throws "; } exceptions += clzs[j].getName(); if(j != clzs.length -1 ){ exceptions += ", "; } } exceptions += ";"; String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions; System.out.println(" "+methodPrototype ); } System.out.println("}"); }
次に、出力を見てみましょう:
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); Class clz = bp.getClass(); printClassDefinition(clz); }
明らかに、Proxy.newProxyInstance メソッドは次のことを行います。
1.渡された 2 番目のパラメーター インターフェイスに基づいてクラスを動的に生成し、インターフェイスにインターフェイスを実装します。この例では、BusinessProcessor インターフェイスの processBusiness メソッドです。そしてProxyクラスを継承し、hashcode、toString、equalsの3つのメソッドを書き換えます。具体的な実装については、ProxyGenerator.generateProxyClass(...); を参照してください。 この例では、$Proxy0 クラス
2 が生成され、最初のパラメーターで渡されたクラスローダーを通じて新しく生成されたクラスが jvm にロードされます。 $Proxy0 クラス
3 をロードしようとしています。3 番目のパラメーターを使用して $Proxy0 の $Proxy0 (InvocationHandler) コンストラクターを呼び出して $Proxy0 のオブジェクトを作成し、interfaces パラメーターを使用してそのすべてのインターフェイスのメソッドを走査します。そしてメソッドオブジェクト初期化オブジェクトを生成します。いくつかのメソッドメンバー変数
4は$Proxy0のインスタンスをクライアントに返します。
もう大丈夫です。クライアントがそれをどのように調整するかを見てみましょう。そうすれば明らかになるでしょう。
1. クライアントが取得するのは$Proxy0のインスタンスオブジェクトです。$Proxy0はBusinessProcessorを継承しているため、BusinessProcessorに変換しても問題ありません。
You can do something here before process your business processing business..... You can do something here after process your business $Proxy0 $Proxy0 extends java.lang.reflect.Proxy implements com.tom.proxy.dynamic.BusinessProcessor { java.lang.reflect.Method m4; java.lang.reflect.Method m2; java.lang.reflect.Method m0; java.lang.reflect.Method m3; java.lang.reflect.Method m1; void processBusiness(); int hashCode(); boolean equals(java.lang.Object); java.lang.String toString(); }2, bp.processBusiness();
まとめ
以上がJava の Proxy メカニズムの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。