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

 

 

 

posted @ 2021-02-13 20:21  _kerry  阅读(201)  评论(0编辑  收藏  举报