dubbo源码分析13——服务本地暴露 exportLocal(url)

dubbo服务的本地暴露,显然是针对当服务消费者和服务提供者都在同一个jvm的进程内这种场景 。通常是发生在服务之间的调用的情况下。一种情况就是A服务调用B服务的情况,如果A服务和B服务都是在一个线程中进行服务暴露的,就是本地调用。  

下面先看本地暴露的源码:

 private void exportLocal(URL url) {
//这是本协议url示例:injvm://127.0.0.1/org.huxin.dubbo.test.user.service.UserInterface?anyhost=true&application=dubbo-provider&default.retries=0&default.timeout=5000&dubbo=2.8.4&generic=false&interface=org.huxin.dubbo.test.user.service.UserInterface&methods=getUserById,getUserList,updateUsers&organization=huxin&owner=programmer&pid=5964&retries=0&serialization=kryo&side=provider&timestamp=1513044127040
if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { URL local = URL.valueOf(url.toFullString()) .setProtocol(Constants.LOCAL_PROTOCOL) .setHost(NetUtils.LOCALHOST) .setPort(0); // ServiceClassHolder是用来保存当前服务接口实例ref对应的Class的,是一个简单的单例实现 ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));        //由于默认protocol是dubbo,所以此处的protocol应是com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol类的实例 Exporter<?> exporter = protocol.export( proxyFactory.getInvoker(ref, (Class) interfaceClass, local)); exporters.add(exporter); logger.info("Export dubbo service " + interfaceClass.getName() +" to local registry"); } }

根据上面的源码,我们只需搞清楚Invoker实例是如何产生的,Invoker是什么,以及DubboProtocol的export方法就可以分析清楚本地暴露的过程了。
1. proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
(1)首先是
proxyFactory的来历
ServiceConfig类中初始化时进行实例化:private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
根据之前对dubbo的SPI机制,这个proxyFactory当是com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory类的实例,也就是使用Javassist技术来产生Invoker对象。
ProxyFactory接口有两个方法:
<T> T getProxy(Invoker<T> invoker) throws RpcException; //供消费者使用

                     <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;  //服务提供者使用

       (2) JavassistProxyFactory实例的 getInvoker方法分析

       可以通过如下源码看出Invoker实例在被调用时实隙地是通过其内部的wrapper对象调用proxy对象来完成的 ,下面分析下这个方法传入的参数:

  •         第一个参数proxy传入是的ref变量  ,

           ref的定义:private T  ref; //接口实现类的引用  ,就是接口实现类的Class的实例 

            赋值的相关代码参见: http://www.cnblogs.com/hzhuxin/p/7677265.html  

  •      第二个参数 type  的定义是:private Class<?>            interfaceClass;  //也就是我们定义服务接口
  •      第三个参数url 比较理解,是由之前面的调用方法 doExportUrlsFor1Protocol(protocolConfig, registryURLs) 方法拼接出来的
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper类不能正确处理带$的类名
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName, 
                                      Class<?>[] parameterTypes, 
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
2. DubboProtocol的export方法分析:
因本方法比较重要,新开一篇进行分析 ,参见 http://www.cnblogs.com/hzhuxin/p/8228982.html
原文地址:https://www.cnblogs.com/hzhuxin/p/8022783.html