java 動態代理 為什麼在debug 時會多次執行invoke 內部方法
阿新 • • 發佈:2019-01-09
java 動態代理 為什麼在debug 時會多次執行invoke 內部方法
最近被一個同事問道該問題,有些模糊了,前來驗證記錄下。
copy了一個網上例項進行驗證
package com.huilong.hrs.portal.study.amn.jdkpox; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author zhanghuilong * @desc * @since 2018/12/28 */ public class Test { public static void main(String args[]) { ProxyHandler proxy = new ProxyHandler(); //繫結該類實現的所有介面 Subject sub = (Subject) proxy.bind(new RealSubject()); sub.doSomething(); } } interface Subject { public void doSomething(); } class RealSubject implements Subject { @Override public void doSomething() { System.out.println("call doSomething()"); } } class ProxyHandler implements InvocationHandler { private Object tar; //繫結委託物件,並返回代理類 public Object bind(Object tar) { this.tar = tar; //繫結該類實現的所有介面,取得代理類 return Proxy.newProxyInstance(tar.getClass().getClassLoader(), tar.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable//不依賴具體介面實現 { Object result = null;//被代理的型別為Object基類 //這裡就可以進行所謂的AOP程式設計了 //在呼叫具體函式方法前,執行功能處理 System.out.println("======呼叫方法:" + method.getName() + "======"); System.out.println("proxy = [" + "before" + "]"); result = method.invoke(tar, args); System.out.println("proxy = [" + "after" + "]"); //在呼叫具體函式方法後,執行功能處理 return result; } }
DEBUG 啟動單步斷點,輸出結果如下:可以看出實際執行核心程式碼只有一處。
Connected to the target VM, address: '127.0.0.1:64388', transport: 'socket' ======呼叫方法:toString====== proxy = [before] proxy = [after] ======呼叫方法:toString====== proxy = [before] proxy = [after] ======呼叫方法:doSomething====== ======呼叫方法:toString====== proxy = [before] proxy = [after] proxy = [before] ======呼叫方法:toString====== proxy = [before] proxy = [after] call doSomething() ======呼叫方法:toString====== proxy = [before] proxy = [after] proxy = [after] ======呼叫方法:toString====== proxy = [before] proxy = [after] ======呼叫方法:toString====== proxy = [before] proxy = [after] ======呼叫方法:toString====== proxy = [before] proxy = [after] Disconnected from the target VM, address: '127.0.0.1:64388', transport: 'socket'
再看下正常啟動輸出結果:
======呼叫方法:doSomething======
proxy = [before]
call doSomething()
proxy = [after]