Spring源码解析02:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析 (3)

Document是DOM的根节点,提供对文档数据访问的入口。

2.3 registerBeanDefinitions(Document doc, Resource resource)

功能概述: 解析DOM Document成容器的内部数据接口BeanDefinition并注册到容器内部。

/**
 * XmlBeanDefinitionReader
 **/

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
 // 已注册的BeanDefinition的数量
    int countBefore = getRegistry().getBeanDefinitionCount();
 // DOM Document->BeanDefinition,注册BeanDefinition至容器
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 返回此次注册新增的BeanDefinition数量
 return getRegistry().getBeanDefinitionCount() - countBefore;
}

知识点:

BeanDefinitionDocumentReader是接口,实际完成对DOM Document解析的是其默认实现类DefaultBeanDefinitionDoucumentReade。

createReaderContext(resource)创建XmlReaderContext上下文,包含了XmlBeanDefinitionReader读取器和NamespaceHandlerResolver 命名空间解析器。

3.1 registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

功能概述: 在此之前一直 是XML加载解析的准备阶段,在获取到Document对象之后就开始真正的解析了。

/**
 * DefaultBeanDefinitionDocumentReader
 **/

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
 this.readerContext = readerContext;
 doRegisterBeanDefinitions(doc.getDocumentElement());
}
3.2 doRegisterBeanDefinitions(Element root)

功能概述: 解析Element,DefaultBeanDefinitionDoucumentReader同样不具有解析Element的能力,委托给BeanDefinitionParserDelegate执行。

/**
 * DefaultBeanDefinitionDocumentReader
 **/

protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);
    ...
    // 解析前处理,留给子类实现
 preProcessXml(root);
 parseBeanDefinitions(root, this.delegate);
    // 解析后处理,留给子类实现
 postProcessXml(root);

 this.delegate = parent;
}

知识点:

preProcessXml和postProcessXml里代码是空的,这两个方法是面向子类设计的,设计模式中的模板方法,也可以说是Spring的一个扩展点,后面有机会可以深入下细节。

3.3 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

功能概述: 判别XML中Bean的声明标签是默认的还是自定义的,执行不同的解析逻辑。对于根节点或者子节点是默认命名空间采用parseDefaultElement,否则使用parseCustomElement对自定义命名空间解析。

/**
 * DefaultBeanDefinitionDocumentReader
 **/

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate){
 // 对beans的处理
    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)) {
                    // 对默认的Bean标签解析
     parseDefaultElement(ele, delegate);
    }
    else {
                    // 对自定义的Bean标签解析
     delegate.parseCustomElement(ele);
    }
   }
  }
 }
 else {
  delegate.parseCustomElement(root);
 }
}

知识点:

Spring中XML有两大类Bean的声明标签

默认声明标签:

<bean id="userService" class="com.fly4j.service.impl.UserServiceImpl"/>

自定义声明标签: ·

<tx: annotation-driven />

怎么区分是默认命名空间还是自定义命名空间?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjwff.html