BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
XmlBeanFactory的初始化时序图1)首先调用ClassPathResource的构造函数来构造Resource资源文件beanFactoryTest.xml的实例对象;
2)用Resource提供的服务对后续的资源进行处理;
3)利用XmlBeanFactory对Resource进行初始化。
一、配置文件(Resource)封装
Spring配置文件读取是通过ClassPathResource进行封装的。
Spring对其内部使用到的资源实现了自己的抽象结构:Resource接口来封装底层资源
public interface InputStreamSource {
InputStream getInputStream()throws IOException;
}
public interface Resourceextends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getUrl()throws IOException;
URI getURI()throws IOException;
File getFile()throws IOException;
long lastModified()throws IOException;
Resource createRelative(String relativePath)throws IOException;
String getFilename();
String getDescription();
}
1. InputStreamSource封装任何能返回InputStream的类,比如File、Classpath下的资源和Byte Array等。只有一个定义方法:getInputStream(),返回一个新的InputStream对象。
2. Resource接口抽象了所有Spring内部使用到的底层资源:File、URL、Classpath等
a)定义了3个判断当前资源状态的方法:存在性(exists)、可读性(isReadable)、是否处于打开状态(isOpen);
b)Resource接口提供了不同资源到URL、URI、File类型的转换,以及获取lastModified属性、文件名的方法;
c)Resource提供了基于当前资源创建相对资源的方法:createRelative();
d)Resource提供了getDescription()方法用于在错误处理中打印信息。
3. 对不同来源的资源文件都有相应的Resource实现:
文件(FileSystemResource)、Classpath资源(ClassPathResource)、URL资源(UrlResource)、IInputStream资源(InputStreamResource)、Byte Array(ByteArrayResource)等 。
资源文件的加载:
Resource resource = new ClassPathResource("beanFactoryTest.xml");
InputStream inputStream = resource.getInputStream();
得到inpurStream后,就可以按照以前的开发方式实现了。
Resource接口实现
Resource接口可以对所有资源文件进行统一处理,以getInputStream为例
1)ClassPathResource通过class或者classLoader提供的底层方法进行调用
if( this.clazz != null ){
is = this.clazz.getResourceAsSream(this.path);
} else{
is = this.classLoader.getResourceAsStream(this.path);
}
2)FileSystemResource直接用FileInputStream对文件进行实例化
public InputStream getInputStream() throws IOException{
return new FileInputStream(this.file);
}
二、加载Bean
XmlBeanFactory构造函数调用XmlBeanDefinitionReader类型的reader属性提供的方法this.reader.loadBeanDefinitions(resource),整个资源加载的切入点。
loadBeanDefinitions(resource)时序图1)封装资源文件。对参数resource使用EncodedResource类进行封装(处理资源文件的编码);
2)获取输入流。从Resource中获取对应的InputStream并构造InputSource;
3)通过构造的InputSource实例和Resource实例继续调用函数doLoadDefinitions。
loadBeanDefinitions函数的具体实现如下:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException{
return loadBeanDefinitions(new EncodedResource(resource));
}
doLoadDefinitions(InputSource inputSource,Resource resource){...} //有兴趣的自己查看源码
1)获取XML对象的验证模式;
2)加载XML文件,并得到对应的Document;
3)根据返回的Document注册Bean信息。
网友评论