動的エージェントおよびエージェント・モード

5856 ワード

1.動的エージェントとは
動的エージェントについては、まずJDKの言葉を引用します.
動的エージェントクラス(以下、エージェントクラスと略称する)は、クラスの作成時に実行時に指定されたインタフェースリストを実装するクラスであり、以下に説明する動作を有する.エージェントインタフェースは、エージェントクラスが実装するインタフェースです.プロキシインスタンスは、プロキシクラスのインスタンスです.各エージェントインスタンスには、インタフェースInvocationHandlerを実装できる関連する呼び出しハンドラオブジェクトがある.1つのプロキシインタフェースのプロキシインスタンス上の方法によって、インスタンスに割り当てられる呼び出しハンドラのInvokeメソッドが呼び出され、プロキシインスタンス、呼び出しメソッドを識別するjava.lang.reflect.Methodオブジェクト、およびパラメータを含むObjectタイプの配列が渡される.呼び出しハンドラは、符号化されたメソッド呼び出しを適切に処理し、その返された結果は、プロキシインスタンス上のメソッド呼び出しの結果として返される.
上の一節を見て、動的エージェントとは何か知っているでしょう.わからなかった?大丈夫、正直に言うと、私も分かりません.上の話を半分見ても見られません.本当にこの辛抱強く見ていません.しかし、隣に例があります.
     InvocationHandler handler = new MyInvocationHandler(...);
        Class proxyClass = Proxy.getProxyClass(
            Foo.class.getClassLoader(), new Class[] { Foo.class });
        Foo f = (Foo) proxyClass.
            getConstructor(new Class[] { InvocationHandler.class }).
            newInstance(new Object[] { handler });

一連の方法によって,最終的にFooのインスタンスが作成されたことがわかる. 
ではMyInvocationHandlerとは何でしょうか?jdkで述べたように,invoke(Object proxy,Method method,Object[]args)メソッドを持つInvocationHandlerインタフェースを実現した.すなわち,反射によりFooインタフェースのインスタンスを呼び出す具体的な実装方法である.具体的な呼び出しは、invokeの中で発生したに違いない.
ここで分かるように、動的エージェントは、実行中に変更できる他のオブジェクトへのアクセスを制御するために動的なエージェントを提供することです.すなわち,実行中にFooのインスタンス,さらにはFooのこのインタフェースを変更できるのは,動的エージェントと呼ばれる理由である.本当に具体的な応用とは関係なく、抽象的です.
2.動的エージェントの役割
ダイナミックエージェントとは何か知っていますが、何の役割がありますか?
JDKを見ると、ProxyというクラスはJDK 1から来ていることがわかります.3は最初からあって、どうしてこの类を设计して、私はやはり理解したくなくて、ネット上でも探し当てていませんが、もしあの人达の思惟は私达が理解することができるならば、それでは私达もjdkを设计することができます.
では、動的エージェントをどのような状況で使用できるかを自分で考えてみましょう.明らかに、ローカルコードでは、各インタフェースの実装と参照を動的エージェントに変更するのに苦労することはありません.それは見苦しいし、理解しにくいし、メンテナンスも容易ではありませんが、フレームワークを設計している場合、実行中にその表現を動的に変更できるフレームワークはありますか.
また、リモートコール(RMI)がある場合は、remoteobjのクラスを統合し、独自のインタフェースを実現する必要があります.
public class RemoteTest extends RemoteObject implements Foo
{
    Foo f;
    public RemoteTest(Foo f)
    {
        this.f = f;
    }
   
    void fooMethod1()
    {
       
    }
}

RMIの応用問題を解決した後、動的エージェントには多くの応用があることが分かった.例えば、このように、私たちは継承する必要があり、Fooのインスタンスを伝える必要があります.つまり、私たちは異なるビジネスインスタンスを実現する必要があります.面倒ですが、汎用性があれば、簡単ですが、JDK 1では.3の年代、どこから来たのはどんな泛型ですか、だからこの时私达は方法を考えて1つの代理类を创建して、いかなる业务のインタフェースに适任することができて、运行の时にどのインタフェースを実现することができて、今私达は分かったでしょう、これはダイナミックな代理ではありませんか、ダイナミックな代理JDKを书くのは人材です動的エージェントをRMIに適用した人はまるで天才(彼は確かに天才で、彼はRickardObergで、彼の事績について、多すぎて、自分で調べましょう).
ログモジュール:たとえば、メソッドの開始と終了の印刷パラメータと実行時間が必要で、アプリケーションコードを変更したくない場合は、どのように半分ですか?
セキュリティチェック:フォーラム登録ユーザーアクセスや非登録ユーザーアクセスなど.
トランザクション管理:たとえば、データベースにアクセスし、各メソッドの呼び出し前に接続を開き、呼び出し後に接続を閉じる必要があります.これにより、コード、優雅な設計を大幅に簡素化できますよね?
上の一連の応用をよく見ていると、一つの言葉がだんだん頭に浮かび上がってきて、AOP(接面プログラミング向け)は、AOPが解決しなければならない問題ではないでしょうか.
確かに、Struts、Springなどのフレームワークの実現原理はソースとダイナミックエージェントであり、ダイナミックエージェントを通じてブロックの機能を実現し、その後、複数のブロックを一連に接続します.それはフィルタチェーンモードです.よし、余計な話はしないで、更に撤退すれば多くて、制御の反転、依存の逆転、依存の注入などがあります.
3.動的エージェントの実装
動的エージェントから引用されるものが多いため,しばらくは言いきれず,基本的な動的エージェント呼び出しを貼り付けるだけで,簡単なAOP実装,エージェントモード実装などは,我々は放っておく.また書く時間があるでしょう.
1、bird.java 
package com.test.proxy;
 
public interface Bird
{
    void fly(String arg);
 
    void display();
}
2、Angel.java
package com.test.proxy;
 
/**
 *    
 * @author Ransom
 *
 */
public class Angel implements Bird
{
    private String name;
 
    public Angel(String name)
    {
        this.name = name;
    }
 
    @Override
    public void fly(String arg)
    {
        System.out.println("Bird " + name + " called fly method,args:" + arg);
    }
 
    @Override
    public void display()
    {
        System.out.println("Bird " + name + " called display method");
    }
 
}
 
3、BirdInvocationHandler.java
package com.test.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 *      bird,            ,             
 * @author Ransom
 *
 */
public class BirdInvocationHandler implements InvocationHandler
{
    private Object target;

    public BirdInvocationHandler(Object target)
    {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        /*
         *                      
         *            AOP  。
         */
        System.out.println("excute medhod:" + method.getName());
        Object obj = method.invoke(target, args);
        return obj;
    }

    public void setTarget(Object target)
    {
        this.target = target;
    }

}

4、Testmain.java
package com.test.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;

public class TestMain
{
    public static void main(String[] args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException
    {
        /*
         *       1
         */
        InvocationHandler handler = new BirdInvocationHandler(new Angel(
                "birdman"));
        // Class> proxyClass =
        // Proxy.getProxyClass(Bird.class.getClassLoader(),
        // Bird.class);
        // Bird b = (Bird) proxyClass.getConstructor(new Class[]
        // { InvocationHandler.class }).newInstance(new Object[]
        // { handler });
        // b.fly();
        // b.display();

        /**
         *       2
         */
        Bird b2 = (Bird) Proxy.newProxyInstance(
                BirdInvocationHandler.class.getClassLoader(), new Class[]
                { Bird.class }, handler);

        b2.fly("abc");
        b2.display();

    }
}