黒馬プログラマーのダイナミックエージェントの深入浅出
3707 ワード
--------androidトレーニング、JAvaトレーニング、交流を楽しみにしています!--------
インタフェースHelloにsayHello()の方法があるとします
実装クラスHelloImplと
私たちは今、sayHello()メソッドの実行前に何かをし、sayHello()メソッドの実行後に何かをする必要があります.開放閉鎖の原則によって元のクラスを変えることはできません.どうすればいいですか.
この時、私たちのダイナミックエージェントが登場する番です!
まず、動的エージェントに関連する2つのクラスについて説明します.
1.interface InvocationHandler
Object invoke(Object proxy,Method,Object[]args)メソッドは1つしかありません
パラメータリストから、このクラスがエージェントを必要とするクラスのメソッドを伝達するメソッドオブジェクトmethodが表示され、このオブジェクトによってエージェントを必要とするクラスのメソッドを呼び出すことができ、argsはこのメソッドのパラメータである.つまり、このインタフェースは、Proxyエージェントクラス呼び出しのための統一されたエントリを定義します.このインタフェースの異なる実装によって異なる付加機能を達成し,これが多態の体現である.
2.class Proxyは本当に動的エージェントのクラスを表し、2つの静的メソッドを提供します:ClassgetProxyClass(ClassLoader loader,Class[]interface)はエージェントクラスを生成するために使用され、パラメータはinterface配列を提供し、これらのinterfaceの「仮想実装」を生成し、実際のオブジェクトを偽るために使用されます.このエージェントクラスは、返されたClassタイプから、伝達されたパラメータに基づいて動的に生成されるので、動的エージェントと呼ばれます.Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)はエージェントオブジェクトを生成し、InvocationHandlerパラメータ(InvocationHandlerインタフェースの実装クラスのみ)が多くなり、エージェントオブジェクトに関連付けられ、リクエストがエージェントに配布されるとh.invoke(...)が自動的に実行されます.方法、invokeの方法は私たちがNの多くのことをする場所(^o^)/~です.伝達されたInvocationHandlerインタフェースのインプリメンテーションに従って、動的エージェントクラスのインスタンスが生成される.
--------------------------------------憎らしい分割線O(∩∩)O~----------------------------------------------------
以上説明したように,まずInvocationHandlerインタフェースの実装を生成して我々の機能を完成させ,bind()メソッドではこのInvocationHandlerインタフェースを実装したオブジェクトに基づいて生成された動的エージェントクラスの例を返す.
最後にコードをテストします
実行結果
質問?ダイナミックエージェントはインタフェースのすべての方法に統一的に指定された機能を加えて、細粒度の制御を行うことができますか?例えば、指定された機能を加える方法もあれば、変わらない方法もありますか?あるいは、方法ごとに機能が異なることができますか?これも静的エージェントでしか実現できないと思います.
インタフェースHelloにsayHello()の方法があるとします
public interface Hello {
public void sayHello();
}
実装クラスHelloImplと
public class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("Hello");
}
}
私たちは今、sayHello()メソッドの実行前に何かをし、sayHello()メソッドの実行後に何かをする必要があります.開放閉鎖の原則によって元のクラスを変えることはできません.どうすればいいですか.
この時、私たちのダイナミックエージェントが登場する番です!
まず、動的エージェントに関連する2つのクラスについて説明します.
1.interface InvocationHandler
Object invoke(Object proxy,Method,Object[]args)メソッドは1つしかありません
パラメータリストから、このクラスがエージェントを必要とするクラスのメソッドを伝達するメソッドオブジェクトmethodが表示され、このオブジェクトによってエージェントを必要とするクラスのメソッドを呼び出すことができ、argsはこのメソッドのパラメータである.つまり、このインタフェースは、Proxyエージェントクラス呼び出しのための統一されたエントリを定義します.このインタフェースの異なる実装によって異なる付加機能を達成し,これが多態の体現である.
2.class Proxyは本当に動的エージェントのクラスを表し、2つの静的メソッドを提供します:ClassgetProxyClass(ClassLoader loader,Class[]interface)はエージェントクラスを生成するために使用され、パラメータはinterface配列を提供し、これらのinterfaceの「仮想実装」を生成し、実際のオブジェクトを偽るために使用されます.このエージェントクラスは、返されたClassタイプから、伝達されたパラメータに基づいて動的に生成されるので、動的エージェントと呼ばれます.Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)はエージェントオブジェクトを生成し、InvocationHandlerパラメータ(InvocationHandlerインタフェースの実装クラスのみ)が多くなり、エージェントオブジェクトに関連付けられ、リクエストがエージェントに配布されるとh.invoke(...)が自動的に実行されます.方法、invokeの方法は私たちがNの多くのことをする場所(^o^)/~です.伝達されたInvocationHandlerインタフェースのインプリメンテーションに従って、動的エージェントクラスのインスタンスが生成される.
--------------------------------------憎らしい分割線O(∩∩)O~----------------------------------------------------
以上説明したように,まずInvocationHandlerインタフェースの実装を生成して我々の機能を完成させ,bind()メソッドではこのInvocationHandlerインタフェースを実装したオブジェクトに基づいて生成された動的エージェントクラスの例を返す.
public class myHandler implements InvocationHandler {
private Object target;
/**
*
*
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
before();
result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("before....");
}
private void after() {
System.out.println("after....");
}
}
最後にコードをテストします
public class ProxyTest {
public static void main(String[] args) {
//
//
MyHandler my = new MyHandler();
//
//
Hello hello = (Hello)my.bind(new HelloImpl());
//
//
hello.sayHello();
}
}
実行結果
before....
Hello
after....
質問?ダイナミックエージェントはインタフェースのすべての方法に統一的に指定された機能を加えて、細粒度の制御を行うことができますか?例えば、指定された機能を加える方法もあれば、変わらない方法もありますか?あるいは、方法ごとに機能が異なることができますか?これも静的エージェントでしか実現できないと思います.