Spring的classpath前缀差异

159

4.7.2.2 The classpath*: prefix中记录了以下内容:

这个特殊的前缀指定了所有与给定名称匹配的类路径资源必须被获取(内部上,这基本上是通过ClassLoader.getResources(...)调用来实现的),然后合并以形成最终的应用程序上下文定义。

有人能解释一下吗?

使用classpath*:conf/appContext.xml和不带星号的classpath:conf/appContext.xml之间有什么区别?


未来的读者,也请查看这个带有“status=declined”的错误。 https://github.com/spring-projects/spring-framework/issues/16017 以防万一URL最终失败,该错误帖子的标题是“使用通配符类路径和通配符路径从JAR文件的根目录导入XML文件无法正常工作[SPR-11390]”。 - granadaCoder
4个回答

230

简单定义

classpath*:conf/appContext.xml 简单来说,就是在类路径下的所有jar包中位于 conf 文件夹下的所有 appContext.xml 文件都会被读取并整合成一个大的应用程序上下文。

相反,classpath:conf/appContext.xml 只会加载第一个被找到的文件...其余的将被忽略。


8
它们之间还有一个有趣的区别。请参见我的问题也:https://dev59.com/3nPYa4cB1Zd3GeqPeg4T - Eugene
37
非常重要的一点——如果您使用 *,但Spring找不到匹配项,它将不会抱怨。如果您不使用 * 并且没有匹配项,上下文将无法启动(!) - Roy Truelove

43

classpath*:... 语法主要用于从多个 bean 定义文件构建应用程序上下文,使用通配符语法。

例如,如果你使用 classpath*:appContext.xml 构建上下文,类路径将会扫描所有名为 appContext.xml 的资源,并将所有文件的 bean 定义合并到一个上下文中。

相比之下,classpath:conf/appContext.xml 只会在类路径中获取一个名为 appContext.xml 的文件。如果有多个文件,则其它文件将被忽略。


2
classpath* 会查找子目录吗?换句话说,如果我在 classpath 根目录下有 appContext.xml 文件,并且在 /dir/appContext.xml 目录下也有一个,那么当我使用 classpath*:appContext.xml 时,它会同时加载这两个文件吗? - AHungerArtist

24
classpath*: 它指的是一个资源列表,并且加载所有在类路径中存在的文件,列表可以为空,如果类路径中没有这样的文件,则应用程序不会抛出任何异常(只是忽略错误)。 classpath: 它指的是一个特定的资源,并且仅加载第一个在类路径中找到的文件,如果类路径中没有这样的文件,则它将抛出异常
java.io.FileNotFoundException: 
class path resource [conf/appContext.xml] cannot be opened because it does not exist

“官方文档”:“不可能使用classpath *:前缀构建实际的“资源”,因为资源一次只指向一个资源。”加上我刚刚遇到了这个奇怪的错误,这就是我来这里的原因。如果您要导入资源,那么使用通配符classpath前缀就没有意义了。” - GabrielOshiro

1

Spring的源代码:

public Resource[] getResources(String locationPattern) throws IOException {
   Assert.notNull(locationPattern, "Location pattern must not be null");
   //CLASSPATH_ALL_URL_PREFIX="classpath*:"
   if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
      // a class path resource (multiple resources for same name possible)
      if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
         // a class path resource pattern
         return findPathMatchingResources(locationPattern);
      }
      else {
         // all class path resources with the given name
         return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
      }
   }
   else {
      // Only look for a pattern after a prefix here
      // (to not get fooled by a pattern symbol in a strange prefix).
      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)};
      }
   }
}  

你能否请解释一下? - RtmY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接