# 2.7应用程序上下文和资源路径

本节介绍如何使用资源创建应用程序上下文，包括使用XML的快捷方式、如何使用通配符以及其他详细信息。

## 2.7.1 构造Application Contexts

application context constructor（特定context类型）通常使用string或者string数组作为resources路径的地址，比如定义context 的XML地址。

如果该地址没有前缀，那么该定义bean定义的Resource将会依赖于和他最相近的application context.比如下面的例子会使用ClassPathXmlApplicationContext：

```
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
```

这个bean定义将会从classpath加载，因为ClassPathResource被使用。但是下面的例子将会创建FileSystemXmlApplicationContext：

```
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("conf/appContext.xml");
```

现在bean定义从文件系统加载。

如果加上前缀，那么将会覆盖默认的Resource类型。如下：

```
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
```

这里虽然使用了FileSystemXmlApplicationContext，但是还是会从classpath中加载。但是如果在后面的代码中，还有需要使用到ResourceLoader的， 那么没有前缀的paths仍然会被认为是filesystem路径。

**构造ClassPathXmlApplicationContext-快捷方式**

ClassPathXmlApplicationContext公开了许多构造函数，以方便实例化。基本思想是，你只需提供一个字符串数组，该数组只包含XML文件本身的文件名（不包含前导路径信息），还提供一个类。然后，ClassPathXmlApplicationContext从提供的类中派生路径信息。

考虑下面的文件结构：

```
com/
  foo/
    services.xml
    daos.xml
    MessengerService.class
```

下面的示例演示如何实例化由名为services.xml和daos.xml（位于类路径上）文件中定义的bean组成的ClassPathXmlApplicationContext实例：

```
ApplicationContext ctx = new ClassPathXmlApplicationContext(
    new String[] {"services.xml", "daos.xml"}, MessengerService.class);
```

## 2.7.2 应用程序上下文构造函数资源路径中的通配符

应用程序上下文构造函数值中的资源路径可以是简单路径（如前所示），每个路径都有到目标资源的一对一映射，或者可以包含特殊的“classpath\*：”前缀或内部ant样式正则表达式（通过使用Spring的PathMatcher实用程序）。后者都是有效的通配符。

此机制的一个用途是在需要进行组件样式的应用程序组装时使用。所有组件都可以将上下文定义片段“发布”到一个众所周知的位置路径，并且，当使用前缀为classpath\*：的同一路径创建最终应用程序上下文时，所有组件片段都会自动拾取。

注意，这个通配符是特定于应用程序上下文构造函数中资源路径的使用（或者直接使用PathMatcher实用程序类层次结构时），并且在构造时解析。它与资源类型本身无关。不能使用classpath\*：前缀构造实际资源，因为资源一次只指向一个资源。

**Ant-style Patterns**

下面是 Ant-style patterns 的路径：

```
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
```

当路径位置包含一个Ant样式的模式时，解析器将遵循一个更复杂的过程来尝试解析通配符。它为最后一个非通配符段的路径生成一个资源，并从中获取一个URL。如果该URL不是jar:URL或容器特定的变量（例如，weblogic中的zip、websphere中的wsjar等），则从该URL获取java.io.File，并通过遍历文件系统来解析通配符。对于JAR URL，解析器要么从中获取java.net.JarURLConnection，要么手动解析JAR URL，然后遍历JAR文件的内容以解析通配符。

**对可移植性的影响**

如果指定的路径已经是一个文件URL（或者隐式地因为ResourceLoader是一个文件系统，或者显式地指定），则通配符是完全可移植的。

如果指定的路径是类路径位置，解析程序必须通过调用ClassLoader.getResource（）获取最后一个非通配符路径段URL。因为这只是路径的一个节点（而不是文件的末尾），所以实际上（在类加载器JavaDoc中）没有定义在这种情况下返回的具体URL类型。实际上，它始终是一个java.io.File，表示目录（类路径资源解析为文件系统位置）或某种类型的JAR URL（类路径资源解析为JAR位置）。尽管如此，这个操作还是存在可移植性问题。

如果为最后一个非通配符段获取JAR URL，解析程序必须能够从中获取java.net.JarURLConnection，或者手动解析JAR URL，以便能够遍历JAR的内容并解析通配符。这在大多数环境中都有效，但在其他环境中失败，我们强烈建议在依赖JAR之前，在特定环境中彻底测试来自JAR的资源的通配符解析。

**classpath\*:前缀**

构造基于XML的application context，路径地址可以使用classpath\*: 前缀，如下：

```
ApplicationContext ctx =
    new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
```

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

> 通配符类路径依赖于基础类加载器的getResources（）方法。由于现在大多数应用程序服务器都提供自己的类加载器实现，因此其行为可能会有所不同，尤其是在处理JAR文件时。检查ClassPath\*是否有效的一个简单测试是使用ClassLoader从类路径上的jar中加载文件：getClass().getClassLoader().getResources("")。尝试使用具有相同名称但位于两个不同位置的文件进行此测试。如果返回不适当的结果，请检查应用程序服务器文档中可能影响类加载器行为的设置。

你还可以在位置路径的其余部分（例如，classpath\_:META-INF/\_-beans.xml）中将classpath\*：前缀与PathMatcher模式组合。在这种情况下，解析策略相当简单：在最后一个非通配符路径段上使用ClassLoader.getResources()调用以获取类加载程序层次结构中的所有匹配资源，然后在每个资源上，使用前面描述的相同路径匹配器解析策略通配符子路径。

**通配符的其他关注点**

注意，当与Ant样式模式结合使用时，除非实际目标文件位于文件系统中，否则classpath\_: 在模式开始之前只能在至少有一个根目录的情况下可靠的执行。这意味着classpath\_:\*.xml等模式可能不会从jar文件的根目录中检索文件，而是只从扩展目录的根目录中检索文件。

Spring检索类路径条目的能力源自JDK的 ClassLoader.getResources()）方法，该方法只返回空字符串的文件系统位置（指示要搜索的潜在根）。Spring也评估了JAR文件中的URLClassLoader运行时配置和java.class.path清单，但这并不保证会导致可移植行为。

> 扫描classpath包需要在classpath中存在相应的目录。当你使用Ant构建JAR时，不要激活JAR任务的“仅文件”开关。此外，根据某些环境中的安全策略，类路径目录可能不会被公开-例如，JDK 1.7.0 U45及更高版本上的独立应用程序（需要在清单中设置“可信库”）。请参阅<https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources）。> 在JDK9的模块路径（Jigsaw）上，Spring的类路径扫描通常按预期工作。在这里，将资源放入一个专用的目录也是非常推荐的，这样可以避免前面提到的在搜索JAR文件根级别时的可移植性问题。

Ant-style 模式classpath: resources 并不一定能保证匹配的资源，如果要搜索的根package存在于多个类路径地址中。考虑下面的资源情况：

```
com/mycompany/package1/service-context.xml
```

下面是可能用到的Ant-style path 匹配：

```
classpath:com/mycompany/**/service-context.xml
```

这样的资源只能位于一个位置，但是当使用前面的示例这样的路径来尝试解析它时，解析程序将使用getResource（“com/mycompany”）；返回的（第一个）URL。如果此基本包节点存在于多个类加载器位置中，则实际的最终资源可能找不到。因此，在这种情况下，你应该更喜欢使用具有相同ant样式模式的classpath\*:来搜索包含根包的所有类路径位置。

## 2.7.3 FileSystemResource注意事项

未连接到FileSystemApplicationContext的FileSystemResource（即，当FileSystemApplicationContext不是实际的ResourceLoader时）会按预期处理绝对和相对路径。相对路径相对于当前工作目录，而绝对路径相对于文件系统的根目录。

但是，由于向后兼容性（历史）的原因，当FileSystemApplicationContext是ResourceLoader时，这一点会发生变化。FileSystemApplicationContext强制所有附加的FileSystemResource实例将所有位置路径视为相对路径，不管它们是否以前导斜杠开头。实际上，这意味着以下示例是等效的：

```
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("conf/context.xml");

ApplicationContext ctx =
    new FileSystemXmlApplicationContext("/conf/context.xml");
```

以下例子也是等效的（即使它们是不同的，因为一种情况是相对的，另一种是绝对的）：

```
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");


FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");
```

在实践中，如果需要真正的绝对文件系统路径，则应避免将绝对路径与FileSystemResource或FileSystemXmlApplicationContext一起使用，并通过使用file: URL 前缀强制使用UrlResource。以下示例说明了如何执行此操作：

```
// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");

// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
ApplicationContext ctx =
    new FileSystemXmlApplicationContext("file:///conf/context.xml");
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flydean.com/spring-framework-documentation5/core-technologies/2.resources/2.7application-contexts-and-resource-paths.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
