Javaのプロキシとは何ですか?

青灯夜游
リリース: 2019-11-18 17:17:15
オリジナル
3956 人が閲覧しました

Javaのプロキシとは何ですか?

javaプロキシとは何ですか?

プロキシは、ターゲット オブジェクトにアクセスする別の方法、つまりプロキシ オブジェクトを介してターゲット オブジェクトにアクセスする方法を提供する設計パターンです。対象オブジェクトを変更することなく、対象オブジェクトの機能を拡張できます。

エージェントの役割: コードの冗長性を削減します。

プロキシモードの実装は静的実装と動的実装の2つに分類され、動的実装は実装方法によりjdk動的実装、cglib動的実装に分かれます

3 Java の種類 エージェント モード

上記の要件を達成するには 3 つの方法があります。このパートでは、3 つのモードのコードの記述方法のみを説明し、実装については説明しません。まず原則。

1. 静的プロキシ

public interface ISinger {
    void sing();
}

/**
 *  目标对象实现了某一接口
 */
public class Singer implements ISinger{
    public void sing(){
        System.out.println("唱一首歌");
    }  
}

/**
 *  代理对象和目标对象实现相同的接口
 */
public class SingerProxy implements ISinger{
    // 接收目标对象,以便调用sing方法
    private ISinger target;
    public UserDaoProxy(ISinger target){
        this.target=target;
    }
    // 对目标对象的sing方法进行功能扩展
    public void sing() {
        System.out.println("向观众问好");
        target.sing();
        System.out.println("谢谢大家");
    }
}
ログイン後にコピー

Test

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        //目标对象
        ISinger target = new Singer();
        //代理对象
        ISinger proxy = new SingerProxy(target);
        //执行的是代理的方法
        proxy.sing();
    }
}
ログイン後にコピー

メリット:対象オブジェクトの機能を変更せずに対象機能を拡張

デメリット:この実装方法非常に直感的でシンプルですが、プロキシ オブジェクトを事前に記述しておく必要があり、インターフェイス層が変更された場合でもプロキシ オブジェクトのコードも維持する必要があるという欠点があります。プロキシ オブジェクトを実行時に動的に記述できれば、大量のプロキシ クラス コードが削減されるだけでなく、定期的なメンテナンスの手間も軽減されますが、実行時の効率は確実に影響を受けます。このメソッドは次の動的プロキシです。

2. JDK プロキシ

静的プロキシの前提は同じですが、Singer オブジェクトを拡張します

public interface ISinger {
    void sing();
}

/**
 *  目标对象实现了某一接口
 */
public class Singer implements ISinger{
    public void sing(){
        System.out.println("唱一首歌");
    }  
}
ログイン後にコピー

今回は直接テストされます。 Java のレイヤーは実装の詳細をカプセル化しているため (詳しくは後ほど説明します)、コードは非常にシンプルで、形式も基本的に固定されています。

Proxy クラスの静的メソッド newProxyInstance を呼び出すだけです。このメソッドはプロキシ クラス オブジェクトを返します。

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

受け取った 3 つのパラメータは次のとおりです:

●ClassLoader ローダー: 指定します。現在の対象オブジェクトはクラスローダーを使用しており、書き込み方法は固定されています

#● Class[] インターフェース: 対象オブジェクトによって実装されるインターフェースの種類、書き込み方法は固定です

●InvocationHandler h: イベント処理インターフェイス、必須 実装クラスに渡します。通常は匿名の内部クラスを直接使用します。

テスト コード

public class Test{
    public static void main(String[] args) {
  Singer target = new Singer();
        ISinger proxy  = (ISinger) 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("向观众问好");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("谢谢大家");
                        return returnValue;
                    }
                });
        proxy.sing();
    }
}
ログイン後にコピー

利点: 拡張機能を変更しない拡張機能を動的に実装します。ターゲット オブジェクトのロジック

欠点: 静的プロキシと JDK プロキシには共通の欠点があることがわかります。つまり、ターゲット オブジェクトは 1 つ以上のインターフェイスを実装する必要があり、そうでない場合は動的プロキシを実装できません。

3. Cglib エージェント

前提条件:

● cglib の jar ファイルを導入する必要がありますが、Spring のコアパッケージにはすでに Cglib 関数が含まれているので、それを導入することもできます。 spring-core-3.2.5.jar

# ターゲット クラスを Final にすることはできません

# ターゲット オブジェクトのメソッドが Final/static である場合、インターセプトされません。ターゲットは実行されません。オブジェクトの追加ビジネス メソッド

/**
 * 目标对象,没有实现任何接口
 */
public class Singer{

    public void sing() {
        System.out.println("唱一首歌");
    }
}
ログイン後にコピー
/**
 * Cglib子类代理工厂
 */
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;
    }
}
ログイン後にコピー

ここのコードも非常に修正されています。黄色でマークされた部分だけを自分で書く必要があります。

Test

/**
 * 测试类
 */
public class Test{
    public static void main(String[] args){
        //目标对象
        Singer target = new Singer();
        //代理对象
        Singer proxy = (Singer)new ProxyFactory(target).getProxyInstance();
        //执行代理对象的方法
        proxy.sing();
    }
}
ログイン後にコピー
利点: 目標を変更せずに動的に実装できるオブジェクト ロジックの拡張

欠点: ターゲットはインターフェイスを実装する必要があります。そうしないと動的プロキシを実現できません

概要: それぞれ 3 つのプロキシ モードそれぞれに独自の長所と短所、および対応する適用範囲があり、主に対象オブジェクトがインターフェイスを実装しているかどうかによって決まります。 Spring フレームワークによって選択されたプロキシ モードを例に挙げます。

Spring の AOP プログラミングでは:

コンテナに追加されたターゲット オブジェクトに実装インターフェイスがある場合は、JDK プロキシを使用します
Ifターゲット オブジェクトはインターフェイスを実装していません。Cglib プロキシを使用してください

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

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート