学习笔记之Dubbo源码分析

Dubbo源码分析

(个人学习笔记,如有错误欢迎指正!!!)

服务端启动:

首相服务端启动是通过 com.alibaba.dubbo.container.Main类中的 main()方法启动的:

public class App 
{
    public static void main( String[] args )
    {
        Main.main(args);
    }
}

main()方法中,主要的工作便是分析输入的参数,添加使用的容器,如果使用dubbo协议,默认使用的时Spring容器,然后循环遍历容器列表,并且调用容器的 start()方法,在container中的 start()方法只是创建了一个context,并且调用该context的 start()方法,之后便是Spring中bean加载的内容。

public static void main(String[] args) {
    try {
        if (args == null || args.length == 0) {
           ......
        }
        
        final List<Container> containers = new ArrayList<Container>();
        for (int i = 0; i < args.length; i ++) {
            containers.add(loader.getExtension(args[i]));
        }
        logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
        
        if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
         	......
        }
        
        for (Container container : containers) {
            container.start();
            logger.info("Dubbo " + container.getClass().getSimpleName() + " started!");
        }
        System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!");
    } catch (RuntimeException e) {
        e.printStackTrace();
        logger.error(e.getMessage(), e);
        System.exit(1);
    }
    synchronized (Main.class) {
        while (running) {
            try {
                Main.class.wait();
            } catch (Throwable e) {
            }
        }
    }
}

之后的操作便是根据定义的dubbo配置文件进行bean的加载工作,见后面

客户端启动

客户端的启动只是使用Spring的context获取提供服务的bean,然后调用相关的服务方法

dubbo配置加载

首先必须要了解的一点是Spring会自动加载jar包下面的 META-INF/spring.handlersMETA-INF/spring.schemas文件,

例如dubbo源码中,dubbo-config-spring模块中的 spring.handlers文件中内容:

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

该文件定义的是dubbo命名空间的解析类

dubbo-config-spring模块中的 spring.schemas文件中内容:

http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

该文件定义的是dubbo命名空间的定义

这里就解释了xml配置文件中如下部分内容:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
</beans>

通过上面的分析可知, com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler为dubbo配置文件的处理类,该类的 init()方法会在解析xml文件之前加载解析器时调用,该方法主要工作便是针对不同的element,注册不同的bean定义解析器

public void init() {
    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
       registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
       registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
       registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
       registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
       registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
       registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
       registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
       registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
       registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
   }

DubboBeanDefinitionParser类主要完成dubbo配置文件中bean的解析工作,其中最主要的方法便是 parse()方法:

private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
    //创建beanDefinition
    RootBeanDefinition beanDefinition = new RootBeanDefinition();
    beanDefinition.setBeanClass(beanClass);
    beanDefinition.setLazyInit(false);
    //获取定义的id
    String id = element.getAttribute("id");
    //如果没定义id
    if ((id == null || id.length() == 0) && required) {
       String generatedBeanName = element.getAttribute("name");
       if (generatedBeanName == null || generatedBeanName.length() == 0) {
           if (ProtocolConfig.class.equals(beanClass)) {
               generatedBeanName = "dubbo";
           } else {
               generatedBeanName = element.getAttribute("interface");
           }
       }
       if (generatedBeanName == null || generatedBeanName.length() == 0) {
          generatedBeanName = beanClass.getName();
       }
        id = generatedBeanName; 
        int counter = 2;
        while(parserContext.getRegistry().containsBeanDefinition(id)) {
            id = generatedBeanName + (counter ++);
        }
    }
    //如果定义了id
    if (id != null && id.length() > 0) {
        if (parserContext.getRegistry().containsBeanDefinition(id))  {
          throw new IllegalStateException("Duplicate spring bean id " + id);
       }
        parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
        beanDefinition.getPropertyValues().addPropertyValue("id", id);
    }
    //判断是否为protocol类
    if (ProtocolConfig.class.equals(beanClass)) {
        for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
            BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
            PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
            if (property != null) {
                Object value = property.getValue();
                if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
                    definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
                }
            }
        }
        //判断是否为service类
    } else if (ServiceBean.class.equals(beanClass)) {
        String className = element.getAttribute("class");
        if(className != null && className.length() > 0) {
            RootBeanDefinition classDefinition = new RootBeanDefinition();
            classDefinition.setBeanClass(ReflectUtils.forName(className));
            classDefinition.setLazyInit(false);
            parseProperties(element.getChildNodes(), classDefinition);
            beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
        }
        //判断是否为provider类
    } else if (ProviderConfig.class.equals(beanClass)) {
        parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
        //判断是否为consumer类
    } else if (ConsumerConfig.class.equals(beanClass)) {
        parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
    }
    //对节点的属性进行处理
    Set<String> props = new HashSet<String>();
    ManagedMap parameters = null;
    for (Method setter : beanClass.getMethods()) {
        String name = setter.getName();
        if (name.length() > 3 && name.startsWith("set")
                && Modifier.isPublic(setter.getModifiers())
                && setter.getParameterTypes().length == 1) {
            Class<?> type = setter.getParameterTypes()[0];
            String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");
            props.add(property);
            Method getter = null;
            try {
                getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);
            } catch (NoSuchMethodException e) {
                try {
                    getter = beanClass.getMethod("is" + name.substring(3), new Class<?>[0]);
                } catch (NoSuchMethodException e2) {
                }
            }
            if (getter == null 
                    || ! Modifier.isPublic(getter.getModifiers())
                    || ! type.equals(getter.getReturnType())) {
                continue;
            }
            if ("parameters".equals(property)) {
                parameters = parseParameters(element.getChildNodes(), beanDefinition);
            } else if ("methods".equals(property)) {
                parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);
            } else if ("arguments".equals(property)) {
                parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);
            } else {
                String value = element.getAttribute(property);
                if (value != null) {
                   value = value.trim();
                   if (value.length() > 0) {
                      if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {
                           RegistryConfig registryConfig = new RegistryConfig();
                           registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
                           beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);
                        } else if ("registry".equals(property) && value.indexOf(',') != -1) {
                         parseMultiRef("registries", value, beanDefinition, parserContext);
                        } else if ("provider".equals(property) && value.indexOf(',') != -1) {
                           parseMultiRef("providers", value, beanDefinition, parserContext);
                        } else if ("protocol".equals(property) && value.indexOf(',') != -1) {
                            parseMultiRef("protocols", value, beanDefinition, parserContext);
                        } else {
                            Object reference;
                            if (isPrimitive(type)) {
                                if ("async".equals(property) && "false".equals(value)
                                        || "timeout".equals(property) && "0".equals(value)
                                        || "delay".equals(property) && "0".equals(value)
                                        || "version".equals(property) && "0.0.0".equals(value)
                                        || "stat".equals(property) && "-1".equals(value)
                                        || "reliable".equals(property) && "false".equals(value)) {
                                    // 兼容旧版本xsd中的default值
                                    value = null;
                                }
                                reference = value;
                            } else if ("protocol".equals(property) 
                                    && ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)
                                    && (! parserContext.getRegistry().containsBeanDefinition(value)
                                            || ! ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
                                if ("dubbo:provider".equals(element.getTagName())) {
                                    logger.warn("Recommended replace <dubbo:provider protocol=\"" + value + "\" ... /> to <dubbo:protocol name=\"" + value + "\" ... />");
                                }
                                // 兼容旧版本配置
                                ProtocolConfig protocol = new ProtocolConfig();
                                protocol.setName(value);
                                reference = protocol;
                            } else if ("monitor".equals(property) 
                                    && (! parserContext.getRegistry().containsBeanDefinition(value)
                                            || ! MonitorConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
                                // 兼容旧版本配置
                                reference = convertMonitor(value);
                            } else if ("onreturn".equals(property)) {
                                int index = value.lastIndexOf(".");
                                String returnRef = value.substring(0, index);
                                String returnMethod = value.substring(index + 1);
                                reference = new RuntimeBeanReference(returnRef);
                                beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);
                            } else if ("onthrow".equals(property)) {
                                int index = value.lastIndexOf(".");
                                String throwRef = value.substring(0, index);
                                String throwMethod = value.substring(index + 1);
                                reference = new RuntimeBeanReference(throwRef);
                                beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);
                            } else {
                                if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {
                                    BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
                                    if (! refBean.isSingleton()) {
                                        throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value+ "\" scope=\"singleton\" ...>");
                                    }
                                }
                                reference = new RuntimeBeanReference(value);
                            }
                      beanDefinition.getPropertyValues().addPropertyValue(property, reference);
                        }
                   }
                }
            }
        }
    }
    NamedNodeMap attributes = element.getAttributes();
    int len = attributes.getLength();
    for (int i = 0; i < len; i++) {
        Node node = attributes.item(i);
        String name = node.getLocalName();
        if (! props.contains(name)) {
            if (parameters == null) {
                parameters = new ManagedMap();
            }
            String value = node.getNodeValue();
            parameters.put(name, new TypedStringValue(value, String.class));
        }
    }
    if (parameters != null) {
        //将各种属性的值添加到beanDefinition中
        beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);
    }
    //返回beanDefinition
    return beanDefinition;
}

Provider

对于dubbo配置文件中各个节点的定义,我们只针对service进行分析,因为该节点涉及到服务的发布,对于service的定义,主要由 com.alibaba.dubbo.config.spring.ServiceBean完成

该类实现了 org.springframework.beans.factory.InitializingBean接口,所以在bean初始化完成之后,会调用 afterPropertiesSet()方法:

public void afterPropertiesSet() throws Exception {
    //判断provider是否为空,如果为空会自动去设置,后面也是类似的
       if (getProvider() == null) {
           Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
           if (providerConfigMap != null && providerConfigMap.size() > 0) {
               Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
               if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
                       && providerConfigMap.size() > 1) { // 兼容旧版本
                   List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
                   for (ProviderConfig config : providerConfigMap.values()) {
                       if (config.isDefault() != null && config.isDefault().booleanValue()) {
                           providerConfigs.add(config);
                       }
                   }
                   if (providerConfigs.size() > 0) {
                       //设置provider
                       setProviders(providerConfigs);
                   }
               } else {
                   ProviderConfig providerConfig = null;
                   for (ProviderConfig config : providerConfigMap.values()) {
                       if (config.isDefault() == null || config.isDefault().booleanValue()) {
                           if (providerConfig != null) {
                               throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
                           }
                           providerConfig = config;
                       }
                   }
                   if (providerConfig != null) {
                       //设置provider
                       setProvider(providerConfig);
                   }
               }
           }
       }
    //判断application是否为空
       if (getApplication() == null
               && (getProvider() == null || getProvider().getApplication() == null)) {
           Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
           if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
               ApplicationConfig applicationConfig = null;
               for (ApplicationConfig config : applicationConfigMap.values()) {
                   if (config.isDefault() == null || config.isDefault().booleanValue()) {
                       if (applicationConfig != null) {
                           throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                       }
                       applicationConfig = config;
                   }
               }
               if (applicationConfig != null) {
                   setApplication(applicationConfig);
               }
           }
       }
    //判断module是否为空
       if (getModule() == null
               && (getProvider() == null || getProvider().getModule() == null)) {
           Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
           if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
               ModuleConfig moduleConfig = null;
               for (ModuleConfig config : moduleConfigMap.values()) {
                   if (config.isDefault() == null || config.isDefault().booleanValue()) {
                       if (moduleConfig != null) {
                           throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                       }
                       moduleConfig = config;
                   }
               }
               if (moduleConfig != null) {
                   setModule(moduleConfig);
               }
           }
       }
    //判断register是否为空
       if ((getRegistries() == null || getRegistries().size() == 0)
               && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
               && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
           Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
           if (registryConfigMap != null && registryConfigMap.size() > 0) {
               List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
               for (RegistryConfig config : registryConfigMap.values()) {
                   if (config.isDefault() == null || config.isDefault().booleanValue()) {
                       registryConfigs.add(config);
                   }
               }
               if (registryConfigs != null && registryConfigs.size() > 0) {
                   super.setRegistries(registryConfigs);
               }
           }
       }
    //判断monitor是否为空
       if (getMonitor() == null
               && (getProvider() == null || getProvider().getMonitor() == null)
               && (getApplication() == null || getApplication().getMonitor() == null)) {
           Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
           if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
               MonitorConfig monitorConfig = null;
               for (MonitorConfig config : monitorConfigMap.values()) {
                   if (config.isDefault() == null || config.isDefault().booleanValue()) {
                       if (monitorConfig != null) {
                           throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                       }
                       monitorConfig = config;
                   }
               }
               if (monitorConfig != null) {
                   setMonitor(monitorConfig);
               }
           }
       }
    //判断协议是否为空
       if ((getProtocols() == null || getProtocols().size() == 0)
               && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
           Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
           if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
               List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
               for (ProtocolConfig config : protocolConfigMap.values()) {
                   if (config.isDefault() == null || config.isDefault().booleanValue()) {
                       protocolConfigs.add(config);
                   }
               }
               if (protocolConfigs != null && protocolConfigs.size() > 0) {
                   super.setProtocols(protocolConfigs);
               }
           }
       }
    //判断path是否为空
       if (getPath() == null || getPath().length() == 0) {
           if (beanName != null && beanName.length() > 0 
                   && getInterface() != null && getInterface().length() > 0
                   && beanName.startsWith(getInterface())) {
               setPath(beanName);
           }
       }
    //发布服务
       if (! isDelay()) {
           export();
       }
   }

发布操作是在 export()方法中进行的,该方法是 ServiceBean的父类 ServiceConfig中的方法:

public synchronized void export() {
    if (provider != null) {
        if (export == null) {
            export = provider.getExport();
        }
        if (delay == null) {
            delay = provider.getDelay();
        }
    }
    if (export != null && ! export.booleanValue()) {
        return;
    }
    //如果延迟发布,创建一个线程然后sleep延迟时间,之后再发布
    if (delay != null && delay > 0) {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(delay);
                } catch (Throwable e) {
                }
                doExport();
            }
        });
        thread.setDaemon(true);
        thread.setName("DelayExportServiceThread");
        thread.start();
    } else {
        //直接发布
        doExport();
    }
}

该方法是在进行发布之前对服务的一些配置进行检查

protected synchronized void doExport() {
    if (unexported) {
        throw new IllegalStateException("Already unexported!");
    }
    if (exported) {
        return;
    }
    exported = true;
    if (interfaceName == null || interfaceName.length() == 0) {
        throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
    }
    //主要是对配置判断
    checkDefault();
    if (provider != null) {
        if (application == null) {
            application = provider.getApplication();
        }
        if (module == null) {
            module = provider.getModule();
        }
        if (registries == null) {
            registries = provider.getRegistries();
        }
        if (monitor == null) {
            monitor = provider.getMonitor();
        }
        if (protocols == null) {
            protocols = provider.getProtocols();
        }
    }
    if (module != null) {
        if (registries == null) {
            registries = module.getRegistries();
        }
        if (monitor == null) {
            monitor = module.getMonitor();
        }
    }
    if (application != null) {
        if (registries == null) {
            registries = application.getRegistries();
        }
        if (monitor == null) {
            monitor = application.getMonitor();
        }
    }
    if (ref instanceof GenericService) {
        interfaceClass = GenericService.class;
        generic = true;
    } else {
        try {
            interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
                    .getContextClassLoader());
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
        checkInterfaceAndMethods(interfaceClass, methods);
        checkRef();
        generic = false;
    }
    if(local !=null){
        if(local=="true"){
            local=interfaceName+"Local";
        }
        Class<?> localClass;
        try {
            localClass = ClassHelper.forNameWithThreadContextClassLoader(local);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
        if(!interfaceClass.isAssignableFrom(localClass)){
            throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceName);
        }
    }
    if(stub !=null){
        if(stub=="true"){
            stub=interfaceName+"Stub";
        }
        Class<?> stubClass;
        try {
            stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub);
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
        if(!interfaceClass.isAssignableFrom(stubClass)){
            throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName);
        }
    }
    checkApplication();
    checkRegistry();
    checkProtocol();
    appendProperties(this);
    checkStubAndMock(interfaceClass);
    if (path == null || path.length() == 0) {
        path = interfaceName;
    }
    //调用该方法
    doExportUrls();
}

在该方法中通过遍历协议列表,通过 doExportUrlsFor1Protocol()方法,对每种协议和注册中心的url进行发布

private void doExportUrls() {
    List<URL> registryURLs = loadRegistries(true);
    for (ProtocolConfig protocolConfig : protocols) {
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
    String name = protocolConfig.getName();
    //如果协议为空,默认使用dubbo协议
    if (name == null || name.length() == 0) {
        name = "dubbo";
    }
	//获取host
    String host = protocolConfig.getHost();
    if (provider != null && (host == null || host.length() == 0)) {
        host = provider.getHost();
    }
    boolean anyhost = false;
    //host如果不合法
    if (NetUtils.isInvalidLocalHost(host)) {
        anyhost = true;
        try {
            //获取本地host
            host = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            logger.warn(e.getMessage(), e);
        }
        //如果host仍然不合法
        if (NetUtils.isInvalidLocalHost(host)) {
            if (registryURLs != null && registryURLs.size() > 0) {
                for (URL registryURL : registryURLs) {
                    try {
                        Socket socket = new Socket();
                        try {
                            //连接到注册中心,然后通过socket获取host
                            SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
                            socket.connect(addr, 1000);
                            host = socket.getLocalAddress().getHostAddress();
                            break;
                        } finally {
                            try {
                                socket.close();
                            } catch (Throwable e) {}
                        }
                    } catch (Exception e) {
                        logger.warn(e.getMessage(), e);
                    }
                }
            }
            if (NetUtils.isInvalidLocalHost(host)) {
                host = NetUtils.getLocalHost();
            }
        }
    }
	//获取port
    Integer port = protocolConfig.getPort();
    if (provider != null && (port == null || port == 0)) {
        port = provider.getPort();
    }
    final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
    if (port == null || port == 0) {
        port = defaultPort;
    }
    if (port == null || port <= 0) {
        port = getRandomPort(name);
        if (port == null || port < 0) {
            port = NetUtils.getAvailablePort(defaultPort);
            putRandomPort(name, port);
        }
        logger.warn("Use random available port(" + port + ") for protocol " + name);
    }
    
	......
        
    // 导出服务
    String contextPath = protocolConfig.getContextpath();
    if ((contextPath == null || contextPath.length() == 0) && provider != null) {
        contextPath = provider.getContextpath();
    }
    URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);

    if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
            .hasExtension(url.getProtocol())) {
        url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
    }

    String scope = url.getParameter(Constants.SCOPE_KEY);
    //配置为none不暴露
    if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {

        //配置不是remote的情况下做本地暴露 (配置为remote,则表示只暴露远程服务)
        if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
            exportLocal(url);
        }
        //如果配置不是local则暴露为远程服务.(配置为local,则表示只暴露远程服务)
        if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){
            if (logger.isInfoEnabled()) {
                logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
            }
           	//判断注册中心列表是否为空
            if (registryURLs != null && registryURLs.size() > 0
                    && url.getParameter("register", true)) {
                //循环注册中心列表
                for (URL registryURL : registryURLs) {
                    url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
                    URL monitorUrl = loadMonitor(registryURL);
                    if (monitorUrl != null) {
                        url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
                    }
                    if (logger.isInfoEnabled()) {
                        logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                    }
                    //使用代理方式发布
                    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));

                    Exporter<?> exporter = protocol.export(invoker);
                    exporters.add(exporter);
                }
            } else {
                Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);

                Exporter<?> exporter = protocol.export(invoker);
                exporters.add(exporter);
            }
        }
    }
    this.urls.add(url);
}

Consumer

对于consumer的分析主要针对 ReferenceBean类进行分析,该类同样实现了 InitializingBean接口,所以,当bean初始化之后,会调用如下方法,该方法和ServiceBean类中的类似,都是判断相关的属性是否存在,不存在便进行设置

public void afterPropertiesSet() throws Exception {
    if (getConsumer() == null) {
        Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);
        if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
            ConsumerConfig consumerConfig = null;
            for (ConsumerConfig config : consumerConfigMap.values()) {
                if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    if (consumerConfig != null) {
                        throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config);
                    }
                    consumerConfig = config;
                }
            }
            if (consumerConfig != null) {
                setConsumer(consumerConfig);
            }
        }
    }
    if (getApplication() == null
            && (getConsumer() == null || getConsumer().getApplication() == null)) {
        Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
        if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
            ApplicationConfig applicationConfig = null;
            for (ApplicationConfig config : applicationConfigMap.values()) {
                if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    if (applicationConfig != null) {
                        throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                    }
                    applicationConfig = config;
                }
            }
            if (applicationConfig != null) {
                setApplication(applicationConfig);
            }
        }
    }
    if (getModule() == null
            && (getConsumer() == null || getConsumer().getModule() == null)) {
        Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
        if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
            ModuleConfig moduleConfig = null;
            for (ModuleConfig config : moduleConfigMap.values()) {
                if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    if (moduleConfig != null) {
                        throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                    }
                    moduleConfig = config;
                }
            }
            if (moduleConfig != null) {
                setModule(moduleConfig);
            }
        }
    }
    if ((getRegistries() == null || getRegistries().size() == 0)
            && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0)
            && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
        Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
        if (registryConfigMap != null && registryConfigMap.size() > 0) {
            List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
            for (RegistryConfig config : registryConfigMap.values()) {
                if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    registryConfigs.add(config);
                }
            }
            if (registryConfigs != null && registryConfigs.size() > 0) {
                super.setRegistries(registryConfigs);
            }
        }
    }
    if (getMonitor() == null
            && (getConsumer() == null || getConsumer().getMonitor() == null)
            && (getApplication() == null || getApplication().getMonitor() == null)) {
        Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
        if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
            MonitorConfig monitorConfig = null;
            for (MonitorConfig config : monitorConfigMap.values()) {
                if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    if (monitorConfig != null) {
                        throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                    }
                    monitorConfig = config;
                }
            }
            if (monitorConfig != null) {
                setMonitor(monitorConfig);
            }
        }
    }
    Boolean b = isInit();
    if (b == null && getConsumer() != null) {
        b = getConsumer().isInit();
    }
    if (b != null && b.booleanValue()) {
        getObject();
    }
}

此外,该类还实现了 FactoryBean,所以该类是一个工厂bean,根据Spring中的相关知识,可以知道获取该类的bean实际上获取的不是该类本身的实例,而是该工厂bean生产出来的bean,所以从 getObject()方法进行分析

public Object getObject() throws Exception {
    return get();
}

getObject()方法调用的是父类 ReferenceConfig类中的 get() 方法,get()方法中又调用了 init()方法,该方法主要是完成调用服务的bean的创建

public synchronized T get() {
    if (destroyed){
        throw new IllegalStateException("Already destroyed!");
    }
   if (ref == null) {
      init();
   }
   return ref;
}
private void init() {
	    if (initialized) {
	        return;
	    }
	    initialized = true;
    	if (interfaceName == null || interfaceName.length() == 0) {
    	    throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
    	}
    	// 获取消费者全局配置
    	checkDefault();
        appendProperties(this);
        if (getGeneric() == null && getConsumer() != null) {
            setGeneric(getConsumer().getGeneric());
        }
        if (ProtocolUtils.isGeneric(getGeneric())) {
            interfaceClass = GenericService.class;
        } else {
            try {
				interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
				        .getContextClassLoader());
			} catch (ClassNotFoundException e) {
				throw new IllegalStateException(e.getMessage(), e);
			}
            checkInterfaceAndMethods(interfaceClass, methods);
        }
        String resolve = System.getProperty(interfaceName);
        String resolveFile = null;
        if (resolve == null || resolve.length() == 0) {
	        resolveFile = System.getProperty("dubbo.resolve.file");
	        if (resolveFile == null || resolveFile.length() == 0) {
	        	File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
	        	if (userResolveFile.exists()) {
	        		resolveFile = userResolveFile.getAbsolutePath();
	        	}
	        }
	        if (resolveFile != null && resolveFile.length() > 0) {
	        	Properties properties = new Properties();
	        	FileInputStream fis = null;
	        	try {
	        	    fis = new FileInputStream(new File(resolveFile));
					properties.load(fis);
				} catch (IOException e) {
					throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e);
				} finally {
				    try {
                        if(null != fis) fis.close();
                    } catch (IOException e) {
                        logger.warn(e.getMessage(), e);
                    }
				}
	        	resolve = properties.getProperty(interfaceName);
	        }
        }
        if (resolve != null && resolve.length() > 0) {
        	url = resolve;
        	if (logger.isWarnEnabled()) {
        		if (resolveFile != null && resolveFile.length() > 0) {
        			logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
        		} else {
        			logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
        		}
    		}
        }
        if (consumer != null) {
            if (application == null) {
                application = consumer.getApplication();
            }
            if (module == null) {
                module = consumer.getModule();
            }
            if (registries == null) {
                registries = consumer.getRegistries();
            }
            if (monitor == null) {
                monitor = consumer.getMonitor();
            }
        }
        if (module != null) {
            if (registries == null) {
                registries = module.getRegistries();
            }
            if (monitor == null) {
                monitor = module.getMonitor();
            }
        }
        if (application != null) {
            if (registries == null) {
                registries = application.getRegistries();
            }
            if (monitor == null) {
                monitor = application.getMonitor();
            }
        }
        checkApplication();
        checkStubAndMock(interfaceClass);
        Map<String, String> map = new HashMap<String, String>();
        Map<Object, Object> attributes = new HashMap<Object, Object>();
        map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
        map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());
        map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
        if (ConfigUtils.getPid() > 0) {
            map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
        }
        if (! isGeneric()) {
            String revision = Version.getVersion(interfaceClass, version);
            if (revision != null && revision.length() > 0) {
                map.put("revision", revision);
            }

            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if(methods.length == 0) {
                logger.warn("NO method found in service interface " + interfaceClass.getName());
                map.put("methods", Constants.ANY_VALUE);
            }
            else {
                map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
            }
        }
        map.put(Constants.INTERFACE_KEY, interfaceName);
        appendParameters(map, application);
        appendParameters(map, module);
        appendParameters(map, consumer, Constants.DEFAULT_KEY);
        appendParameters(map, this);
        String prifix = StringUtils.getServiceKey(map);
        if (methods != null && methods.size() > 0) {
            for (MethodConfig method : methods) {
                appendParameters(map, method, method.getName());
                String retryKey = method.getName() + ".retry";
                if (map.containsKey(retryKey)) {
                    String retryValue = map.remove(retryKey);
                    if ("false".equals(retryValue)) {
                        map.put(method.getName() + ".retries", "0");
                    }
                }
                appendAttributes(attributes, method, prifix + "." + method.getName());
                checkAndConvertImplicitConfig(method, map, attributes);
            }
        }
        //attributes通过系统context进行存储.
        StaticContext.getSystemContext().putAll(attributes);
    	//通过该方法创建代理对象
        ref = createProxy(map);
    }

createProxy()方法的实现如下:

private T createProxy(Map<String, String> map) {
   URL tmpUrl = new URL("temp", "localhost", 0, map);
   final boolean isJvmRefer;
       if (isInjvm() == null) {
           if (url != null && url.length() > 0) { //指定URL的情况下,不做本地引用
               isJvmRefer = false;
           } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
               //默认情况下如果本地有服务暴露,则引用本地服务.
               isJvmRefer = true;
           } else {
               isJvmRefer = false;
           }
       } else {
           isJvmRefer = isInjvm().booleanValue();
       }
   
   if (isJvmRefer) {
      URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
      invoker = refprotocol.refer(interfaceClass, url);
           if (logger.isInfoEnabled()) {
               logger.info("Using injvm service " + interfaceClass.getName());
           }
   } else {
           if (url != null && url.length() > 0) { // 用户指定URL,指定的URL可能是点对点直连地址,也可能是注册中心URL
               String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
               if (us != null && us.length > 0) {
                   for (String u : us) {
                       URL url = URL.valueOf(u);
                       if (url.getPath() == null || url.getPath().length() == 0) {
                           url = url.setPath(interfaceName);
                       }
                       if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                           urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                       } else {
                           urls.add(ClusterUtils.mergeUrl(url, map));
                       }
                   }
               }
           } else { // 通过注册中心配置拼装URL
               List<URL> us = loadRegistries(false);
               if (us != null && us.size() > 0) {
                   for (URL u : us) {
                       URL monitorUrl = loadMonitor(u);
                       if (monitorUrl != null) {
                           map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                       }
                       urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                   }
               }
               if (urls == null || urls.size() == 0) {
                   throw new IllegalStateException("No such any registry to reference " + interfaceName  + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
               }
           }

           if (urls.size() == 1) {
               invoker = refprotocol.refer(interfaceClass, urls.get(0));
           } else {
               List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
               URL registryURL = null;
               for (URL url : urls) {
                   invokers.add(refprotocol.refer(interfaceClass, url));
                   if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                       registryURL = url; // 用了最后一个registry url
                   }
               }
               if (registryURL != null) { // 有 注册中心协议的URL
                   // 对有注册中心的Cluster 只用 AvailableCluster
                   URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 
                   invoker = cluster.join(new StaticDirectory(u, invokers));
               }  else { // 不是 注册中心的URL
                   invoker = cluster.join(new StaticDirectory(invokers));
               }
           }
       }

       Boolean c = check;
       if (c == null && consumer != null) {
           c = consumer.isCheck();
       }
       if (c == null) {
           c = true; // default true
       }
       if (c && ! invoker.isAvailable()) {
           throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
       }
       if (logger.isInfoEnabled()) {
           logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
       }
       // 创建服务代理
       return (T) proxyFactory.getProxy(invoker);
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值