Spring IoC实现
Spring对资源文件和资源的加载都做了统一的抽象,以下是资源文件的继承体系:
其中,顶层接口InputStreamSource
只包含一个getInputStream()
方法用于返回指定资源的InputStream
;而Resource
是对资源的一个抽象,里面提供了判断资源是否存在、资源是否可读、资源大小等常见接口,并且大部分接口由抽象子类AbstractResource
提供了默认实现,而一些方法则由具体的子类如FileSystemResource
、ClassPathResource
等覆写,以满足特定的场景需求。
接下来看看Spring对资源加载的统一抽象,同样从它的继承体系说起:
与AbstractResource
相似,DefaultResourceLoader
是ResourceLoader
的默认实现。其中getResource()
方法是其核心(两个子类都没覆盖该方法),它根据方法参数location
的内容来决定到底是返回ClassPathResource
还是FileSystemResource
还是Resource
其它的一些子类。由于在默认的实现策略中,凡是以/
开头的都会返回ClassPathContextResource
类型的资源,但对于/user/hecenjie/test.xml
这样的路径我们更加希望是FileSystemResource
类型的资源,因此在子类FileSystemResourceLoader
中覆写了相关方法,使之可以从文件系统中获取资源;而另一个子类ClassRelativeResourceLoader
则扩展了功能,可以根据给定的Class所在包或者所在包的子包下加载资源。
ResourceLoader
的另一个重要实现是ResourcePatternResolver
,与上面的ResourceLoader
实现类不同的是,它支持根据指定的资源路径匹配模式每次返回多个Resource
实例(也就是Resource
数组),并且它也新增了一种新的协议前缀classpath*:
,该前缀表示可以加载多个jar包中相同的资源文件,而classpath:
只能加载找到的第一个文件。
PathMatchingResourcePatternResolver
除了支持ResourceLoader
和ResourcePatternResolver
新增的classpath*:
前缀外,还支持Ant风格的路径匹配模式(类似于**/*.xml
)。
Simple IoC实现
目前自己实现的IoC容器中,只实现了文件系统的资源与加载抽象,以下为它们各自的类图:
快速使用
我们可以尝试写一些简单的单元测试从文件系统中加载指定的资源,并对该资源做一些基本操作。首先,准备一个test.xml
文件,然后编写以下测试方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void testFileSystemResource() throws IOException {
Resource resource = new FileSystemResource("C:\\Users\\canjie\\Desktop\\test.xml");
assertTrue(resource.exists());
assertEquals(resource.contentLength(), 992);
}
public void testFileSystemResourceLoader() throws IOException {
ResourceLoader resourceLoader = new FileSystemResourceLoader();
Resource resource = resourceLoader.getResource("C:\\Users\\canjie\\Desktop\\test.xml");
assertTrue(resource.exists());
assertEquals(resource.contentLength(), 992);
}