Spring加载classpath与classpath*的过程

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包中的资源