上面方法中主要调用了核心流程 #doFindMatchingFileSystemResources(...) , 代码如下:
/** * 通过ant通配符的subPattern与已经获取的根目录rootDir来组合获取所有在文件系统中的资源 * 如:我们本来的 url: 'classpath*:/test/aa/app-*.xml' * 那么这里rootDir:classpath*:/test/aa/ subPattern :app-*.xml * Find all resources in the file system that match the given location pattern * via the Ant-style PathMatcher. * @param rootDir the root directory in the file system * @param subPattern the sub pattern to match (below the root directory) * @return a mutable Set of matching Resource instances * @throws IOException in case of I/O errors * @see #retrieveMatchingFiles * @see org.springframework.util.PathMatcher */ protected Set<Resource> doFindMatchingFileSystemResources(File rootDir, String subPattern) throws IOException { if (logger.isTraceEnabled()) { logger.trace("Looking for matching resources in directory tree [" + rootDir.getPath() + "]"); } //调用真实处理方法,获取set集合的File Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern); Set<Resource> result = new LinkedHashSet<>(matchingFiles.size()); //将获取的File转换为 FileSystemResource 同时添加到result结果集中 for (File file : matchingFiles) { result.add(new FileSystemResource(file)); } return result; }上面方法主要是将获取的 Set<File> 的结果进行转换,将资源类型转换为 FileSystemResource , 上面方法的核心方法是 #retrieveMatchingFiles(...)
#retrieveMatchingFiles(...) 代码如下:
/** * * Retrieve files that match the given path pattern, * checking the given directory and its subdirectories. * @param rootDir the directory to start from * @param pattern the pattern to match against, * relative to the root directory * @return a mutable Set of matching Resource instances * @throws IOException if directory contents could not be retrieved */ protected Set<File> retrieveMatchingFiles(File rootDir, String pattern) throws IOException { //1.不存在直接返回空集合 if (!rootDir.exists()) { // Silently skip non-existing directories. if (logger.isDebugEnabled()) { logger.debug("Skipping [" + rootDir.getAbsolutePath() + "] because it does not exist"); } return Collections.emptySet(); } //2.不是目录直接返回空 if (!rootDir.isDirectory()) { // Complain louder if it exists but is no directory. if (logger.isInfoEnabled()) { logger.info("Skipping [" + rootDir.getAbsolutePath() + "] because it does not denote a directory"); } return Collections.emptySet(); } //3/判断是否可读 if (!rootDir.canRead()) { if (logger.isInfoEnabled()) { logger.info("Skipping search for matching files underneath directory [" + rootDir.getAbsolutePath() + "] because the application is not allowed to read the directory"); } return Collections.emptySet(); } //4.将所有的系统分割器转换为 / String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, "http://www.likecs.com/"); //5.若子路径开头没有 / 则父路径要最后添加 / if (!pattern.startsWith("http://www.likecs.com/")) { fullPattern += "http://www.likecs.com/"; } fullPattern = fullPattern + StringUtils.replace(pattern, File.separator, "http://www.likecs.com/"); Set<File> result = new LinkedHashSet<>(8); //真真处理的方法 doRetrieveMatchingFiles(fullPattern, rootDir, result); return result; }我们可以看到方法中主要是做了一些校验和转换,真真的处理是调用了 #doRetrieveMatchingFiles(...) 方法,
#doRetrieveMatchingFiles(...) 方法定义:
/** * 递归遍历 dir 目录 结合fullpattern 进行路径匹配,将符合的资源全部放入result中 * Recursively retrieve files that match the given pattern, * adding them to the given result list. * @param fullPattern the pattern to match against, * with prepended root directory path * @param dir the current directory * @param result the Set of matching File instances to add to * @throws IOException if directory contents could not be retrieved */ protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set<File> result) throws IOException { if (logger.isTraceEnabled()) { logger.trace("Searching directory [" + dir.getAbsolutePath() + "] for files matching pattern [" + fullPattern + "]"); } //遍历目录 for (File content : listDirectory(dir)) { //获取当前文件/目录的路径同时分隔符全部替换为 / String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "http://www.likecs.com/"); //如果是目录 同时和 fullPattern匹配 则进递归 if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "http://www.likecs.com/")) { if (!content.canRead()) { if (logger.isDebugEnabled()) { logger.debug("Skipping subdirectory [" + dir.getAbsolutePath() + "] because the application is not allowed to read the directory"); } } else { doRetrieveMatchingFiles(fullPattern, content, result); } } //如果是文件则进行匹配 if (getPathMatcher().match(fullPattern, currPath)) { result.add(content); } } } 3.5.5 findAllClassPathResources上面分析了当有通配符时的方法调用过程,那么这里我们来分析当没有通配符时的方法调用