spring源码(十一)--DefaultBeanDefinitionDocumentReader(spring配置文件解析)

DefaultBeanDefinitionDocumentReader的类层次图:
DefaultBeanDefinitionDocumentReader


接口中定义了一个方法,注册xml中的bean

public interface BeanDefinitionDocumentReader {
    void registerBeanDefinitions(Document var1, XmlReaderContext var2) throws BeanDefinitionStoreException;
}

子类实现:

//readerContext一般是XmlReaderContext,在XmlBeanDefinitionReader中创建
 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        this.doRegisterBeanDefinitions(root);
    }

主要内容:

  1. 获取delegate,看看有没有委托的reader(默认一般是没有的)
  2. 然后创建BeanDefinitionParserDelegate,赋值给delegate
  3. 使用delegate判断root(根节点一般是beans)节点是不是默认命名空间的
  4. 看看根节点的profile属性,是不是可以被接受的,如果不被接受,则直接返回。在beans上加profile属性,可以指定dev或者production模式。可以用于数据库配置。在web.xml中指定项目的模式。
  5. 开始解析document
  6. 是默认命名空间的节点,由当前类解析,否则由delegate解析
protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = this.createDelegate(this.getReaderContext(), root, parent);
        //创建的是BeanDefinitionParserDelegate
        if(this.delegate.isDefaultNamespace(root)) {//判断根节点是不是默认命名空间,如果是,获取应用环境
            String profileSpec = root.getAttribute("profile");
            if(StringUtils.hasText(profileSpec)) {//判断这个节点的应用环境是不是符合要求,比如是不是生产环境,如果不是,则不解析这个root节点下的内容
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; ");
                if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if(this.logger.isInfoEnabled()) {
                        this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource());
                    }

                    return;
                }
            }
        }

        this.preProcessXml(root);//默认空
        this.parseBeanDefinitions(root, this.delegate);
        this.postProcessXml(root);//默认空
        this.delegate = parent;
    }

从根节点开始遍历

 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if(delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();

            for(int i = 0; i < nl.getLength(); ++i) {
                Node node = nl.item(i);
                if(node instanceof Element) {
                    Element ele = (Element)node;
                    if(delegate.isDefaultNamespace(ele)) {
                        this.parseDefaultElement(ele, delegate);
                    } else {
                        delegate.parseCustomElement(ele);//委托解析
                    }
                }
            }
        } else {
            delegate.parseCustomElement(root);
        }

    }

如果是默认命名空间的节点:
默认命名空间http://www.springframework.org/schema/beans

 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if(delegate.nodeNameEquals(ele, "import")) {//等价于新解析一个配置文件
            this.importBeanDefinitionResource(ele);
        } else if(delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if(delegate.nodeNameEquals(ele, "bean")) {//使用BeanDefinitionParserDelegate解析
            this.processBeanDefinition(ele, delegate);
        } else if(delegate.nodeNameEquals(ele, "beans")) {//一般根节点就是这个节点,如果是,则遍历解析子节点
            this.doRegisterBeanDefinitions(ele);
        }

    }

不是默认命名空间,由BeanDefinitionParserDelegate解析。

 public BeanDefinition parseCustomElement(Element ele) {
        return this.parseCustomElement(ele, (BeanDefinition)null);
    }

所以最后实际的能有产出的解析工作,是由BeanDefinitionParserDelegate完成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值