上两节对XmlBeanFactory和XmlBeanDefinitionReader对象reader进行了一些介绍,下面我们继续回到XmlBeanFactory中解析源码!
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
在(2)中我们解析到这一步!
继续Debug…
进入XmlBeanDefinitionReader
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
- new EncodedResource(resource)创建EncodedResource对象,封装resource
/**
* 构造函数
* 创建EncodedResource对象
* Create a new {@code EncodedResource} for the given {@code Resource},
* not specifying an explicit encoding or {@code Charset}.
* @param resource the {@code Resource} to hold (never {@code null})
*/
public EncodedResource(Resource resource) {
this(resource, null, null);
}
//初始化属性resource private final Resource resource;
private EncodedResource(Resource resource, String encoding, Charset charset) {
super();
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.encoding = encoding;
this.charset = charset;
}
/**
* Load bean definitions from the specified XML file.
* @param encodedResource the resource descriptor for the XML file,
* allowing to specify an encoding to use for parsing the file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
*/
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());
}
//ThreadLocal对象,具体作用未知。。。???
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);//创建集合
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
//保存添加Resource
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//通过封装resource的EncodedResource对象获取xml文档输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
//封装输入流
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {//是null
inputSource.setEncoding(encodedResource.getEncoding());
}
//加载bean
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();
}
}
}
获取输入流:
还记得当初创建的new ClassPathResource(“bean_test.xml”)对象吗?
对象类中的getInputStream()方法,通过类加载器来获取输入流。。。
/**
* 获取xml文件的输入流
* This implementation opens an InputStream for the given class path resource.
* @see java.lang.ClassLoader#getResourceAsStream(String)
* @see java.lang.Class#getResourceAsStream(String)
*/
@Override
public InputStream getInputStream() throws IOException {
InputStream is;
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else if (this.classLoader != null) {
//通过类加载器获取输入流,并返回
is = this.classLoader.getResourceAsStream(this.path);
}
else {
is = ClassLoader.getSystemResourceAsStream(this.path);
}
if (is == null) {
throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
}
return is;
}
那么,随后InputSource是如何封装输入流的呢?
看看InputSource类吧!
public class InputSource 很简单的一个类
private InputStream byteStream;
public InputSource (InputStream byteStream)
{
setByteStream(byteStream);
}
public void setByteStream (InputStream byteStream)
{
this.byteStream = byteStream;
}
封装了输入流
继续往下解析源码:
//加载bean
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
/**
* Actually load bean definitions from the specified XML file.
* @param inputSource the SAX InputSource to read from
* @param resource the resource descriptor for the XML file
* @return the number of bean definitions found
* @throws BeanDefinitionStoreException in case of loading or parsing errors
* @see #doLoadDocument
* @see #registerBeanDefinitions
*/
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//获取Document对象用于解析xml文档,包含xml文档的一些相关信息
Document doc = doLoadDocument(inputSource, resource);
//注册bean,创建是当获取的时候创建getBean("...");
return registerBeanDefinitions(doc, resource);
}
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(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}