ジャワの静的および動的なエージェントProxyエージェントモデル

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/TreeShu321/article/details/102640372


エージェントモデルの説明:
プロキシ(プロキシ)ターゲットオブジェクトにアクセスするための追加的な方法を提供し、デザインパターンであり、それはそうするの代理オブジェクトの利点を介してターゲットによってアクセスされます:追加の機能強化に達成することができ、対象物に基づいて。ターゲットオブジェクトの機能の拡張の機能動作。
思想にこのプログラムを使用します。変更を変更する必要が、この方法は、プロキシを経由して拡張することができるならば、誰かに行くか、既に書かれたコードを変更すること自由に感じてはいけません

例えば:私たちは私たちの仲介プロキシオブジェクトである、購入する不動産開発に直接移動することなく、購入する不動産エージェントを介して住宅を購入することができます。

カテゴリ別にプロキシモードは、次の3つのカテゴリに分けることができます。

  • 帯電防止剤
  • 動的プロキシ
    JDK API動的プロキシとプロキシ動的CGLIB:動的プロキシは、に分けることができます。

帯電防止剤

帯電防止剤を使用する場合、インターフェイスまたは親クラスを定義する必要があり、同じまたは同じ親がプロキシオブジェクトプロキシオブジェクトと一緒に継承さを達成するためのインタフェースです。

コード例:
プロキシインタフェースUserDao

package com.sl.proxy;

/**
 * @author shuliangzhao
 * @Title: UserDao
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:02
 */
public interface UserDao {

    void delete();
}

オーディエンスUserDaoImpl

package com.sl.proxy;

/**
 * @author shuliangzhao
 * @Title: UserDaoImpl
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:02
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void delete() {
        System.out.println("删除数据");
    }
}

プロキシオブジェクトUserDaoProxy

package com.sl.proxy;

/**
 * 代理对象
 * @author shuliangzhao
 * @Title: UserDaoProxy
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:03
 */
public class UserDaoProxy implements UserDao {

    private UserDao target;

    public UserDaoProxy(UserDao target) {
        this.target = target;
    }

    @Override
    public void delete() {
        System.out.println("开始操作");
        target.delete();
        System.out.println("结束操作");
    }
}

TestクラスのApp

public class App {

    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
        userDaoProxy.delete();
    }
}

要約:ターゲット・オブジェクトへのプロキシオブジェクトことに留意する必要があるターゲットを呼び出すためのプロキシオブジェクトのメソッドを呼び出す。同じインタフェースを実装し、その後アプローチの同じメソッドを呼び出して、ターゲットオブジェクトを呼び出します。
1.ターゲットの拡張は、ターゲットオブジェクトを変更することなく、関数内で行うことができます。
2.短所:プロキシオブジェクトは、一度、ターゲットオブジェクトと同じインタフェースを実装し、非常に多くのプロキシクラス、同時にあまりにも多くのクラスする必要があるため。ターゲット・オブジェクトとプロキシオブジェクトを増大させるためのインターフェース方法は、維持されなければなりません。

動的プロキシ

エージェントの動的特性:
1、プロキシ・オブジェクト、インターフェースを実装する必要はありません
JDKは、APIを使用して、プロキシオブジェクトを生成するために2を、メモリに構築動的プロキシオブジェクト

JDK生成されたプロキシオブジェクト

JDKの実装エージェントのみたとえば、Proxy.newProxyInstanceメソッドを使用する必要があるが、この方法は、3つのパラメータを必要とし、完全な文言は次のようになります。

静的オブジェクトnewProxyInstance(クラスローダローダ、クラス<?> []
インターフェイス、のInvocationHandlerのH)

  • クラスローダローダは、:現在のクラスローダを指定するために使用される観客は、ローダーは固定を得ることです
  • クラス[]インタフェース、<?>:ターゲット・オブジェクトのタイプは、の種類を確認するために、一般的な方法を使用して、インターフェイスを実装
  • InvocationHandler H:イベント処理は、ターゲット・オブジェクトの実行方法は、イベントハンドラメソッドがトリガーされたときに、現在のメソッドは、パラメータとしてターゲット・オブジェクトを実行します

サンプルコードは
、インタフェースのInvocationHandlerを実装UserDaoInvocationHandlerクラスを作成し、このクラスは、プロキシオブジェクトを保持している対象のインスタンスであります

package com.sl.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author shuliangzhao
 * @Title: UserDaoInvocationHandler
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:14
 */
public class UserDaoInvocationHandler implements InvocationHandler {

    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
        Object invoke = method.invoke(target, args);
        return invoke;
    }
}

プロキシクラスを作成するためのファクトリー

package com.sl.jdkproxy;

import java.lang.reflect.Proxy;

/**
 * @author shuliangzhao
 * @Title: ProxyFactory
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:19
 */
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 UserDaoInvocationHandler(target));
    }
}

TestクラスのApp

package com.sl.jdkproxy;

import com.sl.staticproxy.UserDao;
import com.sl.staticproxy.UserDaoImpl;

/**
 * @author shuliangzhao
 * @Title: App
 * @ProjectName spring-boot-learn
 * @Description: TODO
 * @date 2019/10/19 17:22
 */
public class App {

    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();

        UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();

        System.out.println(proxyInstance.getClass());

        // 执行方法   【代理对象】
        proxyInstance.delete();
    }
}

概要:プロキシオブジェクトがインタフェースを実装する必要はありませんが、ターゲットオブジェクトがインタフェースを実装しなければならない、または動的プロキシを使用することはできません

演技のCGLIB

上記静的および動的エージェントプロキシモデルは、ターゲットの目的を達成するために必要とされる対象物のインタフェースであるが、時にはターゲット・オブジェクトが1つだけの目的であり、任意のインターフェースを実装していない、我々は、ターゲットオブジェクトを使用することができ、この時間は、サブクラスでありますエージェントクラスは、このメソッドが呼び出され、実施形態を実装する:CGLIB剤
CGLIBは、強力な、高性能コード生成パッケージである、それは広く、例えばスプリングを使用し、実行時に多くのAOPフレームJavaインターフェースに実装されたJavaクラスを拡張することができます。 AOPとsynaop、その傍受(インターセプト)する方法を提供する
CGLIBプロキシ注使用:
1.エージェントクラスは、最終的なことができない、そうでなければエラー
ターゲット・オブジェクトのメソッドは、静的/最終ある場合2.が、それはつまり、ブロックされません、ビジネスメソッドは、ターゲットオブジェクトの追加を実行しません
:サンプルコード
UserDaoをプロキシされているオブジェクトを

 */
public class UserDao {

    public void delete() {
        System.out.println("删除方法");
    }
}

プロキシクラスを作成するためのファクトリー

public class ProxyFactory implements MethodInterceptor {

    //维护目标对象
    private Object target;

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

    //给目标对象创建一个代理对象
    public Object getProxyInstance() {
        //1.工具类
        Enhancer enhancer = new Enhancer();
        //2.设置父类
        enhancer.setSuperclass(target.getClass());
        //3.设置回调函数
        enhancer.setCallback(this);
        //4.创建子类
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开始事务...");

        //执行目标对象的方法
        Object returnValue = method.invoke(target, objects);

        System.out.println("提交事务...");

        return returnValue;
    }
}

テストカテゴリ

public class App {

    public static void main(String[] args) {
        UserDao userDao = new UserDao();
        UserDao proxyInstance = (UserDao) new ProxyFactory(userDao).getProxyInstance();
        proxyInstance.delete();
    }
}

おすすめ

転載: blog.csdn.net/TreeShu321/article/details/102640372