美文网首页
Spring对象解析及注册(二)

Spring对象解析及注册(二)

作者: OPice | 来源:发表于2019-10-22 15:36 被阅读0次

    标签解析

    前面对Spring解析对象的整体做些整理,下面进出核心方法registerBeanDefinitions

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                throws BeanDefinitionStoreException {
    
            try {
                Document doc = doLoadDocument(inputSource, resource);
                int count = registerBeanDefinitions(doc, resource);
                if (logger.isDebugEnabled()) {
                    logger.debug("Loaded " + count + " bean definitions from " + resource);
                }
                return count;
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
               ......
        }
    
    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
            //实例化BeanDefinitionDocumentReader
            BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
            //记录统计前BeanDefinition加载个数  
            int countBefore = getRegistry().getBeanDefinitionCount();
            //加载及注册Bean
            documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
            //记录本次加载的BeanDefinition个数
            return getRegistry().getBeanDefinitionCount() - countBefore;
        }
    

    registerBeanDefinitions 里执行了doRegisterBeanDefinitions() -> parseBeanDefinitions() 看下时序图


    image.png

    parseBeanDefinitions方法针对默认标签和自定义标签处理。

    默认标签处理

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
            if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
                importBeanDefinitionResource(ele);
            }
            else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
                processAliasRegistration(ele);
            }
            else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
                processBeanDefinition(ele, delegate);
            }
            else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
                // recurse
                doRegisterBeanDefinitions(ele);
            }
        }
    

    先看下Bean标签的处理:processBeanDefinition

    /**
         * Process the given bean element, parsing the bean definition
         * and registering it with the registry.
         */
        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
                try {
                    // 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);
                }
                // Send registration event.
                getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
        }
    

    其实上Spring源码很方便理解,每个功能方法都是下面的总纲。
    processBeanDefinition方法的大致逻辑
    1、BeanDefinitionParserDelegate进行元素解析,返回BeanDefinitionParserDelegate实例bdHolder,实例里已经有了id,class,alias等属性 。
    具体解析逻辑:BeanDefinitionParserDelegate.parseBeanDefinitionElement() -> parseBeanDefinitionElement() 针对不同标签处理
    2、如果实例不为空,若默认标签下子标签存在自定义标签,使用自定义标签处理
    3、对解析后的bdHolder注册(维护 beanName:beanDefinition的map)
    DefaultListableBeanFactory.registerBeanDefinition()
    4、最后发出响应事件,bean加载完成

    自定义标签处理

    public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
            //获取对应的命名空间
            String namespaceUri = getNamespaceURI(ele);
            if (namespaceUri == null) {
                return null;
            }
            //根据命名空间找到对应NamespaceHandler
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler == null) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                return null;
            }
              //调用自定义的NamespaceHandler进行解析
            return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
        }
    

    至此,Bean解析和注册的代码和结构大体有了了解。

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=200l148seo740

    相关文章

      网友评论

          本文标题:Spring对象解析及注册(二)

          本文链接:https://www.haomeiwen.com/subject/zelxvctx.html