1. 程式人生 > >java 動態代理 為什麼在debug 時會多次執行invoke 內部方法

java 動態代理 為什麼在debug 時會多次執行invoke 內部方法

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]