再看Proxy.newProxyInstance与InvocationHandler
public static Object Proxy::newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
*/
为指定得一些接口返回一个代理类实例,该实例分发方法调用到指定的invocation handler
public Object InvocationHandler::invoke(Object proxy, Method method, Object[] args)
proxy参数就是newProxyInstance返回值,method为interfaces中的某个方法,args为方法参数
返回值作为方法的返回值
精简代码测验
public interface BrandMapper {
List getAll();
}
public class MapperProxy<T> implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
System.out.println("进入代理1:" + method);
System.out.println("进入代理2:" + proxy);
//将逻辑委托给真正的实现
method.invoke(new DefaultBrandMapper(),args);
return null;
}
@Override
public String toString() {
System.out.println("MapperProxy toString");
return "111";
}
}
public class ProxyTestBrief {
public static void main(String[] args) {
MapperProxy<BrandMapper> invocationHandler = new MapperProxy();
BrandMapper brandMapper = (BrandMapper) Proxy.newProxyInstance(BrandMapper.class.getClassLoader(), new Class[]{BrandMapper.class},invocationHandler);
brandMapper.getAll();
}
}
测试1--注释到MapperProxy的toString方法
断点测试执行到System.out.println("进入代理2:" + proxy)时,程序再次进入invoke方法,因为在代理实例上执行的方法都被分发给了invocationHandler的invoke接口,此时if条件生效,执行方法toString为顶层Object实例接口,方法调用转为invocationHandler的方法
灵魂拷问--若把if注释掉会怎样
System.out.println("进入代理2:" + proxy)会一直调用invoke方法,栈溢出,在mybatis源码中的出现
虽然源码没有打印,但对源码某行debug触发toString时,若没有这样if判断就会一直调用下去