类继承层次图:
类名 | 作用 |
---|---|
BeanDefinitionReader | 定义资源文件读取并转换为BeanDefinition的功能 |
EnvironmentCapable | 定义了获取Environment的方法 |
AbstractBeanDefinitionReader | 对上面2个接口做了实现 |
XmlBeanDefinitionReader读取配置文件的大致流程
- 通过继承自 AbstractBeanDefinitionReader 的方法,使用ResourceLoader将资源文件路径转换为Resource
- 使用DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件
- 使用BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
持有registry(其实就是beanfactory),reader解析配置文件之后,把bean注册到beanfactory中。
核心方法loadBeanDefinitions:
- 把编码源添加到currentResources 中
- 把inputStream转换为inputSource
- 使用DefaultDocumentLoader把 inputStream转换为Doucument
- 使用DefaultBeanDefinitionDocumentReader解析document,把bean注册到factory
Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
loadCount = this.loadBeanDefinitions(resources);
if(actualResources != null) {
Resource[] var6 = resources;
int var7 = resources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource resource = var6[var8];
actualResources.add(resource);
}
}
return loadCount;
一连串的调用之后,会走到这里,resource其实就是spring的xml配置文件。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if(currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if(!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} else {
int var5;
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if(encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
} catch (IOException var15) {
throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
} finally {
((Set)currentResources).remove(encodedResource);//目的是防止重复加载同一个配置文件
if(((Set)currentResources).isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
return var5;
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
Document doc = this.doLoadDocument(inputSource, resource);
return this.registerBeanDefinitions(doc, resource);
}
//这里的EntityResolver一般是ResourceEntityResolver(二般情况是DelegatingEntityResolver)
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, this.getValidationModeForResource(resource), this.isNamespaceAware());
}
//DefaultBeanDefinitionDocumentReader解析doc,DefaultBeanDefinitionDocumentReader在第十一篇
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
int countBefore = this.getRegistry().getBeanDefinitionCount();
// Map<String, BeanDefinition> beanDefinitionMap的size大小,所以解析后的bean都放在这里
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
具体的解析过程转接到DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法中。
关于EncodedResource,提供了reader对象,没有设置字符集和编码时,将使用默认的字符集解码。
public Reader getReader() throws IOException {
return this.charset != null?new InputStreamReader(this.resource.getInputStream(), this.charset):(this.encoding != null?new InputStreamReader(this.resource.getInputStream(), this.encoding):new InputStreamReader(this.resource.getInputStream()));
}