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]