Javaプロキシモードのjdk動的プロキシの詳細な説明(超詳細)

エージェントモード:

プロキシは基本的なデザインパターンの1つであり、追加または異なる操作を提供し、挿入されたオブジェクトは「実際の」オブジェクトのプロキシに使用されます。これらの操作は通常「実際の」オブジェクトとの通信を伴うため、プロキシは通常、仲介者の役割。

動的プロキシ

動的プロキシーは、実装フェーズでプロキシー・クラスを考慮する必要はありませんが、ランタイム・フェーズでどのオブジェクトを指定するか
動的プロキシーの利点:

  • 明確な責任
    実際の役割は、実際のビジネスロジックを実現することです。他の責任のないトランザクションを気にする必要はありません。後のエージェントを通じてトランザクションを完了することができます。付随的な結果は、単純で明確なプログラミングです。
  • プロキシオブジェクトは、クライアントとターゲットオブジェクトの間の仲介者として機能できます。これは、仲介者として機能し、ターゲットオブジェクトを保護します。つまり、ターゲットオブジェクトを変更せずに機能を拡張できます。
  • 高いスケーラビリティ。必要なメソッドに必要な機能を追加できます。

jdkに基づく動的プロキシを実装します。

Java.lang.reflect.ProxyはjdkのAPIで提供されています。動的プロキシの作成を完了するのに役立ちます。
注:動的プロキシオブジェクトの作成を完了するためにJavaでProxyを使用すると、インターフェースを実装するクラスのプロキシオブジェクトしか作成できません。
動的プロキシは、メモリ内に直接プロキシオブジェクトを生成することです。
ここに画像の説明を挿入引き続きAPIを見てください。
ここに画像の説明を挿入通常このメソッドを使用してプロキシオブジェクトを作成します。これには3つのパラメータが必要です。

  1. ClassLoaderローダー:

ここに画像の説明を挿入変換は次のとおりです。各Classオブジェクトには、それを定義するClassLoaderへの参照が含まれています。配列クラスのクラスオブジェクトは、クラスローダーでは作成されませんが、Javaランタイムのニーズに応じて自動的に作成されます。Class.getClassLoader()によって返される配列クラスのクラスローダーは、その要素タイプのクラスローダーと同じです。要素タイプが基本タイプの場合、配列クラスにはクラスローダーがありません。したがって、プロキシする必要のあるオブジェクトが配列でない限り、ClassオブジェクトのgetClassLoader()を使用してClassLoaderオブジェクトを取得できます。

  1. Class <?> []インターフェース:

ここに画像の説明を挿入このメソッドはクラスクラスにあり、直接取得できます。このクラスは、ターゲットオブジェクトによって実装されるインターフェースを表します

  1. InvocationHandler h:
    クリックすると、これがインターフェースであり、実装されていないinvoke(…)メソッドがあります。
    ここに画像の説明を挿入
    ここに画像の説明を挿入つまり、ここに渡す必要があるオブジェクトは、このインターフェースを実装する必要があり、invoke()メソッドは、以下で説明するように完了する必要があります。このメソッドの3つのパラメーター:
  • パラメータ1:オブジェクトプロキシ、これはプロキシするオブジェクトです

  • パラメータ2:メソッドメソッド:アクセスする必要があるターゲット動作、つまり呼び出す必要があるメソッド

  • パラメーター3:オブジェクト[]引数:動作を呼び出すときに必要なパラメーター

このメソッドの主な機能は、プロキシオブジェクトを通じてビヘイビアーを呼び出すときに、ターゲットビヘイビアーを呼び出すことができるかどうかを制御することです。
以下はコードで実装されています:

//接口
public interface IUserService {
	public String addUser(String username,String password);
}
//实现类
public class UserServiceImpl implements IUserService {
	@Override
	public String addUser(String username, String password) {
		System.out.println("添加用户:" + username + "   " + password);
		return "hello " + username;
	}
}

次に、UserServiceImplをプロキシするプロキシクラスを記述する必要があります。

public class UserServiceProxy implements InvocationHandler {
    // 目标对象
    private Object target;
    public UserServiceProxy(Object target) {
        this.target = target;
    }
    // 作用:创建代理对象
    public Object createProxy() {
        ClassLoader loader = target.getClass().getClassLoader();
        Class[] interfaces = target.getClass().getInterfaces();
        return Proxy.newProxyInstance(loader, interfaces, this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method);
        System.out.println(Arrays.asList (args));
        System.out.println("方法调用之前");
        Object result = method.invoke (target,args);
        System.out.println("方法调用之后");
        return result;
    }
}

次にテストクラスを書きます:

public class Test {
    public static void main(String[] args) {
        //需要代理的对象
        IUserService userservice = new UserServiceImpl ();
        //创建代理类
        UserServiceProxy up =  new UserServiceProxy(userservice);
        IUserService proxy = (IUserService) up.createProxy ();
        //使用代理类进行方法增强
        String s = proxy.addUser ("tom", "123");
        System.out.println("s: " + s);
    }
}

出力結果:
ここに画像の説明を挿入
出力は以下で分析されます。
最初の出力はIUserService.addUserを指すメソッドオブジェクトで、2番目はinvoke()の3番目のパラメーターです。これは、実際にはプロキシオブジェクトを使用するときに使用するパラメーターです(通常、最初のパラメーターは使用されません)、次にaddUser()メソッドの前後にカスタムコンテンツを追加し、メソッド呼び出しの戻り値も取得しました。

要約:

  1. 動的プロキシーは、実装フェーズでプロキシー・クラスを考慮する必要はないが、ランタイム・フェーズでどのオブジェクトを指定するかを示すプロキシー・メソッドです。
  2. jdkの動的プロキシメソッドは、Proxy.newProxyInstance(ClassLoaderローダー、クラス<?> []インターフェイス、InvocationHandler h)メソッドを使用してプロキシオブジェクトを生成することです。エージェントクラスはメソッドの拡張を実行します。
  3. 開発では、動的プロキシを使用して、パフォーマンスの監視、権限の制御、ロギングなどの操作を完了します。SpringのAOPは、jdk動的プロキシを使用して部分的に実装されています。
公開された39元の記事 ウォンの賞賛1 ビュー4620

おすすめ

転載: blog.csdn.net/thetimelyrain/article/details/96383180