概述
在分析服务暴露和服务引用的都提到ProxyFactory,它是Dubbo的代理工厂,只定义了两个方法。
- getInvoker,暴露服务时调用,将ref(真正的服务实现类)转化为Invoker
- getProxy,引用服务时调用,将Invoker对象转化为proxy代理对象
Invoker
Invoker 是 Dubbo 领域模型中非常重要的一个概念,很多设计思路都是向它靠拢。这就使得 Invoker 渗透在整个实现代码里,对于刚开始接触 Dubbo 的人,确实容易给搞混了。 下面我们用一个精简的图来说明最重要的两种 Invoker:服务提供 Invoker 和服务消费 Invoker:
上面是出自Dubbo的官方教程。
服务提供端的AbstractProxyInvoker,封装了真正的服务实现类,代理了它的方法。服务消费端的DubboInvoker等,封装了远程通信的逻辑。
Dubbo中对远程的调用是Invoker,调用服务真正的实现类也是Invoker。
ProxyFactory
Dubbo的代理工厂,Dubbo之所以能够宣传像调用本地服务一样调用远程服务,就是用它实现的。@SPI扩展接口,默认实现是JavassistProxyFactory,还有一个实现是JdkProxyFactory,最终都会被StubProxyFactoryWrapper包装。
@SPI("javassist")public interface ProxyFactory { /** * 服务引用时调用 * create proxy. * * @param invoker Protocol生成的Invoker * @return proxy */ @Adaptive({Constants.PROXY_KEY})T getProxy(Invoker invoker) throws RpcException; /** * 服务暴露时调用 * create invoker. * * @param * @param proxy Service对象 * @param type Service类型 * @param url * @return invoker */ @Adaptive({Constants.PROXY_KEY}) Invoker getInvoker(T proxy, Class type, URL url) throws RpcException;}
getInvoker
JavassistProxyFactory和JdkProxyFactory的返回的都是AbstractProxyInvoker,区别在于前者使用自动生成的类,包装了硬编码进行调用,后者则使用JDK反射机制进行调用。对于Dubbo来说都是Invoker,进行了统一的抽象,这样Dubbo框架就不需要关心服务的具体业务,全部交给AbstractProxyInvoker去封装。
真正调用服务的时候会执行Invoker#invoke(),而AbstractProxyInvoker会把调用转给真正的服务实现类。
JavassistProxyFactory
publicInvoker getInvoker(T proxy, Class type, URL url) { // TODO Wrapper类不能正确处理带$的类名 // TODO Wrapper cannot handle this scenario correctly: the classname contains '$' // proxy.getClass()返回的是实现类的Class,type是接口的Class // Wrapper对象对方法的调用进行了包装,没有使用反射, // Wrapper是使用javassist动态生成类才进行方法调用的包装 final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); return new AbstractProxyInvoker (proxy, type, url) { @Override protected Object doInvoke(T proxy, String methodName, Class [] parameterTypes, Object[] arguments) throws Throwable { return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments); } };}
某个Wrapper类的代码片段,没有用反射
public Object invokeMethod(Object var1, String var2, Class[] var3, Object[] var4) throws InvocationTargetException { DemoService var5; try { var5 = (DemoService)var1; } catch (Throwable var8) { throw new IllegalArgumentException(var8); } try { if ("sayHello".equals(var2) && var3.length == 1) { return var5.sayHello((String)var4[0]); } } catch (Throwable var9) { throw new InvocationTargetException(var9); } throw new NoSuchMethodException("Not found method \"" + var2 + "\" in class cre.dubbo.demo.DemoService.");}
JdkProxyFactory
publicInvoker getInvoker(T proxy, Class type, URL url) { return new AbstractProxyInvoker (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); } };}
getProxy
生成的代理类实现指定的服务接口(还会实现EchoService接口),因此消费端在使用代理对象的时候跟使用本地服务是一样的。JavassistProxyFactory和JdkProxyFactory的都使用到了InvokerInvocationHandler,
InvokerInvocationHandler它的作用是将消费端的调用转到内部的Invoker#invoke()上
JavassistProxyFactory
publicT getProxy(Invoker invoker, Class [] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));}
JdkProxyFactory
publicT getProxy(Invoker invoker, Class [] interfaces) { return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));}
InvokerInvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Class [] parameterTypes = method.getParameterTypes(); if (method.getDeclaringClass() == Object.class) { return method.invoke(invoker, args); } 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]); } // Invoker进行Rpc调用 return invoker.invoke(new RpcInvocation(method, args)).recreate();}
附录
参照: