目录
1、概述
2、初始化
3、解析Spring配置
XMLBeanDefinitionReader 是 XmlBeanFactory 中特殊的存在,利用 SAX 方式解析Spring配置XML文件为 Document 的辅助类。
package org.springframework.beans.factory.xml;
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
// 初始化
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
// AbstractBeanDefinitionReader 初始化 BeanDefinitionRegistry、ResourceLoader、Environment
super(registry);
// SAX解析异常类
this.errorHandler = new SimpleSaxErrorHandler(this.logger);
// 验证XML是DTD、XSD 的类
this.validationModeDetector = new XmlValidationModeDetector();
// 存放 Resource的 ThreadLocal
this.resourcesCurrentlyBeingLoaded = new NamedThreadLocal("XML bean definition resources currently being loaded");
}
}
package org.springframework.beans.factory.xml;
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public void setValidating(boolean validating) {
this.validationMode = validating ? 1 : 0;
this.namespaceAware = !validating;
}
public void setValidationModeName(String validationModeName) {
this.setValidationMode(constants.asNumber(validationModeName).intValue());
}
public void setValidationMode(int validationMode) {
this.validationMode = validationMode;
}
public int getValidationMode() {
return this.validationMode;
}
public void setNamespaceAware(boolean namespaceAware) {
this.namespaceAware = namespaceAware;
}
public boolean isNamespaceAware() {
return this.namespaceAware;
}
public void setProblemReporter(@Nullable ProblemReporter problemReporter) {
this.problemReporter = (ProblemReporter)(problemReporter != null ? problemReporter : new FailFastProblemReporter());
}
public void setEventListener(@Nullable ReaderEventListener eventListener) {
this.eventListener = (ReaderEventListener)(eventListener != null ? eventListener : new EmptyReaderEventListener());
}
public void setSourceExtractor(@Nullable SourceExtractor sourceExtractor) {
this.sourceExtractor = (SourceExtractor)(sourceExtractor != null ? sourceExtractor : new NullSourceExtractor());
}
public void setNamespaceHandlerResolver(@Nullable NamespaceHandlerResolver namespaceHandlerResolver) {
this.namespaceHandlerResolver = namespaceHandlerResolver;
}
public void setDocumentLoader(@Nullable DocumentLoader documentLoader) {
this.documentLoader = (DocumentLoader)(documentLoader != null ? documentLoader : new DefaultDocumentLoader());
}
public void setEntityResolver(@Nullable EntityResolver entityResolver) {
this.entityResolver = entityResolver;
}
protected EntityResolver getEntityResolver() {
if (this.entityResolver == null) {
ResourceLoader resourceLoader = this.getResourceLoader();
if (resourceLoader != null) {
this.entityResolver = new ResourceEntityResolver(resourceLoader);
} else {
this.entityResolver = new DelegatingEntityResolver(this.getBeanClassLoader());
}
}
return this.entityResolver;
}
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
public void setDocumentReaderClass(Class extends BeanDefinitionDocumentReader> documentReaderClass) {
this.documentReaderClass = documentReaderClass;
}
// 加载Resource
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 包装成 EncodedResource,可以根据配置的编码类型解析 Spring配置文件
return this.loadBeanDefinitions(new EncodedResource(resource));
}
// 加载Resource
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());
}
// 判断该线程内是否已经存在 Resource
Set 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 {
// SAX解析 start
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;
}
}
public int loadBeanDefinitions(InputSource inputSource) throws BeanDefinitionStoreException {
return this.loadBeanDefinitions(inputSource, "resource loaded through SAX InputSource");
}
public int loadBeanDefinitions(InputSource inputSource, @Nullable String resourceDescription) throws BeanDefinitionStoreException {
return this.doLoadBeanDefinitions(inputSource, new DescriptiveResource(resourceDescription));
}
// 正式解析
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
// 转换成 Document
Document doc = this.doLoadDocument(inputSource, resource);
//
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var4) {
throw var4;
} catch (SAXParseException var5) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);
} catch (SAXException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
} catch (ParserConfigurationException var7) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
} catch (IOException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
} catch (Throwable var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
}
}
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, this.getValidationModeForResource(resource), this.isNamespaceAware());
}
protected int getValidationModeForResource(Resource resource) {
int validationModeToUse = this.getValidationMode();
if (validationModeToUse != 1) {
return validationModeToUse;
} else {
int detectedMode = this.detectValidationMode(resource);
return detectedMode != 1 ? detectedMode : 3;
}
}
protected int detectValidationMode(Resource resource) {
if (resource.isOpen()) {
throw new BeanDefinitionStoreException("Passed-in Resource [" + resource + "] contains an open stream: cannot determine validation mode automatically. Either pass in a Resource that is able to create fresh streams, or explicitly specify the validationMode on your XmlBeanDefinitionReader instance.");
} else {
InputStream inputStream;
try {
inputStream = resource.getInputStream();
} catch (IOException var5) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: cannot open InputStream. Did you attempt to load directly from a SAX InputSource without specifying the validationMode on your XmlBeanDefinitionReader instance?", var5);
}
try {
return this.validationModeDetector.detectValidationMode(inputStream);
} catch (IOException var4) {
throw new BeanDefinitionStoreException("Unable to determine validation mode for [" + resource + "]: an error occurred whilst reading from the InputStream.", var4);
}
}
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
int countBefore = this.getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader)BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, this.getNamespaceHandlerResolver());
}
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = this.createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
ClassLoader cl = this.getResourceLoader() != null ? this.getResourceLoader().getClassLoader() : this.getBeanClassLoader();
return new DefaultNamespaceHandlerResolver(cl);
}
}