XmlBeanFactory
源码解读
XmlBeanFactory
是Spring专门用于读取xml
源的BeanFactory
。是DefaultListableBeanFactory
的拓展类。这个类目前已经被标记为过期,然而对于学习Spring而言,恰到好处。
整个XmlBeanFactory
只有两个构造函数,我们的话主要关注于XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
。
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
// 将加载BeanDefinition的工作交给reader去执行
// 这里的Reader对应的是XmlBeanDefinitionReader类
// XmlBeanDefinitionReader实现了BeanDefinitionReader接口
this.reader.loadBeanDefinitions(resource);
}
跟进XmlBeanDefinitionReader
的loadBeanDefinitions
方法
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
可以发现,loadBeanDefinitions
调用了它的重载方法。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// 主要是用于判断传入的EncodedResource是否已经被加载了
// 如果被加载了,则抛出异常
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 真正加载bean的方法
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
得到输入源后,执行真正负责加载Bean的方法doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 解析xml文件,得到DOM document对象
// 这个方法是调用了javax.xml相关的解析方法
Document doc = doLoadDocument(inputSource, resource);
// 注册Bean定义,很关键的方法
// count返回的是注册了多少个bean
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
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(),