JAvase基礎回顧(三)動的エージェント

9147 ワード

ダイナミックエージェントは大規模なフレームワークでよく使われる古典的な技術の一つであり、ブロガーはspringの制御反転(注入依存)の思想を理解する際にjavaのダイナミックエージェントを振り返って復習した.
動的エージェントを話す前に、エージェントが何に使用されているのか、どのようなビジネスシーンに使用されているのかを簡単に説明し、静的エージェントと動的エージェントを導入します.
エージェント・モードで一般的に使用されるロールには、–抽象ロール:リアル・オブジェクトとエージェント・オブジェクトの共通インタフェースを宣言する–エージェントロール:エージェント・オブジェクト・ロールの内部にリアル・オブジェクトへの参照が含まれているため、リアル・オブジェクトを操作できます.また、エージェント・オブジェクトはリアル・オブジェクトと同じインタフェースを提供し、リアル・オブジェクトの代わりにいつでも使用できます.また、プロキシオブジェクトは、実際のオブジェクト操作を実行するときに、実際のオブジェクトをカプセル化することに相当する他の操作を追加できます.実際のロール:プロキシロールが表す実際のオブジェクトは、最終的に参照するオブジェクトです.
場合によっては、1つのクライアントが別のオブジェクトを直接参照したくないか、または直接参照できない場合があります.エージェントオブジェクトは、クライアントとターゲットオブジェクトの間で仲介の役割を果たすことができます.
エージェント・モードの役割は、このオブジェクトへのアクセスを制御するために他のオブジェクトにエージェントを提供することです.
一、静的エージェント
具体的なコードを見てみましょう
抽象的な役割:
public interface Subject {
    
    public void doSomething();
}

実際の役割:
public class RealSubject implements Subject {
    @Override
    public void doSomething() {
        
        System.out.println("do something!");
    }
}

プロキシロール:
public class PoxySubject implements Subject{
    private RealSubject subject;
    
    @Override
    public void doSomething() {
        this.doPreThing();
        
        if (null == subject) {
            
            subject = new RealSubject();
        }
        
        subject.doSomething();
        this.dopostThing();
    }
    
    public void doPreThing() {
        System.out.println("pre things");
    }
    
    public void dopostThing() {
        System.out.println("post things");
    }
}

テストクラス(mainメソッド)
public class Client {
    /**
     *                                 。
     *                 doSomething()  ,                        。
     * @param args
     */
    public static void main(String[] args) {
        Subject subject = new PoxySubject();
        subject.doSomething();
    }
}

mainメソッドの実行:
pre thingsdo something!post things
このようにして、私たちは実際のロールを隠すのではなく、エージェントロールを通じて実際のロールがしたことを完成したことを発見しました.エージェントの役割の中で、自分が実現したい方法をいくつか手足で実現することができます.これが静的エージェントの役割です.しかし、すぐに限界を発見しました.
上記の方法でプロキシモードを使用する場合は、実際のロールは事前に存在し、プロキシオブジェクトの内部プロパティとして使用する必要があります.しかし、実際に使用する場合、実際のロールはエージェントロールに対応する必要があります.大量に使用すると、クラスが急激に膨張します.また、実際のロールが事前に知られていない場合は、エージェントをどのように使用すればいいのでしょうか.これが静的エージェントの限界であり,この問題はJavaの動的エージェントクラスによって解決できる.
二、動的代理
Javaダイナミックエージェントクラスはjava.lang.reflectパッケージの下にあり、一般的には主に以下の2つのクラスに関連しています.
(1)Interface InvocationHandler:このインタフェースでは、1つのメソッド-public object invoke(Object obj,Method method,Object[]args)が実際に使用されている場合、最初のパラメータobjは一般的にエージェントクラスを指し、methodはエージェントされるメソッドであり、argsはこのメソッドのパラメータ配列である.この抽象的な方法はエージェントクラスで動的に実現される.
(2)Proxy:このクラスは動的エージェントクラスであり,前例のProxySubjectと同様の役割を果たす.
-protected Proxy(InvocationHandler h):内部のhに値を割り当てるコンストラクション関数.-static Class getProxyClass(ClassLoader loader,Class[]interfaces):loaderはクラスローダであり、interfacesは実際のクラスが所有するすべてのインタフェースの配列であるエージェントクラスを取得します.-static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h):エージェントクラスのインスタンスを返し、返されたエージェントクラスをエージェントクラスとして使用できます(Subjectインタフェースで宣言されたメソッドを使用できます).
次に、動的エージェントを使用して以前の例を実装します.
抽象的な役割:
public interface Subject {
    public void doSomething();
}

実際の役割:
public class RealSubject implements Subject {

    public void doSomething() {
        System.out.println("from real subject");
    }
}

エージェントロールを実装するクラス:
public class DynamicSubject implements InvocationHandler {
    
    private Object sub;
    
    public DynamicSubject(Object obj) {
        this.sub = obj;
    }
 
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("    " + method);
        
        method.invoke(sub, args);
        
        System.out.println("    " + method);
        
        return null;
    }    
}

テストクラス(mainメソッド):
public class Client {
    
    public static void main(String[] args) {
        RealSubject sub = new RealSubject();
        InvocationHandler hanlder = new DynamicSubject(sub);
        
        //          
        Subject subject =(Subject)Proxy.newProxyInstance(hanlder.getClass().getClassLoader(), sub.getClass().getInterfaces(), hanlder);
        subject.doSomething();
    }
}

実行結果:
呼び出し前public abstract void com.wenge.dynamicporxy.Subject.doSomething()from real subject呼び出し後public abstract void com.wenge.dynamicporxy.Subject.doSomething()
静的エージェントが実装する機能を実装し、プログラムの拡張性を向上させました.このようにして1つのクラスだけでなく、複数のクラスが上位インタフェースを実現すれば、これらはすべて動的に生成され、javaの反射技術を利用していることが明らかになった.これでダイナミックエージェントはいろいろなことができますが、最も古典的なのはspringフレームワークに依存して注入し、興味のある子供靴はソースコードを深く見ることができます.
Dynamic Proxyとは、実行時に生成されたclassであり、生成時にinterfaceのセットを提供する必要があり、classはこれらのinterfaceを実現したと主張します.もちろんclassのインスタンスをこれらのinterfaceのいずれかとして使用することができます.もちろん、このDynamic Proxyは実際にはProxyであり、実質的な仕事はしません.インスタンスを生成するときはhandlerを提供し、実際の仕事を引き継ぐ必要があります.
動的エージェントを実装するには、次の手順に従います.
1.invokeメソッドを実装する必要がある実装インタフェースInvocationHandlerのクラスを作成する2.エージェントされるクラスを作成する3.Proxyの静的メソッドnewProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h)によってエージェントを作成する4.エージェント呼び出しメソッドによって
このようにして,エージェントされるオブジェクト(RealSubject)を実行時に動的に変更することができ,制御が必要なインタフェース(Subjectインタフェース)を実行時に変更することができ,制御の方式(DynamicSubjectクラス)を動的に変更することができ,非常に柔軟な動的エージェント関係を実現することができる.
ご意見をお待ちしております
 
転載先:https://www.cnblogs.com/Vdiao/p/6694287.html