曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的 (3)

这方面我懂得也不多,回头可以单独讲解。我们继续正文:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) { try { int validationMode = getValidationModeForResource(resource); // 反正org.w3c.dom.Document也是jdk的类,具体不管 Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); // 下边就开始正题了 return registerBeanDefinitions(doc, resource); } }

关于documentLoader.loadDocument,大家只要简单知道,是进行初步的解析就行了,主要是基于xsd、dtd等,进行语法检查等。

我这里的堆栈,大家看下:

曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的

这里,先不深究xml解析的东西(主要是我也不怎么会啊,哈哈哈)

接着走:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } BeanDefinitionDocumentReader

看得出来,XmlBeanDefinitionReader可能觉得工作繁重,于是将具体的工作,交给了BeanDefinitionDocumentReader。

public interface BeanDefinitionDocumentReader { void setEnvironment(Environment environment); void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) throws BeanDefinitionStoreException; }

核心方法肯定是

void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

两个参数,Document我们理解,就是代表xml文件;

XmlReaderContext

XmlReaderContext是啥,看样子是个上下文,上下文,一般来说,就是个大杂烩,把需要用到的都会放在里面。

我们看看放了些啥:

public class XmlReaderContext extends ReaderContext { // 之前的核心类,把自己传进来了 private final XmlBeanDefinitionReader reader; // org.springframework.beans.factory.xml.NamespaceHandlerResolver,这个也是核心类! private final NamespaceHandlerResolver namespaceHandlerResolver; } public class ReaderContext { //xml资源本身 private final Resource resource; //盲猜是中间处理报错后,报告问题 private final ProblemReporter problemReporter; // event/listener机制吧,方便扩展 private final ReaderEventListener eventListener;` // 跳过 private final SourceExtractor sourceExtractor; }

看完了这个上下文的定义,要知道,它是作为一个参数,传给:

org.springframework.beans.factory.xml.BeanDefinitionDocumentReader void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) throws BeanDefinitionStoreException;

那,这个参数怎么构造的呢?

那,我们还得切回前面的代码:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); // 这里,调用createReaderContext(resource)创建上下文 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } /** * Create the {@link XmlReaderContext} to pass over to the document reader. */ protected XmlReaderContext createReaderContext(Resource resource) { if (this.namespaceHandlerResolver == null) { // 创建一个namespacehandler this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.namespaceHandlerResolver); } namespaceHandlerResolver

这里太核心了,我们看看namespaceHandlerResolver是干嘛的:

public interface NamespaceHandlerResolver { /** * Resolve the namespace URI and return the located {@link NamespaceHandler} * implementation. * @param namespaceUri the relevant namespace URI * @return the located {@link NamespaceHandler} (may be {@code null}) */ // 比如解析xml时,我们可能有<bean>,这个是默认命名空间,其namespace就是<beans>;如果是<context:component-scan>,这里的namespace,就是context NamespaceHandler resolve(String namespaceUri); }

这个类的用途,就是根据传入的namespace,找到对应的handler。

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

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