spring 源码分析--IOC容器初始化五
上面完成了对资源的定位工作,接下去就是解析资源的内容了,接着第四节的第一个函数说,这一节主要完成将xml文件解析为DOM对象,函数的职责很单一。
1.2.2.1.1.3.1.1.3 loadBeanDefinitions(EncodedResource encodedResource): 方法定义在 XmlBeanDefinitionReader 类中,用以装载以 xml 格式定义的 bean 。
====================================================================
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull (encodedResource, "EncodedResource must not be null" );
if ( logger .isInfoEnabled()) {
logger .info( "Loading XML bean definitions from " + encodedResource.getResource());
}
// 使用 ThreadLocal 解决多线程问题。
Set currentResources = (Set ) this . resourcesCurrentlyBeingLoaded .get();
if (currentResources == null ) {
currentResources = new HashSet (4);
this . resourcesCurrentlyBeingLoaded .set(currentResources) ;
}
// 放置资源。
if (!currentResources.add(encodedResource) ) {
throw new BeanDefinitionStoreException(
"Detected recursive loading of " + encodedResource + " - check your import definitions!" );
}
try {
// 这里通过 Resource 得到 InputStream 的 IO 流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 从 InputStream 中得到 XML 的解析源
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null ) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 这里是具体的解析和注册过程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource()) ;
}
finally {
// 关闭从 Resource 中得到的 IO 流
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this . resourcesCurrentlyBeingLoaded .set( null ) ;
}
}
}
====================================================================
然后进入到具体的解析过程,实际真正从 xml 中装载 bean 的地方:即函数;
(从上面的过程可以知道,接下去的工作都会在下面的函数里完成,所以先做一个假设:2=1.2.2.1.1.3.1.1.3.1)
2. doLoadBeanDefinitions(inputSource, encodedResource.getResource())
该函数定义在 XmlBeanDefinitionReader ,
====================================================================
protected int doLoadBeanDefinitions (InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 通过解析得到 DOM ,然后完成 bean 在 IOC 容器中的注册
int validationMode = getValidationModeForResource(resource);
Document doc = this . documentLoader .loadDocument(
inputSource, getEntityResolver(), this . errorHandler , validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource) ;
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid" , ex);
} catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid" , ex);
} catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
} catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
====================================================================
2.1 registerBeanDefinitions(doc, resource) : 我们看到先把定义文件解析为 DOM 对象,然后进行具体的注册过程:
====================================================================
public int registerBeanDefinitions (Document doc, Resource resource) throws BeanDefinitionStoreException {
// Support old XmlBeanDefinitionParser SPI for backwards-compatibility.
// 这里定义解析器,使用 XmlBeanDefinitionParser 来解析 xml 方式的 bean 定义文件 –
// 现在的版本不用这个解析器了,使用的是 XmlBeanDefinitionReader
if ( this . parserClass != null ) {
XmlBeanDefinitionParser parser =
(XmlBeanDefinitionParser ) BeanUtils.instantiateClass ( this . parserClass );
return parser.registerBeanDefinitions( this , doc, resource) ;
}
// Read document based on new BeanDefinitionDocumentReader SPI.
// 具体的注册过程 , 首先得到 DefaultBeanDefinitionDocumentReader , 来处理 xml
// 的 bean 定义文件
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 得到当前容器中 bean 的数量,由 前面 可知,这里的 Registry 实际上是一个 // DefaultListableBeanFactory 这 里实际上是得到 DefaultListableBeanFactory // 类中字段 beanDefinitionMap 的大小。
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource)) ;
return getRegistry().getBeanDefinitionCount() - countBefore;
}
====================================================================
²2.1.1 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)): 在类
DefaultBeanDefinitionDocumentReader 中定义
====================================================================
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this . readerContext = readerContext;
logger .debug( "Loading bean definitions" );
Element root = doc.getDocumentElement();
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
// 允许子类继承预处理 xml ,默认实现为空。
preProcessXml(root);
parseBeanDefinitions(root, delegate);
// 允许子类继承进一步处理 xml ,默认实现为空。
postProcessXml(root);
}
====================================================================
本站支持 pay for your wishes
上一篇: 三摄加持 iPhone 11 Pro Max DxO评分即将公布
下一篇: 你是个值得信赖的好孩子
推荐阅读
-
SpringBoot 源码解析 (六)----- Spring Boot的核心能力 - 内置Servlet容器源码分析(Tomcat)
-
spring源码分析系列5:ApplicationContext的初始化与Bean生命周期
-
spring源码分析6: ApplicationContext的初始化与BeanDefinition的搜集入库
-
Spring源码剖析2:Spring IOC容器的加载过程
-
Spring源码分析之IoC容器初始化
-
详解Spring IOC 容器启动流程分析
-
Spring源码学习(一):Spring容器创建和初始化工作准备
-
Spring源码分析-IOC容器BeanFactory的应用场景
-
Guzz源码分析(一) guzz容器初始化过程
-
Spring IOC 容器源码分析