ホームページ  >  記事  >  类库下载  >  Java動的プロキシを実装する2つの方法

Java動的プロキシを実装する2つの方法

高洛峰
高洛峰オリジナル
2016-11-30 14:59:302377ブラウズ

JavaのダイナミックプロキシについてはJava APIで説明しているのでここでは書きません。私が理解しているプロキシ:

特定のインターフェースの特定のメソッドの機能を拡張するのがプロキシです。プロキシは、プロキシ インスタンスに関連付けられた呼び出しハンドラー オブジェクトを通じてメソッドを呼び出します。

例を見てみましょう:

インターフェース:

public interface Num {
    void show();
    
    int getNum();
    
    int getProduct(int x);
}

実装クラス:

public class MyNum implements Num {
    @Override
    public int getNum() {
        return 3;
    }
    
    @Override
    public int getProduct(int x) {
        return x;
    }

    @Override
    public void show() {
        System.out.println("底层方法打印数字99");
    }
}

まず、Method の invoke メソッドが API でどのように記述されているかを見てみましょう

Java動的プロキシを実装する2つの方法

つまり、ハンドラーインターフェイス上で呼び出されます。実装クラス オブジェクトは、Method オブジェクトによって表される基礎となるメソッドを呼び出します。

プロキシを実装する最初の方法:

public class NumProxy {
    private Object num;

  //通过构造方法构造接口的实现类对象
    public NumProxy(Object num) {
        this.num = num;
    }

    public Object getNumByProxy(){
        Object numProxy =  Proxy.newProxyInstance(num.getClass().getClassLoader(), new Class[]{Num.class}, new InvocationHandler() {
            /**
             * method: 对应于在代理实例上调用的接口方法的 Method 实例。我理解的就是被代理的真实方法实例
             * args: 我理解的是真实方法的参数数组
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                Object obj = null;
                System.out.println("在方法之前开始记录");
                String methodName = method.getName();
                if("getProduct".equals(methodName)){
                    obj = method.invoke(num, args);
                    obj = (Integer) obj * 2;
                    System.out.println("proxy: getProduct()结束");
                }
                else if("show".equals(methodName)){
                    obj = method.invoke(num, args);
                    System.out.println("proxy: show()结束");
                }
                return obj;
            }
        });
        return numProxy;
    }
}

プロキシを実装する 2 番目の方法: InvocationHandler インターフェイスを実装することによる

public class NumProxyImpl implements InvocationHandler {
  //这里我把接口类型具体化了, 没有写成Object
    private Num num;
    
    public NumProxyImpl(Num num){
        this.num = num;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object obj = null;
        String methodName = method.getName();
        if("getProduct".equals(methodName)){
            System.out.println("proxy: getProduct()开始");
            obj = method.invoke(num, args);
            obj = (Integer) obj * 2;
            System.out.println("proxy: getProduct()结束");
        }else if("show".equals(methodName)){
            System.out.println("proxy: show()开始");
            obj = method.invoke(num, args);
            System.out.println("proxy: show()结束");
        }
        return obj;
    }
}

テスト コード:

public class TestNum {
    public static void main(String[] args) {
    //两种方式一起测试
        NumProxy np = new NumProxy(new MyNum());
        Num numProxy = (Num) np.getNumByProxy();
        int x = numProxy.getProduct(2);
        System.out.println(x);
        numProxy.show();
        
        System.out.println("----------------");
        NumProxyImpl npi = new NumProxyImpl(new MyNum());
        Num numPro = (Num) Proxy.newProxyInstance(Num.class.getClassLoader(), new Class[]{Num.class}, npi);
        int n = numPro.getProduct(3);
        System.out.println(n);
        numPro.show();
    }
}

コンソールの結果:

Java動的プロキシを実装する2つの方法

2 番目の方法は少し混乱します, お持ちかどうかはわかりませんが、NumProxyImpl の invoke メソッドは明示的に呼び出されているわけではありませんが、実行されます。うーん、自分で調べてみてください

面倒な場合は覚えておいてください。

例えば、エンコード処理にプロキシを使用することができます。次回は例を書きます。


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