XmlBeanDefinitionReader类用来加载一个DOM 文档,并应用BeanDefinitionDocumentReader读取dom文档中配置的bean,然后将这些bean注册到给定的beanFactory中。
XmlBeanDefinitionReader读取文档时会验证文档,文档的验证方式有四种:VALIDATION_NONE,VALIDATION_AUTO,VALIDATION_DTD,VALIDATION_XSD,这四种验证方式定义在XmlValidationModeDetector验证器中。
XmlBeanDefinitionReader使用Constants工具类缓存自己的属性,和类名。该处理的一个作用就是通过属性名称获取属性的值。
下面重点说说XmlBeanDefinitionReader对配置资源的载入,该类中有一个loadBeanDefinitions方法有一个EncodedResource的参数,该参数是通过Resource转化。
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
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());}SetcurrentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
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.remove();
}
}
}
在该方法中获取ThreadLocal中的set集合,并将当前线程加载过的资源缓存到该set集合中,改操作是为了防止当前线程重复循环加载同一个Resource资源文件。加载完成之后,将资源传递给doLoadBeanDefinitions(inputSource, encodedResource.getResource())方法处理,并在finally中释放资源。
再来看看doLoadBeanDefinitions()方法中做了那些处理,首先,在该方法中调用doLoadDocument()加载当前资源文件并创建一个Document实例。那么doLoadDocument()是怎样创建Document实例的呢?在这个方法中调用了DocumentLoader接口的loadDocument方法,该方法换回一个Document对象而具体的是现在该接口的实现类DefaultDocumentLoader中,这里不再细说。