ホームページ  >  記事  >  Java  >  Javaにおける動的プロキシと静的プロキシの解析例

Javaにおける動的プロキシと静的プロキシの解析例

WBOY
WBOY転載
2023-05-05 21:37:081494ブラウズ

    0. エージェント モード

    なぜエージェント モードを学ぶ必要があるのでしょうか?これは SpringAOP の最下層です [SpringAOP と SpringMVC]

    プロキシ モードの分類:

    • 静的プロキシ

    • 動的プロキシ

    1.静的プロキシ

    静的プロキシでは、ターゲット オブジェクトの各メソッドの拡張は手動で行われます (コードの詳細は後で説明します_)、非常に柔軟性が低く (たとえば、新しいメソッドをインターフェイスに追加すると、ターゲット オブジェクトとプロキシ オブジェクトを変更する必要があります)、面倒です (_それぞれに別個のプロキシ クラス を記述する必要があります)ターゲットクラス)。実際のアプリケーション シナリオは非常に少なく、日常の開発で静的プロキシが使用されるシナリオはほとんどありません。

    #ロール分析:

      #抽象ロール: 一般に、問題を解決するにはインターフェイスまたは抽象クラスが使用されます
    • # #実際の役割: 演じられた役割
    • エージェントの役割: 実際の役割として行動し、実際の役割を果たした後、通常はいくつかの補助的な業務を行います
    • 顧客: プロキシ オブジェクトにアクセスする人!
    • コードステップ:

    1. インターフェイス

    public interface Rent {
        public void rent();
    }

    2. 実際の文字

    //房东
    public class Host implements Rent {
        public void rent() {
            System.out.println("房东要租房子");
        }
    }

    3.エージェント ロール

    public class Proxy implements Rent{
        private Host host;
        public Proxy() {
        }
        public Proxy(Host host) {
            this.host = host;
        }
        public void rent(){
            seeHouse();
            host.rent();
            fare();
        }
        //看房
        public void seeHouse(){
            System.out.println("中介带你看房");
        }
        //收中介费
        public void fare(){
            System.out.println("中介收费");
        }
    }

    4. エージェント ロールへのクライアント アクセス

    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
            //代理,代理角色一般会有附属操作!
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }

    エージェント モードの利点:

    本当の役割 操作はより純粋です!一部の公的な業務に注意を払う必要はありません。
    • #一般の人々はエージェントの役割に任せられます。ビジネスの分業化を実現!
    • 公共サービスが拡大するときは一元管理が便利!
    • 欠点:

    実際のロールはプロキシ ロールを生成します。JVM の観点から見ると、静的プロキシはインターフェイス、実装クラス、およびプロキシ クラスが実際のクラス ファイルになりました。

    2. 基盤となるプロキシ モデルである

    AOP についての理解を深めます

    3. 動的プロキシJavaにおける動的プロキシと静的プロキシの解析例

    動的プロキシの役割は静的プロキシの役割と同じです
    • 動的プロキシのプロキシ クラスは動的に生成され、直接作成されるものではありません。
    • 動的エージェントは、インターフェイス ベースの動的エージェントとクラス ベースの動的エージェントの 2 つのカテゴリに分類されます。
    • インターフェイス ベース— —JDK 動的プロキシ
      • クラスに基づく: cglib 動的プロキシ
      • Java バイトコード実装: javasist
      • 次の 2 つのクラスを理解する必要があります: Proxy: プロキシ クラス、InvocationHandler: 呼び出しハンドラー

    JVM の観点から見ると、動的プロキシは実行時にクラスのバイトコードを動的に生成し、JVM にロードします。 。

    //Proxy是生成动态代理类,提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
    //InvocationHandler-- invoke 调用处理程序并返回接口, 是由代理实例的调用处理程序实现的接口 。
    動的プロキシの利点:

    現実のキャラクターの操作をより純粋にすることができます。何らかの公的業務に対処する必要はありません
    • 一般向けの業務はエージェントの役割に任せられます。実装
    • public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){
      }

    • 1.

    loader : プロキシ オブジェクトをロードするために使用されるクラス ローダー。 2.

    インターフェース : プロキシ クラスによって実装されるいくつかのインターフェース; 3.

    h : InvocationHandler インターフェイスを実装するオブジェクト; 動的プロキシを実装するには、処理ロジックをカスタマイズするために InvocationHandler

    も実装する必要があります。動的プロキシ オブジェクトがメソッドを呼び出すと、このメソッドへの呼び出しは、

    InvocationHandler インターフェイスを実装するクラスの invoke メソッドに転送されます。

    public interface InvocationHandler {
        Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    }
    1.

    proxy: 動的に生成されたプロキシ クラス

    2.

    method: プロキシ クラス オブジェクトによって呼び出されるメソッドに対応します

    3.

    args: 現在のメソッドのパラメータmethod

    動的プロキシの例

    1. インターフェイスを定義します

    public interface Rent {
        public void rent();
    }

    2. 実装しますレンタル インターフェイス

    public class Host implements Rent {
        @Override
        public void rent() {
            System.out.println("房东要租房");
        }
    }

    3. JDK 動的プロキシ クラスを定義します

    public class DebugInvocationHandler implements InvocationHandler {
        /**
         * 代理类中的真实对象
         */
        private final Object target;
        public DebugInvocationHandler(Object target){
            this.target = target;
        }
        /**
         * 当你使用代理对象调用方法的时候实际会调用到这个方法
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //调用方法前
            System.out.println("before method" + method.getName());
            Object res = method.invoke(target, args);
            //调用方法后
            System.out.println("after method" + method.getName());
            return res;
        }
    }

    invoke()

    メソッド: 動的プロキシ オブジェクトがネイティブ メソッドを呼び出すと、実際に呼び出されます。取得したのは

    invoke() メソッドで、その後 invoke() メソッドが代わりにプロキシ オブジェクトのネイティブ メソッドを呼び出します。 4. プロキシ オブジェクトのファクトリ クラスを取得する

    public class JdkProxyFactory {
        public static Object getProxy(Object target){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new DebugInvocationHandler(target)
            );
        }
    }

    getProxy()

    : 主に

    Proxy.newProxyInstance を通じて特定のクラスのファクトリ クラスを取得します。 () メソッド プロキシ オブジェクト5。実際の使用法

    public static void main(String[] args) {
            //Rent rent = new Host();
            //Rent rentProxy= (Rent) Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(),new DebugInvocationHandler(rent));
            Rent rentProxy = (Rent)JdkProxyFactory.getProxy(new Host());
            rentProxy.rent();
        }

    メソッドレント前の上記エージェント実行の出力

    ##家主は家を借りたいと考えています

    メソッドレントの後に

    以上がJavaにおける動的プロキシと静的プロキシの解析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。