spring原始碼(三)--XmlBeanDefinitionReader
阿新 • • 發佈:2018-12-10
類繼承層次圖:
類名 | 作用 |
---|---|
BeanDefinitionReader | 定義資原始檔讀取並轉換為BeanDefinition的功能 |
EnvironmentCapable | 定義了獲取Environment的方法 |
AbstractBeanDefinitionReader | 對上面2個介面做了實現 |
XmlBeanDefinitionReader讀取配置檔案的大致流程
- 通過繼承自 AbstractBeanDefinitionReader 的方法,使用ResourceLoader將資原始檔路徑轉換為Resource
- 使用DocumentLoader對Resource檔案進行轉換,將Resource檔案轉換為Document檔案
- 使用BeanDefinitionDocumentReader的實現類DefaultBeanDefinitionDocumentReader對Document進行解析,並使用BeanDefinitionParserDelegate對Element進行解析
核心方法loadBeanDefinitions:
- 把編碼源新增到currentResources 中
- 把inputStream轉換為inputSource
- 使用DefaultDocumentLoader把 inputStream轉換為Doucument
- 解析document,把bean註冊到factory
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if(this.logger.isInfoEnabled()) { this.logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } 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()); }
對與xml檔案中的一個個元素節點,由下面的方法遍歷 方法在DefaultBeanDefinitionDocumentReader中
//root是dom節點的根節點,從根節點開始遍歷,對於不同名稱空間的元素使用不同的解析器解析,然後把符合條件的bean註冊到factory中。 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)) {//是預設名稱空間中的節點,由當前reader解析 this.parseDefaultElement(ele, delegate); } else {//否則由delegate解析,多種parser在第十篇中有描述 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
關於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()));
}