Spring加载Resource文件是通过ResourceLoader来进行的,先来看看ResourceLoader的继承体系。
本文重点分析左节点树资源解析器的源码。
1、ResourceLoader类,由下图可见,ResourceLoader接口只提供了classpath前缀的支持
2、接着看ResourceLoader子类ResourcePatternResolver,该类支持classpath*
通过2个接口的源码对比,我们发现ResourceLoader提供 classpath下单资源文件的载入,而ResourcePatternResolver提供了多资源文件的载入。
3、再接着看ResourcePatternResolver实现类PathMatchingResourcePatternResolver
分析getResources方法,发现有两个分支。
根据上图分析一下分支源码:
(1)、以classpath*开头,但路径不包含通配符的
主要看一下getResources(String name)这个方法
可以看出,如果存在父加载器,则向上迭代获取资源, 因此能加到jar包里面的资源文件。
(2)、不以classpath*开头,路径不包含通配符的
默认是DefaultResourceLoader(),分析代码可以看出,如果以classpath开头,则创建为一个ClassPathResource,否则则试图以URL的方式加载资源,创建一个UrlResource.
(3)、不以classpath*开头,路径包含通配符的
1.先获取目录,加载目录里面的所有资源,determineRootDir(String location)这个方法会确定根目录,不会包含通配符。
2.在所有资源里面进行查找匹配,找出我们需要的资源,方法前面已经分析过
总结:
1.无论是classpath还是classpath*都可以加载整个classpath下(包括jar包里面)的资源文件。
2.classpath只会返回第一个匹配的资源,查找路径是优先在项目中存在资源文件,再查找jar包。
3.文件名字包含通配符资源(如果spring-*.xml,spring*.xml), 如果根目录为"", classpath加载不到任何资源, 而classpath*则可以加载到classpath中可以匹配的目录中的资源,但是不能加载到jar包中的资源