专栏首页D·技术专栏Spring对象解析及注册(二)

Spring对象解析及注册(二)

标签解析

前面对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() 看下时序图

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解析和注册的代码和结构大体有了了解。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 多线程之并发容器

    使用concurrentHashMap之前先了解一下HashMap,在该文章中会看到HashMap在并发场景下是不安全的。ConcurrentHash(1.8)...

    OPice
  • Spring之对象解析及注册(一)

    首先看下new XmlBeanFactory(new ClassPathResource("beans.xml"))这行代码

    OPice
  • 单元测试

      每个开发人员都写过很多代码、函数,但是你能保证你写的每个函数都能执行并且正常吗?   我们太多时间站在功能需求的角度来审视我们的代码,认为需求实现功能逻辑...

    OPice
  • mysql 层级结构查询

    描述:最近遇到了一个问题,在mysql中如何完成节点下的所有节点或节点上的所有父节点的查询? 在Oracle中我们知道有一个Hierarchical Queri...

    用户1217611
  • 小程序开发采的几个坑

    如果我们使用的是自定义导航模式(navigationStyle: 'custom'),一般则需要通过此函数来获取菜单按钮的信息:

    IMWeb前端团队
  • ISLR_Propotion

    逻辑 sampling variability CLT for propotions sampling distribution CLT for propot...

    用户1147754
  • 一文看尽10篇目标检测最新论文(SpineNet/AugFPN/LRF-Net/SABL/DSFPN等)

    一周前 Amusi 整理了 目标检测(Object Detection)较为值得关注的论文:

    Amusi
  • 测试中的图

    我们首先介绍如何从软件当中产生图及图的基本定义。图当中,如何去选择它的路径,如何产生测试路径。 曾经有人说过,所谓软件测试,就是把软件变成一张图,然后覆盖它。由...

    归根落叶
  • Rx实现自定义类Delegate

    事情不多主要是讲讲Rx如何自定义代理,为啥要将这个只要是iOS中太多的delegate 话不多说我们先来代码

    大话swift
  • 数据安全实践之数据资产管理

    在企业安全建设中,资产管理是很多安全工作的基础。而数据资产管理可以帮助我们更准确的发现安全风险,执行更有效的控制措施,在数据安全体系化建设中也有着举足轻重的作用...

    FB客服

扫码关注云+社区

领取腾讯云代金券