zoukankan      html  css  js  c++  java
  • Dubbo源码解析(一)之配置解析篇

    正文
    分析dubbo源码需要读者对Spring自定义标签解析的知识有所了解,可以阅读笔者相关文章进行学习,详见http://blog.csdn.net/heroqiang/article/details/78611213。

    文章中介绍的一些配置的使用我们可以从http://dubbo.apache.org/zh-cn/ API官方文档中找到详细说明。我们从dubbo标签的解析开始分析源码:
    DubboNamespaceHandler:

    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));
    }

    我们看到,dubbo的各个标签都是通过DubboBeanDefinitionParser来解析的,我们来分析解析的过程:
    DubboBeanDefinitionParser:

    public BeanDefinition parse(Element element, ParserContext parserContext) {
    /* 解析 */
    return parse(element, parserContext, beanClass, required);
    }

    DubboBeanDefinitionParser:

    package com.alibaba.dubbo.common.utils;

    /**
    * dubbo-parent
    *
    * @作者: lanxu
    * @日期: 2021-09-13 11:27
    * @描述:
    */
    public class DubboBeanDefinitionParser {
    private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
    RootBeanDefinition beanDefinition = new RootBeanDefinition();
    beanDefinition.setBeanClass(beanClass); // 根据构造方法传入的类型设置beanClass
    beanDefinition.setLazyInit(false); // 设置懒加载为false
    String id = element.getAttribute("id");
    // 如果id属性为空,并且构造方法传入的required为true
    if ((id == null || id.length() == 0) && required) {
    // 生成的beanName默认为name属性值
    String generatedBeanName = element.getAttribute("name");
    // 如果name属性为空
    if (generatedBeanName == null || generatedBeanName.length() == 0) {
    if (ProtocolConfig.class.equals(beanClass)) {
    // 如果解析的是<dubbo:protocol/>标签,设置beanName为dubbo
    generatedBeanName = "dubbo";
    } else {
    // 否则beanName赋值为interface属性值
    generatedBeanName = element.getAttribute("interface");
    }
    }
    if (generatedBeanName == null || generatedBeanName.length() == 0) {
    // 如果beanName还是为空,则将其设置为beanClass的名称
    generatedBeanName = beanClass.getName();
    }
    id = generatedBeanName; // 将beanName赋值给id
    int counter = 2;
    // 循环判断如果当前Spring上下文中包含当前id,则将id拼接递增数字后缀
    while (parserContext.getRegistry().containsBeanDefinition(id)) {
    id = generatedBeanName + (counter++);
    }
    }
    if (id != null && id.length() > 0) {
    // 如果到这里判断如果当前Spring上下文中包含当前bean id,则抛出bean id冲突的异常
    if (parserContext.getRegistry().containsBeanDefinition(id)) {
    throw new IllegalStateException("Duplicate spring bean id " + id);
    }
    // 注册BeanDefinition
    parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
    // 添加id属性值
    beanDefinition.getPropertyValues().addPropertyValue("id", id);
    }
    // <dubbo:protocol/>标签
    if (ProtocolConfig.class.equals(beanClass)) {
    for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
    BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
    PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
    // 遍历所有的BeanDefinition,判断是否有protocol属性
    if (property != null) {
    Object value = property.getValue();
    if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {
    // 如果有并且是ProtocolConfig类型则为其添加对当前bean id的依赖
    definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
    }
    }
    }
    // <dubbo:service/>标签
    } else if (ServiceBean.class.equals(beanClass)) {
    // 获取class属性
    String className = element.getAttribute("class");
    if (className != null && className.length() > 0) {
    // 构建配置的class的BeanDefinition
    RootBeanDefinition classDefinition = new RootBeanDefinition();
    // 设置beanClass
    classDefinition.setBeanClass(ReflectUtils.forName(className));
    classDefinition.setLazyInit(false);
    /* 解析<property/>子标签 */
    parseProperties(element.getChildNodes(), classDefinition);
    // 添加ServiceBean ref属性的依赖
    beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
    }
    // <dubbo:provider/>标签
    } else if (ProviderConfig.class.equals(beanClass)) {
    /* 解析嵌套的元素 */
    parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
    // <dubbo: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;
    // 遍历beanClass的方法
    for (Method setter : beanClass.getMethods()) {
    String name = setter.getName();
    // 判断是否是public的有参数的setter方法
    if (name.length() > 3 && name.startsWith("set")
    && Modifier.isPublic(setter.getModifiers())
    && setter.getParameterTypes().length == 1) {
    Class<?> type = setter.getParameterTypes()[0];
    // 将setter驼峰命名去掉set后转成-连接的命名,如setApplicationContext --> application-context
    String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");
    props.add(property);
    Method getter = null;
    try {
    // 获取对应属性的getter方法
    getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);
    } catch (NoSuchMethodException e) {
    try {
    // boolean类型的属性的getter方法可能以is开头
    getter = beanClass.getMethod("is" + name.substring(3), new Class<?>[0]);
    } catch (NoSuchMethodException e2) {
    }
    }
    // 如果没有getter方法或者getter方法不是public修饰符或者setter方法的参数类型与getter方法的返回值类型不同,直接忽略
    if (getter == null
    || !Modifier.isPublic(getter.getModifiers())
    || !type.equals(getter.getReturnType())) {
    continue;
    }
    if ("parameters".equals(property)) {
    /* parameters属性解析 */
    parameters = parseParameters(element.getChildNodes(), beanDefinition);
    } else if ("methods".equals(property)) {
    /* methods属性解析 */
    parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);
    } else if ("arguments".equals(property)) {
    /* arguments属性解析 */
    parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);
    } else {
    // 获取元素中的对应属性值
    String value = element.getAttribute(property);
    if (value != null) {
    value = value.trim();
    if (value.length() > 0) {
    // registry属性设置为N/A
    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中的默认值
    value = null;
    }
    reference = value;
    // protocol属性
    } 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;
    // onreturn属性
    } 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);
    // 添加onreturnMethod属性值
    beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);
    // onthrow属性
    } 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);
    // 添加onthrowMethod属性值
    beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);
    } else {
    // 校验ref属性依赖的bean必须是单例的
    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);
    }
    }
    }
    }
    }
    }
    // 排除掉上面解析过的,剩余的属性添加到parameters属性中
    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;
    }

    }
    DubboBeanDefinitionParser:
    private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDefinition) {
    if (nodeList != null && nodeList.getLength() > 0) {
    // 如果子节点不为null,遍历子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if (node instanceof Element) {
    // <property/>子标签
    if ("property".equals(node.getNodeName())
    || "property".equals(node.getLocalName())) {
    String name = ((Element) node).getAttribute("name"); // 提取name属性
    if (name != null && name.length() > 0) {
    // 提取value属性
    String value = ((Element) node).getAttribute("value");
    // 提取ref属性
    String ref = ((Element) node).getAttribute("ref");
    if (value != null && value.length() > 0) {
    // value不为null,添加对应属性值
    beanDefinition.getPropertyValues().addPropertyValue(name, value);
    } else if (ref != null && ref.length() > 0) {
    // ref不为null,添加对应属性依赖
    beanDefinition.getPropertyValues().addPropertyValue(name, new RuntimeBeanReference(ref));
    } else {
    throw new UnsupportedOperationException("Unsupported <property name="" + name + ""> sub tag, Only supported <property name="" + name + "" ref="..." /> or <property name="" + name + "" value="..." />");
    }
    }
    }
    }
    }
    }
    }

     DubboBeanDefinitionParser:

    private static void parseNested(Element element, ParserContext parserContext, Class<?> beanClass, boolean required, String tag, String property, String ref, BeanDefinition beanDefinition) {
    NodeList nodeList = element.getChildNodes();
    if (nodeList != null && nodeList.getLength() > 0) {
    boolean first = true;
    // 如果子节点不为null,遍历子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if (node instanceof Element) {
    // 判断节点名称是否与标签名称相同
    if (tag.equals(node.getNodeName())
    || tag.equals(node.getLocalName())) {
    if (first) {
    first = false;
    String isDefault = element.getAttribute("default");
    if (isDefault == null || isDefault.length() == 0) {
    // 如果第一个子节点default属性为null,则设置为false
    beanDefinition.getPropertyValues().addPropertyValue("default", "false");
    }
    }
    // 递归解析嵌套的子节点
    BeanDefinition subDefinition = parse((Element) node, parserContext, beanClass, required);
    if (subDefinition != null && ref != null && ref.length() > 0) {
    // 添加属性依赖
    subDefinition.getPropertyValues().addPropertyValue(property, new RuntimeBeanReference(ref));
    }
    }
    }
    }
    }
    }DubboBeanDefinitionParser:
    private static ManagedMap parseParameters(NodeList nodeList, RootBeanDefinition beanDefinition) {
    if (nodeList != null && nodeList.getLength() > 0) {
    ManagedMap parameters = null;
    // 如果子节点不为null,遍历子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if (node instanceof Element) {
    // 判断子节点名称是否是parameter
    if ("parameter".equals(node.getNodeName())
    || "parameter".equals(node.getLocalName())) {
    if (parameters == null) {
    parameters = new ManagedMap();
    }
    // 提取key属性值
    String key = ((Element) node).getAttribute("key");
    // 提取value属性值
    String value = ((Element) node).getAttribute("value");
    // 判断是否设置hide为true
    boolean hide = "true".equals(((Element) node).getAttribute("hide"));
    if (hide) {
    // 如果设置了hide为true,则为key增加.前缀
    key = Constants.HIDE_KEY_PREFIX + key;
    }
    parameters.put(key, new TypedStringValue(value, String.class));
    }
    }
    }
    return parameters;
    }
    return null;
    }
    DubboBeanDefinitionParser:
    private static void parseMethods(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
    ParserContext parserContext) {
    if (nodeList != null && nodeList.getLength() > 0) {
    ManagedList methods = null;
    // 如果子节点不为null,遍历子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if (node instanceof Element) {
    Element element = (Element) node;
    // 判断子节点名称是否是method
    if ("method".equals(node.getNodeName()) || "method".equals(node.getLocalName())) {
    // 提取name属性值
    String methodName = element.getAttribute("name");
    // name属性为null抛出异常
    if (methodName == null || methodName.length() == 0) {
    throw new IllegalStateException("<dubbo:method> name attribute == null");
    }
    if (methods == null) {
    methods = new ManagedList();
    }
    // 递归解析method子节点
    BeanDefinition methodBeanDefinition = parse(((Element) node),
    parserContext, MethodConfig.class, false);
    // 拼接name
    String name = id + "." + methodName;
    // 构造BeanDefinitionHolder
    BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(
    methodBeanDefinition, name);
    methods.add(methodBeanDefinitionHolder);
    }
    }
    }
    if (methods != null) {
    // 如果不为null,添加对应属性的依赖
    beanDefinition.getPropertyValues().addPropertyValue("methods", methods);
    }
    }
    }DubboBeanDefinitionParser:

     

    private static void parseArguments(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
    ParserContext parserContext) {
    if (nodeList != null && nodeList.getLength() > 0) {
    ManagedList arguments = null;
    // 如果子节点不为null,遍历子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
    Node node = nodeList.item(i);
    if (node instanceof Element) {
    Element element = (Element) node;
    // 判断子节点名称是否是argument
    if ("argument".equals(node.getNodeName()) || "argument".equals(node.getLocalName())) {
    // 提取index属性值
    String argumentIndex = element.getAttribute("index");
    if (arguments == null) {
    arguments = new ManagedList();
    }
    // 递归解析argument子节点
    BeanDefinition argumentBeanDefinition = parse(((Element) node),
    parserContext, ArgumentConfig.class, false);
    // 拼接name
    String name = id + "." + argumentIndex;
    // 构造BeanDefinitionHolder
    BeanDefinitionHolder argumentBeanDefinitionHolder = new BeanDefinitionHolder(
    argumentBeanDefinition, name);
    arguments.add(argumentBeanDefinitionHolder);
    }
    }
    }
    if (arguments != null) {
    // 如果不为null,添加对应属性的依赖
    beanDefinition.getPropertyValues().addPropertyValue("arguments", arguments);
    }
    }
    }
    DubboBeanDefinitionParser:
    private static void parseMultiRef(String property, String value, RootBeanDefinition beanDefinition,
    ParserContext parserContext) {
    // ,号分割value
    String[] values = value.split("\s*[,]+\s*");
    ManagedList list = null;
    for (int i = 0; i < values.length; i++) {
    String v = values[i];
    if (v != null && v.length() > 0) {
    if (list == null) {
    list = new ManagedList();
    }
    list.add(new RuntimeBeanReference(v));
    }
    }
    // 添加对应属性的依赖
    beanDefinition.getPropertyValues().addPropertyValue(property, list);
    }
    }
    到这里,dubbo配置解析的源码分析就完成了,方法看起来很繁琐,但内容还是很好理解的。
  • 相关阅读:
    js代码与html代码分离示例
    day24_Nginx学习笔记
    bookStore商城开发文档
    API Management Architecture Notes
    Taking A Fresh Look At What Open Source API Management Architecture Is Available
    使用API Gateway
    Qcon2017实录|Service Mesh:下一代微服务
    聊聊 API Gateway 和 Netflix Zuul
    项目长期运维中产生的一些问题
    忆情天书的由来
  • 原文地址:https://www.cnblogs.com/lanblogs/p/15261333.html
Copyright © 2011-2022 走看看