ホームページ Java &#&はじめる Java の 3 つのプロキシ モードとは何ですか?

Java の 3 つのプロキシ モードとは何ですか?

Jan 30, 2021 am 09:44 AM
java プロキシモード

Java の 3 つのプロキシ モードとは何ですか?

まず、プロキシモードとは何かについて簡単に説明します。

プロキシは、ターゲット オブジェクトにアクセスする別の方法、つまりプロキシ オブジェクトを介してターゲット オブジェクトにアクセスする方法を提供するデザイン パターンです。この利点は、次の実装に基づいてターゲット オブジェクトを強化できることです。ターゲット オブジェクト。追加の機能操作、つまり、ターゲット オブジェクトの機能を拡張します。
ここではプログラミングの考え方が使用されています。他の人が書いたコードやメソッドを自由に変更しないでください。必要がある場合は、メソッド

エージェントの役割を説明するための例を示します: スターを招待したいとします。その場合、スターに直接連絡するのではなく、スターの連絡先に連絡します。同じ目的を達成するためのエージェント。スターはターゲットオブジェクトであり、彼はイベントのプログラムに責任を持つだけでよく、その他の些細なことはエージェント(ブローカー)に解決を任せます。これは、エージェントの考え方の一例です。現実.

図は次のとおりです:

Java の 3 つのプロキシ モードとは何ですか?

##プロキシ モードの重要なポイントは、プロキシ オブジェクトとターゲット オブジェクトです。プロキシ オブジェクトは拡張機能です。

#1.1. 静的プロキシ

静的プロキシを使用する場合は、インターフェイスまたは親クラスを定義する必要があります。プロキシ オブジェクトとプロキシ オブジェクト同じインターフェイスを実装するか、同じ親クラスを継承します。

次に説明する例を示します。

保存アクションをシミュレートし、保存アクションのインターフェイスを定義します: IUserDao.java、次にターゲット オブジェクトこのインターフェースのメソッド UserDao.java を実装します。このとき、静的プロキシメソッドを使用する場合は、プロキシオブジェクト (UserDaoProxy.java) に IUserDao インターフェースも実装します。呼び出すときは、 を呼び出して対象のオブジェクトを呼び出します。

プロキシ オブジェクトとターゲット オブジェクトは同じインターフェイスを実装し、同じメソッドを呼び出してターゲット オブジェクトのメソッドを呼び出す必要があることに注意してください。

コード例:

インターフェイス:IUserDao.java

/**
 * 接口
 */public interface IUserDao {    void save();
}
ログイン後にコピー

ターゲット オブジェクト:UserDao.java

/**
 * 接口实现
 * 目标对象
 */public class UserDao implements IUserDao {    public void save() {
        System.out.println("----已经保存数据!----");
    }
}
ログイン後にコピー

プロキシ オブジェクト:UserDaoProxy.java

/**
 * 代理对象,静态代理
 */public class UserDaoProxy implements IUserDao{    //接收保存目标对象
    private IUserDao target;    public UserDaoProxy(IUserDao target){        this.target=target;
    }    public void save() {
        System.out.println("开始事务...");
        target.save();//执行目标对象的方法
        System.out.println("提交事务...");
    }
}
ログイン後にコピー

(学習ビデオ共有:

Javaビデオチュートリアル

)テストクラス:App.java

/**
 * 测试类
 */public class App {    public static void main(String[] args) {        //目标对象
        UserDao target = new UserDao();        //代理对象,把目标对象传给代理对象,建立代理关系
        UserDaoProxy proxy = new UserDaoProxy(target);

        proxy.save();//执行的是代理的方法
    }
}
ログイン後にコピー

静的エージェントの概要:

1. ターゲットを変更せずに実行できます の機能を前提としています

2. 欠点:

プロキシ オブジェクトはターゲット オブジェクトと同じインターフェイスを実装する必要があるため、多くのプロキシ クラスが存在し、クラスが多すぎます。インターフェイスにメソッドを追加するときは、ターゲット オブジェクトとプロキシ オブジェクトの両方を維持する必要があります。

静的プロキシの欠点を解決するにはどうすればよいですか?その答えは、動的プロキシ メソッドを使用できることです

1.2. ダイナミック プロキシ

ダイナミック プロキシには次の特徴があります:

1. プロキシ オブジェクトはインターフェイスを実装する必要はありません

2. プロキシ オブジェクトの生成は API を使用します。メモリ内にプロキシ オブジェクトを動的に構築するための JDK の設定 (プロキシ オブジェクトの作成 / ターゲット オブジェクトによって実装されるインターフェイスのタイプを指定する必要があります)
3. 動的プロキシは、JDK プロキシ、インターフェイス プロキシとも呼ばれます

JDK でプロキシ オブジェクトを生成するための API

プロキシ クラスが配置されているパッケージ: java.lang.reflect .Proxy

JDK ではプロキシを実装するために newProxyInstance メソッドを使用するだけで済みますが、このメソッドは完全な書き込みメソッドは次のとおりです:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
ログイン後にコピー

このメソッドは Proxy クラスの静的メソッドであり、3 つのパラメーターを受け取ることに注意してください:

ClassLoader ローダー: 現在のクラスローダーを使用するターゲットオブジェクト、およびローダーの取得方法は固定されています

Class[] インターフェイス,:ターゲット オブジェクトによって実装されるインターフェイスのタイプ。タイプを確認するにはジェネリックスを使用します

InvocationHandler h: イベント処理、対象オブジェクトのメソッドを実行すると、イベントプロセッサのメソッドがトリガーされ、現在実行されている対象オブジェクトのメソッドがパラメータとして使用されます。

を渡します。

コード例:

インターフェースクラス IUserDao.java とインターフェース実装クラス 対象オブジェクト UserDao はそのまま同一です これをベースにプロキシファクトリクラス(ProxyFactory.java)を追加し、この中にプロキシクラスを記述しますを配置し、まずテスト クラス (プロキシを使用する必要があるコード) 内のターゲット オブジェクトとプロキシ オブジェクト間の接続を確立してから、プロキシ オブジェクト


で同じ名前のメソッドを使用します。エージェント ファクトリ クラス: ProxyFactory.java

/**
 * 创建动态代理对象
 * 动态代理不需要实现接口,但是需要指定接口类型
 */public class ProxyFactory{    //维护一个目标对象
    private Object target;    public ProxyFactory(Object target){        this.target=target;
    }   //给目标对象生成代理对象
    public Object getProxyInstance(){        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),                new InvocationHandler() {                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始事务2");                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");                        return returnValue;
                    }
                }
        );
    }

}
ログイン後にコピー

テスト クラス: App.java

/**
 * 测试类
 */public class App {    public static void main(String[] args) {        // 目标对象
        IUserDao target = new UserDao();        // 【原始的类型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());        // 执行方法   【代理对象】
        proxy.save();
    }
}
ログイン後にコピー

概要:

プロキシ オブジェクトはインターフェイスを実装する必要はありませんが、ターゲット オブジェクトはインターフェイスを実装する必要があります。インターフェイス、そうでない場合は動的プロキシは使用できません


1.3.Cglib プロキシ

上記の静的プロキシ モードと動的プロキシ モードでは、ターゲット オブジェクトがインターフェイスを実装するターゲット オブジェクトである必要がありますが、場合によってはターゲットobject は単なる別個のオブジェクトであり、インターフェイスは実装されていません。この時点では、ターゲット オブジェクトのサブクラスを使用してプロキシを実装できます。このメソッドは Cglib proxy

と呼ばれます。

Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.

Cglib子类代理实现方法:
1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入pring-core-3.2.5.jar即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

代码示例:
目标对象类:UserDao.java

/**
 * 目标对象,没有实现任何接口
 */public class UserDao {    public void save() {
        System.out.println("----已经保存数据!----");
    }
}
ログイン後にコピー

Cglib代理工厂:ProxyFactory.java

/**
 * Cglib子类代理工厂
 * 对UserDao在内存中动态构建一个子类对象
 */public class ProxyFactory implements MethodInterceptor{    //维护目标对象
    private Object target;    public ProxyFactory(Object target) {        this.target = target;
    }    //给目标对象创建一个代理对象
    public Object getProxyInstance(){        //1.工具类
        Enhancer en = new Enhancer();        //2.设置父类
        en.setSuperclass(target.getClass());        //3.设置回调函数
        en.setCallback(this);        //4.创建子类(代理对象)
        return en.create();

    }    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开始事务...");        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);

        System.out.println("提交事务...");        return returnValue;
    }
}
ログイン後にコピー

测试类:

/**
 * 测试类
 */public class App {    @Test
    public void test(){        //目标对象
        UserDao target = new UserDao();        //代理对象
        UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance();        //执行代理对象的方法
        proxy.save();
    }
}
ログイン後にコピー

在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理

相关推荐:java入门教程

以上がJava の 3 つのプロキシ モードとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

See all articles