ホームページ  >  記事  >  Java  >  Java の静的プロキシ、動的プロキシ、および CGLIB 動的プロキシの詳細な説明 (図)

Java の静的プロキシ、動的プロキシ、および CGLIB 動的プロキシの詳細な説明 (図)

黄舟
黄舟オリジナル
2017-08-08 10:02:171477ブラウズ

この記事では、主に Java の静的プロキシ、動的プロキシ、および CGLIB 動的プロキシの概要を紹介します。興味のある方は学習してください。プロキシ パターンは、Java で最もよく使用されるデザイン パターンの 1 つです。特に Spring フレームワークで広く使用されています。 Java のプロキシ モードは、一般に、静的プロキシ、動的プロキシ、および CGLIB 動的プロキシに分類できます。


上記の 3 つのプロキシ モードについては個別に説明します。

1. 静的プロキシ

静的プロキシとは、実際にはプログラムを実行する前に事前にプロキシメソッドのプロキシクラスを記述しておき、コンパイル後に実行するものです。クラスはプログラムが実行される前にすでに存在しています。

以下では、静的プロキシのデモを実装します。


静的プロキシ


インターフェイス Target

package com.test.proxy;

public interface Target {

  public String execute();
}

TargetImpl を定義して、インターフェイス Target

package com.test.proxy;

public class TargetImpl implements Target {

  @Override
  public String execute() {
    System.out.println("TargetImpl execute!");
    return "execute";
  }
}

Proxy クラス

を実装します。

rreee
テストクラス:

package com.test.proxy;

public class Proxy implements Target{

  private Target target;

  public Proxy(Target target) {
    this.target = target;
  }

  @Override
  public String execute() {
    System.out.println("perProcess");
    String result = this.target.execute();
    System.out.println("postProcess");
    return result;
  }
}

動作結果:

package com.test.proxy;

public class ProxyTest {

  public static void main(String[] args) {

    Target target = new TargetImpl();
    Proxy p = new Proxy(target);
    String result = p.execute();
    System.out.println(result);
  }

}

静的プロキシは、プロキシメソッドが多い場合、事前にプロキシクラスを記述する必要があるため、上記の欠点は、動的エージェントによって補われました。

2. 動的プロキシ

動的プロキシは主にリフレクションメカニズムを使用して、実行時に必要なプロキシのクラスを動的に生成します。

動的プロキシ

Interface

perProcess
TargetImpl execute!
postProcess
execute

実装クラス

package com.test.dynamic;

public interface Target {

  public String execute();
}

エージェントクラス

package com.test.dynamic;

public class TargetImpl implements Target {

  @Override
  public String execute() {
    System.out.println("TargetImpl execute!");
    return "execute";
  }
}

テストクラス

package com.test.dynamic;


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

public class DynamicProxyHandler implements InvocationHandler{

  private Target target;

  public DynamicProxyHandler(Target target) {
    this.target = target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("========before==========");
    Object result = method.invoke(target,args);
    System.out.println("========after===========");
    return result;
  }
}

実行結果:

package com.test.dynamic;

import java.lang.reflect.Proxy;

public class DynamicProxyTest {

  public static void main(String[] args) {
    Target target = new TargetImpl();
    DynamicProxyHandler handler = new DynamicProxyHandler(target);
    Target proxySubject = (Target) Proxy.newProxyInstance(TargetImpl.class.getClassLoader(),TargetImpl.class.getInterfaces(),handler);
    String result = proxySubject.execute();
    System.out.println(result);
  }

}

動的プロキシであっても静的リーダーであっても、プロキシ関数を実行する前にインターフェースを定義する必要があります。実装される。これにも制限があるため、この問題を解決するために、cglib プロキシという 3 番目のプロキシ方法が登場しました。

3.cglib エージェント

CGLib は、非常に低レベルのバイトコード テクノロジを使用します。原理は、バイトコード テクノロジを通じてクラスのサブクラスを作成し、サブクラス内のメソッド インターセプト テクノロジを使用してすべての親クラスのメソッド呼び出しをインターセプトすることです。横断的なロジックが織り込まれています。 JDK 動的プロキシと CGLib 動的プロキシは両方とも、Spring AOP を実装するための基礎です。

cglib動的プロキシ


ターゲットクラス

========before==========
TargetImpl execute!
========after===========
execute

一般プロキシクラス:

package com.test.cglib;

public class Target {

  public String execute() {
    String message = "-----------test------------";
    System.out.println(message);
    return message;
  }
}

テストクラス

package com.test.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor{

  @Override
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println(">>>>MethodInterceptor start...");
    Object result = proxy.invokeSuper(obj,args);
    System.out.println(">>>>MethodInterceptor ending...");
    return "result";
  }
}

:

package com.test.cglib;

import net.sf.cglib.proxy.Enhancer;

public class CglibTest {

  public static void main(String ... args) {
    System.out.println("***************");
    Target target = new Target();
    CglibTest test = new CglibTest();
    Target proxyTarget = (Target) test.createProxy(Target.class);
    String res = proxyTarget.execute();
    System.out.println(res);
  }

  public Object createProxy(Class targetClass) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(targetClass);
    enhancer.setCallback(new MyMethodInterceptor());
    return enhancer.create();
  }

}

プロキシ オブジェクトの生成このプロセスは Enhancer クラスによって実装され、おおよその手順は次のとおりです:


1. エージェント クラス Class のバイナリ バイトコードを生成します。


2. Class.forName を通じてバイナリ バイトコードをロードして、Class オブジェクトを生成します。 ;


3. リフレクション機構がインスタンス構築を取得し、プロキシ クラス オブジェクトを初期化します。

以上がJava の静的プロキシ、動的プロキシ、および CGLIB 動的プロキシの詳細な説明 (図)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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