私は、我々は、動的なエージェントモデルには見知らぬ人ではないと信じて、ビジネスコードはほとんど関与していない場合でも、春のAopカット指向プログラミングは、プロキシモデル+リフレクションメカニズムの使用は、誰もが非常に明確なはずです!
では、駆け出しの頃にこのような疑問を持つことはありますか?
1. 生成されたプロキシ・クラスはどこにあり、どのように見えますか?
2、なぜ対象クラスはそのインターフェイスを実装しなければならないのですか?
3.InvocationHandlerインターフェイスを実装したinvokeメソッドはいつ実行されますか?
質問への回答の冒頭では、コードのjdkサンプル版に基づいて動的なプロキシを参照してください。ここでは2つのポイントですが、1つはInvocationHandlerインターフェイスの実装では、2つのメソッドを呼び出すProxy.newProxyInstance()メソッドを介してプロキシオブジェクトに返すことです。
package com.my.test.design.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyProxy implements InvocationHandler {
// プロキシされたオブジェクト
private Object obj;
// プロキシ・オブジェクトを返す
public Object bind (Object obj){
this.obj = obj;
// 質問2:この返されたプロキシ・オブジェクトはどこにあり、どのように見えるか?
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this);
}
// 質問2:このinvokeメソッドはいつ実行されるのか?
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin メソッドの実行を開始する");
Object object = method.invoke(obj,args);
System.out.println("end 実行メソッドの終了");
return object;
}
}
静的プロキシを覚えて、静的プロキシは、プロキシクラスとターゲットクラスは、同じインターフェイスを実装する必要がありますし、プロキシされているオブジェクトを紹介するプロキシクラスでは、ターゲットクラスにアクセスできるように、最初のプロキシクラスを介してプロキシクラスにアクセスし、ターゲットクラスにアクセスするために行くので、ターゲットクラスへのアクセスの制御を達成するため
実際には、動的プロキシ-クラスは、プロキシオブジェクトを作成する詳細jdkが行うのに役立つことを除いて、同じです。それだけでなく、動的プロキシの最大の利点は、プロキシするクラスを事前に知っているわけではありませんが、決定で渡すオブジェクトに基づいているということです。
このパラメータを main メソッドに追加すると、ローカル・プロキシ・オブジェクト・クラス・ファイル $Proxy0.class が生成されます。
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
生成されたファイルは、プロジェクト内のcomsun Proxyの下にあります。
以下は、$Proxy0.classファイルを逆コンパイルした結果です。
質問1:プロキシ・クラスはどこにあり、どのようなものですか?それがわかったところで
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
質問2:なぜターゲット・クラスはインタフェースを実装しているのか?デコンパイル後、プロキシ・クラスが見つかる$Proxy0はProxyクラスを継承しているからだ。
単一継承なので、インターフェイスを実装する必要がある。
public final class $Proxy0
extends Proxy
implements IBook
{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
{
// MyProxyはInvocationHandlerインタフェースを実装している。
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
質問3:プロキシ・クラスに実装されているインターフェースのinvokeメソッドはいつ実行されるか?
saleBookメソッドを呼び出すと、invokeメソッドが実行される。
public final void saleBook()
{
try
{
// this.hが親クラスのProxy InvocationHandlerのインスタンスであることはわかったが、サブクラスの本質は、$Proxy0.classに渡されたコンストラクタ・メソッドを通して、まだ彼ら自身のビジネス・クラスである。
// そして、invokeメソッドはメソッドの実装である。,
// m3 後ろのm3 = Class.forName("proxy.IBook").getMethod("saleBook", new Class[0]);
// メソッド内の本当のプロキシ・オブジェクトは
// まとめると、InvocationHandlerインターフェースのinvokeメソッドの実装は以下のようになる。
this.h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void buyBook()
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("proxy.IBook").getMethod("saleBook", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m4 = Class.forName("proxy.IBook").getMethod("buyBook", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
// this.hこのhは、親クラスProxy /のInvocationHandlerインスタンスである。**
* Constructs a new {@code Proxy} instance from a subclass
* (typically, a dynamic proxy class) with the specified value
* for its invocation handler.
*
* @param h the invocation handler for this proxy instance
*
* @throws NullPointerException if the given invocation handler, {@code h},
* is {@code null}.
*/
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}





