Dubbo源码分析之一:spring集成之xml

 2019-11-23 11:13  阅读(998)
文章分类:Spring Cloud

关于dubbo与spring 的集成有俩种方式:xml配置文件,注解。相关代码主要集中在dubbo-config-spring 包中。

xml配置文件方式的处理

spring 在启动时,找到dubbo命名空间的处理类。

META-INF/spring.handlers

内容

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

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

        static {
           //检查重复
               Version.checkDuplicate(DubboNamespaceHandler.class);
        }

        public void init() {
                // 注册xml元素解析器
               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 ,实现了spring 的 BeanDefinitionParser接口

这里要吐槽一下,所有的解析都在一个方法中,有点乱!

public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) {
            this.beanClass = beanClass; //元素对应的配置类
            this.required = required; // 是否必须
        }

    // 最终的解析方法
    // element xml元素
    // parserContext 解析上下文
    // beanClass element对应的Class
    // required 是否必须
    private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
            
                   // 配置bean定义
                   RootBeanDefinition beanDefinition = new RootBeanDefinition();
            beanDefinition.setBeanClass(beanClass);
            beanDefinition.setLazyInit(false); //默认不延迟
            String id = element.getAttribute("id");
            if ((id == null || id.length() == 0) && required) {
                          // 确定bean 名称
                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 ++);
                }
            }
            if (id != null && id.length() > 0) {
                if (parserContext.getRegistry().containsBeanDefinition(id))  {
                    throw new IllegalStateException("Duplicate spring bean id " + id); // 如果ID重复
                }
                parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); // 注入spring
                beanDefinition.getPropertyValues().addPropertyValue("id", id);
            }
            if (ProtocolConfig.class.equals(beanClass)) { //配置 ProtocolConfig
                             //在spring中 将 protocol 注入所有需要的bean中 
                 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())) {
                           // 设置protocol属性    
                                               definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
                        }
                    }
                }
            } else if (ServiceBean.class.equals(beanClass)) {
                           // 待暴露的服务
                String className = element.getAttribute("class");
                if(className != null && className.length() > 0) { //如果指定了class
                    RootBeanDefinition classDefinition = new RootBeanDefinition();
                    classDefinition.setBeanClass(ReflectUtils.forName(className));
                    classDefinition.setLazyInit(false);
                    parseProperties(element.getChildNodes(), classDefinition); //解析服务属性
                                   // 将服务关联到ServiceBean
                    beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
                }
            } else if (ProviderConfig.class.equals(beanClass)) { // 处理提供者
                parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
            } 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];
                                   // setter名处理 (uvwXyz -> uvw-xyz)
                    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); // 解析parameters
                    } 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) { // 多个registry   
                                 parseMultiRef("registries", value, beanDefinition, parserContext);  
                              } else if ("provider".equals(property) && value.indexOf(',') != -1) { // 多个provider属性   
                                 parseMultiRef("providers", value, beanDefinition, parserContext);         
                       } else if ("protocol".equals(property) && value.indexOf(',') != -1) { // 多个protocol属性 
                                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())) { // 不建议使用dubbo:provider
                                          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);
                                }
                            }
                        }
                    }
                }

            
              }

       // 将节点中的属性,全部设置到beanDefinition中
     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.getPropertyValues().addPropertyValue("parameters", parameters);       
     }        
    return beanDefinition;   
     }

来源:http://ddrv.cn/a/88268

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Dubbo源码分析之一:spring集成之xml

相关推荐