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 でどのように記述されているかを見てみましょう
つまり、ハンドラーインターフェイス上で呼び出されます。実装クラス オブジェクトは、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(); } }
コンソールの結果:
2 番目の方法は少し混乱します, お持ちかどうかはわかりませんが、NumProxyImpl の invoke メソッドは明示的に呼び出されているわけではありませんが、実行されます。うーん、自分で調べてみてください
面倒な場合は覚えておいてください。
例えば、エンコード処理にプロキシを使用することができます。次回は例を書きます。