dubbo源码阅读-ProxyFactory(十一)之JdkProxyFactory
接口定义
/** * ProxyFactory. (API/SPI, Singleton, ThreadSafe) */ @SPI("javassist") //缺省值是javasist public interface ProxyFactory { /** * create proxy. * 需要带有proxy key * @param invoker * @return proxy */ @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; /** * create proxy. * 需要带有proxy key * @param invoker * @return proxy */ @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException; /** * create invoker. * 需要带有proxy key * @param <T> * @param proxy * @param type * @param url * @return invoker */ @Adaptive({Constants.PROXY_KEY}) <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException; }
类图
说明
//<1>创建代理类 return (T) proxyFactory.getProxy(invoker);
https://www.cnblogs.com/LQBlog/p/12502317.html#autoid-3-2-0
//<6> Exporter<?> exporter.export( proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
https://www.cnblogs.com/LQBlog/p/12469007.html#autoid-6-14-0
在之前代码 我们常常看到这样的代码 java提供2种代理 一种是通过jdk代理 一种是javasist动态生成class字符串 编译成class类
AbstractProxyFactory
<2>getProxy
//<2> @Override public <T> T getProxy(Invoker<T> invoker) throws RpcException { //<3>非泛型化接口 return getProxy(invoker, false); }
<3>getProxy
@Override public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException { Class<?>[] interfaces = null; //获取配置的interfaces 暂时不知道这个是干嘛的 String config = invoker.getUrl().getParameter("interfaces"); if (config != null && config.length() > 0) { //,号分割 String[] types = Constants.COMMA_SPLIT_PATTERN.split(config); if (types != null && types.length > 0) { interfaces = new Class<?>[types.length + 2]; //获取invoker也就是我们配置的服务接口 interfaces[0] = invoker.getInterface(); //设置回声测试interface interfaces[1] = EchoService.class; for (int i = 0; i < types.length; i++) { //后去class interfaces[i + 1] = ReflectUtils.forName(types[i]); } } } //增加回声测试 和我们的服务接口calass if (interfaces == null) { interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class}; } //如果配置了回声测试 但是并没有声明是回声测试 设置回声测试接口 if (!invoker.getInterface().equals(GenericService.class) && generic) { int len = interfaces.length; Class<?>[] temp = interfaces; interfaces = new Class<?>[len + 1]; System.arraycopy(temp, 0, interfaces, 0, len); interfaces[len] = GenericService.class; } //<4>返回指定接口的代理 由子类实现 模板方法模式 return getProxy(invoker, interfaces); }
JdkProxyFactory
<4>getProxy
@Override @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { //<5>jdk代理 通过InvokerInvocationHandler代理 return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker)); }
<6>getInvoker
/** * proxy为我们的代理对象 type为我们的接口 url为我们的发布和订阅协议 * 包装成Invoker对象 * @param proxy * @param type * @param url * @param <T> * @return */ @Override public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { return new AbstractProxyInvoker<T>(proxy, type, url) { @Override protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable { Method method = proxy.getClass().getMethod(methodName, parameterTypes); return method.invoke(proxy, arguments); } }; }
<5>InvokerInvocationHandler
/** * InvokerHandler */ public class InvokerInvocationHandler implements InvocationHandler { private final Invoker<?> invoker; public InvokerInvocationHandler(Invoker<?> handler) { this.invoker = handler; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); //如果当前method是Object直接调用 if (method.getDeclaringClass() == Object.class) { return method.invoke(invoker, args); } //toString hashCode equals 直接调用object的 // 基础方法,不使用 RPC 调用 if ("toString".equals(methodName) && parameterTypes.length == 0) { return invoker.toString(); } if ("hashCode".equals(methodName) && parameterTypes.length == 0) { return invoker.hashCode(); } if ("equals".equals(methodName) && parameterTypes.length == 1) { return invoker.equals(args[0]); } //走RPC return invoker.invoke(new RpcInvocation(method, args)).recreate(); } }
配置例子
dubbo.application.parameters['proxy']=jdk