zoukankan      html  css  js  c++  java
  • Spring5源码分析(011)——IoC篇之解析bean标签总览

    注:《Spring5源码分析》汇总可参考:Spring5源码分析(002)——博客汇总


      前面用 3 篇文章的篇幅阐述了 BeanDefinition 的整体的解析过程。在《Spring5源码分析(010)——IoC篇之加载BeanDefinition:解析和注册BeanDefinition》中提到过 Spring 中的标签包括默认标签和自定义标签两种,而这两种标签的用法以及解析方式存在着很大的不同:

    • 默认标签解析:DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
    • 自定义标签解析:BeanDefinitionParserDelegate.parseCustomElement(Element ele)

      接下来将先从默认标签的解析过程开始进行分析。代码如下:

    public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
    public static final String NESTED_BEANS_ELEMENT = "beans";
    public static final String ALIAS_ELEMENT = "alias";
    public static final String IMPORT_ELEMENT = "import";
    
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {    // import 标签
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {    // alias 标签
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {    // bean 标签
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {        // beans 标签,需要递归解析
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

      可以看到,这里一共涉及 import、alias、bean、beans 4 种标签:

    • import 标签主要是导入其他的 XML 配置文件,这需要定位加载资源文件然后又从头开始(递归)解析;
    • alias 标签主要是 bean 定义的别名;
    • beans 标签则直接递归解析;
    • 最复杂且最为重要的就是 bean 标签,集中了基本上所有的 bean 定义信息。

      接下来的博客会从 bean 标签的解析方法 DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) 开始深入分析,如果能理解此标签的解析过程,其他标签的解析自然会迎刃而解,代码如下:

    /**
     * Process the given bean element, parsing the bean definition
     * and registering it with the registry.
     * <p>处理给定的 bean 元素,解析 bean 定义并将其注册到 registry 中
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // 1、委托 BeanDefinitionParserDelegate 进行元素解析。解析成功,则返回的 BeanDefinitionHolder 实例
        // 已经包含配置文件中配置的各种属性,例如 class 、 name 、 id 、 alias 之类的属性。
        // 解析失败,则返回为 null
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            // 2、自定义标签解析(若默认标签下有自定义标签)
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // 3、注册 BeanDefinition
                // Register the final decorated instance.
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // 4、发出响应事件,通知相关的监听器,完成 bean 加载
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

      从代码实现来看,整个过程可分为 4 个步骤:

    • 1、首先委托 BeanDefinitionParserDelegate.parseBeanDefinitionElement(Element ele) 方法进行元素解析,返回 BeanDefinitionHolder 实例对象 bdHolder ,即 解析 BeanDefinition 。
      • 如果解析成功,则 bdHolder 实例已经包含配置文件的各种属性,例如 class 、 name 、 id 、 alias 之类的属性。
        • BeanDefinitionHolder 内部有 beanDefinition 、 beanName 、 aliases 3 个属性,而其中的 beanDefinition 则是 bean 的具体定义。
      • 如果解析失败,则 bdHolder 实例为 null 。
    • 2、当返回的 bdHolder 不为空时,若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析。
    • 3、解析完成后,委托 BeanDefinitionReaderUtils.registerBeanDefinition(...) 方法对解析后的 bdHolder 进行 BeanDefinition 的注册。
    • 4、发出响应事件,通知相关的监听器,完成 bean 加载。

    时序图如下:

    注:时序图来自插件 Sequence Diagram

      接下来的文章将分别对这4个步骤进行详细的分析:

    (未完待续。。。)


    参考

  • 相关阅读:
    安装spark-1.5遇到的一些问题
    spark遇到的一些问题及其解决办法
    spark-client 一直 accepted,无法提交任务,报错Failed to connect to driver at
    spark-sql用hive表格,在spark-submit运行jar包时遇到的问题
    hive streaming 使用的时候的一些心得
    [BZOJ]1063 道路设计(Noi2008)
    PKUWC2018划水记
    [BZOJ]3527 力(ZJOI2014)
    [Codeforces]906D Power Tower
    [BZOJ]1071 组队(SCOI2007)
  • 原文地址:https://www.cnblogs.com/wpbxin/p/13534362.html
Copyright © 2011-2022 走看看