前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring对象解析及注册(二)

Spring对象解析及注册(二)

作者头像
OPice
发布2019-10-24 02:34:38
4130
发布2019-10-24 02:34:38
举报
文章被收录于专栏:D·技术专栏D·技术专栏

标签解析

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

代码语言:javascript
复制
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() 看下时序图

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

默认标签处理

代码语言:javascript
复制
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

代码语言:javascript
复制
/**
     * 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加载完成

自定义标签处理

代码语言:javascript
复制
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解析和注册的代码和结构大体有了了解。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.10.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 标签解析
    • 默认标签处理
      • 自定义标签处理
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档