深入Spring IOC源码之ResourceLoader(五)

2014-11-24 10:36:20 · 作者: · 浏览: 3
.

int prefixEnd = locationPattern.indexOf(":") + 1;

if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {

// a file pattern

return findPathMatchingResources(locationPattern);

}

else {

// a single resource with the given name

return new Resource[] {getResourceLoader().getResource(locationPattern)};

}

}

}

对classpath下的资源,相同名字的资源可能存在多个,如果使用”classpath*:”作为前缀,表明需要找到classpath下所有该名字资源,因而需要调用findClassPathResources方法查找classpath下所有该名称的Resource,对非classpath下的资源,对于不存在模式字符的location,一般认为一个location对应一个资源,因而直接调用ResourceLoader.getResource()方法即可(对classpath下没有以”classpath*:”开头的location也适用)。

findClassPathResources方法实现相对比较简单:

适用ClassLoader.getResources()方法,遍历结果URL集合,将每个结果适用UrlResource封装,最后组成一个Resource数组返回即可。

对包含模式匹配字符的location来说,需要调用findPathMatchingResources方法:

protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {

String rootDirPath = determineRootDir(locationPattern);

String subPattern = locationPattern.substring(rootDirPath.length());

Resource[] rootDirResources = getResources(rootDirPath);

Set result = new LinkedHashSet(16);

for (int i = 0; i < rootDirResources.length; i++) {

Resource rootDirResource = resolveRootDirResource(rootDirResources[i]);

if (isJarResource(rootDirResource)) {

result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));

}

else {

result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));

}

}

if (logger.isDebugEnabled()) {

logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);

}

return (Resource[]) result.toArray(new Resource[result.size()]);

}

1. determinRootDir()方法返回locationPattern中最长的没有出现模式匹配字符的路径

2. subPattern则表示rootDirPath之后的包含模式匹配字符的路径信pattern

3. 使用getResources()获取rootDirPath下的所有资源数组。

4. 遍历这个数组。

a) 对jar中的资源,使用doFindPathMatchingJarResources()方法来查找和匹配。

b) 对非jar中资源,使用doFindPathMatchingFileResources()方法来查找和匹配。

doFindPathMatchingJarResources()实现:

1. 计算当前Resource在Jar文件中的根路径rootEntryPath。

2. 遍历Jar文件中所有entry,如果当前entry名以rootEntryPath开头,并且之后的路径信息和之前从patternLocation中截取出的subPattern使用PathMatcher匹配,若匹配成功,则调用rootDirResource.createRelative方法创建一个Resource,将新创建的Resource添加入结果集中。

doFindPathMatchingFileResources()实现:

1. 获取要查找资源的根路径(根路径全名)

2. 递归获得根路径下的所有资源,使用PathMatcher匹配,如果匹配成功,则创建FileSystemResource,并将其加入到结果集中。在递归进入一个目录前首先调用PathMatcher.matchStart()方法,以先简单的判断是否需要递归进去,以提升性能。

protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set result) throws IOException {

if (logger.isDebugEnabled()) {

logger.debug("Searching directory [" + dir.getAbsolutePath() +

"] for files matching pattern [" + fullPattern + "]");

}

File[] dirContents = dir.listFiles();

if (dirContents == null) {

throw new IOException("Could not retrieve contents of directory [" + dir.getAbsolutePath() + "]");

}

for (int i = 0; i < dirContents.length; i++) {

File content = dirContents[i];

String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/"