Spring中的Resource,ResourceLoader,容器的关系
之前提到Spring会将配置文件或者配置类读取到内存转换成一个个的Resource实例。然后将Resource解析一个个的BeanDefinitioon.
Resource接口
public interface Resource extends InputStreamSource
- 1
Resource继承于InputStreamSource接口 ,InputStreamSource接口仅仅定义了一个方法,获取输入流。Resource定义了对资源的基本操作。判断资源是否存在,是否可读,是否打开 ==。
Resource接口体系
EncodedResource类
EncodedResource实现了了InputStreamSource接口,该类的主要作用是 对资源文件的编码处理。
AbstractResource
该抽象类实现了大量的对Resource方法的默认公共实现。如果要实现自己的Resource,应该继承该类,而不是实现顶层接口。
ClassPathResource类
提供根据类文件夹访相对路径问资源的能力。
FileSystemResource类
提供访问系统资源的能力,但是JDK自带的 File类相关,也不错。
此外,FileSystemResource实现了WritableResource接口,WritableResource接口定义了 对资源写的能力。那么回过头去看Resource接口,仅仅定义了读取资源的能力。
体验FileSystemResource
在 项目中创立一个文件。test.txt
然后利用Spring的FileSystemResource进行读写操作。
public class ResourceDemo {
public static void main(String[] args) throws IOException {
FileSystemResource fileSystemResource = new FileSystemResource(
"E:\\mooc\\熟悉Spring源码\\src\\main\\java\\com\\fuyouj\\demo\\resource\\test.txt");
File file = fileSystemResource.getFile();
System.out.println(file.length());
//获取输出流
OutputStream outputStream = fileSystemResource.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("你好");
bufferedWriter.flush();
outputStream.close();
bufferedWriter.close();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可以看到,为了访问不同的资源,要通过不同的Resource实现类,那么可以不显示使用实现类的情况下,就能够访问不同的资源。答案是肯定的,我们平时使用的时候就没有显示用这些实现类。
Spring不仅仅带classpath:,file前缀的资源,还能解析Ant风格的路径。
Ant风格我们也经常用到。
这种自动适配所有资源的能力是 ResourceLoader赋予的。
ResourceLoader
ResourceLoader实现不同的Resource加载策略,按需返回不同的类型的Resource.
DefaultResourceLoader
DefaultResourceLoader实现了ResourceLoader接口,其中的getResource
就是根据地址的不同 返回不同的Resource实例。
@Override
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
Resource resource = protocolResolver.resolve(location, this);
if (resource != null) {
return resource;
}
}
if (location.startsWith("/")) {
return getResourceByPath(location);
}
else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
}
else {
try {
// Try to parse the location as a URL...
URL url = new URL(location);
return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
}
catch (MalformedURLException ex) {
// No URL -> resolve as resource path.
return getResourceByPath(location);
}
}
}
ResourcePatternResolver
回到ResouceLoader接口,观察里面的
Resource getResource(String location);
- 1
方法发现仅仅支持路径地址的解析,而不能满足Ant风格,所以 ResourcePatternResolver正是提供了这样的能力。
继续观察类图,
可以看到熟悉的 Application容器接口,因此可以说,Spring中的容器具有解析任意资源的能力。
本文转自:https://blog.csdn.net/Fujie1997/article/details/106301940