2. Resources

2. Resources

This chapter covers how Spring handles resources and how you can work with resources in Spring. It includes the following topics:

  • Introduction
  • The Resource Interface
  • Built-in Resource Implementations
  • The ResourceLoader
  • The ResourceLoaderAware interface
  • Resources as DependenciesApplication Contexts and Resource Paths
本章介绍了Spring如何处理资源,以及如何在Spring中使用资源。
它包括以下主题:
* 介绍
* 资源接口
* 内置资源实现
* ResourceLoader
* ResourceLoaderAware接口
* 依赖于应用程序上下文和资源路径的资源

2.1. Introduction

Java’s standard java.net.URL class and standard handlers for various URL prefixes, unfortunately, are not quite adequate enough for all access to low-level resources. For example, there is no standardized URL implementation that may be used to access a resource that needs to be obtained from the classpath or relative to a ServletContext. While it is possible to register new handlers for specialized URL prefixes (similar to existing handlers for prefixes such as http:), this is generally quite complicated, and the URL interface still lacks some desirable functionality, such as a method to check for the existence of the resource being pointed to.

不幸的是,Java的标准Java.net.URL类和各种URL前缀的标准处理程序
并不足以访问所有低级资源。
例如,没有一个标准化的URL实现可以用来访问需要从类路径或相对于
ServletContext获得的资源。
虽然可以为专业注册新处理程序URL前缀(类似于现有的前缀,如http处理程序:),
这通常是非常复杂的,并且URL接口仍然缺乏一些可取的功能,
比如一个方法来检查被引用的资源是否存在。

2.2. The Resource Interface

Spring’s Resource interface is meant to be a more capable interface for abstracting access to low-level resources. The following listing shows the Resource interface definition:

Spring的Resource接口是一个更强大的接口,用于抽象对低级资源的访问。
下面的清单显示了资源接口定义:

public interface Resource extends InputStreamSource {
    boolean exists();
    boolean isOpen();
    URL getURL() throws IOException;
    File getFile() throws IOException;
    Resource createRelative(String relativePath) throws IOException;
    String getFilename();
    String getDescription();
}

As the definition of the Resource interface shows, it extends the InputStreamSource interface. The following listing shows the definition of the InputStreamSource interface:

正如资源接口的定义所示,它扩展了InputStreamSource接口。
下面的清单显示了InputStreamSource接口的定义:

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

Some of the most important methods from the Resource interface are:

资源接口的一些最重要的方法是:

  • getInputStream(): Locates and opens the resource, returning an InputStream for reading from the resource. It is expected that each invocation returns a fresh InputStream. It is the responsibility of the caller to close the stream.
getInputStream():定位并打开资源,返回从资源读取的InputStream。
预期每次调用都会返回一个新的InputStream。调用者负责关闭流。

  • exists(): Returns a boolean indicating whether this resource actually exists in physical form.
exists():返回一个布尔值,指示该资源是否以物理形式实际存在。

  • isOpen(): Returns a boolean indicating whether this resource represents a handle with an open stream. If true, the InputStream cannot be read multiple times and must be read once only and then closed to avoid resource leaks. Returns false for all usual resource implementations, with the exception of InputStreamResource.
isOpen():返回一个布尔值,指示该资源是否表示一个打开流的句柄。
如果为真,则不能多次读取InputStream,必须只读取一次,
然后关闭以避免资源泄漏。
除InputStreamResource外,对所有通常的资源实现返回false。

  • getDescription(): Returns a description for this resource, to be used for error output when working with the resource. This is often the fully qualified file name or the actual URL of the resource.
getDescription():返回该资源的描述,用于处理该资源时的错误输出。
这通常是资源的完全限定文件名或实际URL。

Other methods let you obtain an actual URL or File object representing the resource (if the underlying implementation is compatible and supports that functionality).

其他方法让您获得表示资源的实际URL或File对象
(如果底层实现兼容并支持该功能)。

Spring itself uses the Resource abstraction extensively, as an argument type in many method signatures when a resource is needed. Other methods in some Spring APIs (such as the constructors to various ApplicationContext implementations) take a String which in unadorned or simple form is used to create a Resource appropriate to that context implementation or, via special prefixes on the String path, let the caller specify that a specific Resource implementation must be created and used.

Spring本身广泛地使用资源抽象,当需要资源时,它作为许多方法签名
中的参数类型。
其他方法在某些Spring api(如各种ApplicationContext实现构造函数)
在未装饰或简单的形式被用来创建一个资源适合上下文实现或通过特殊
前缀的String路径,让调用者指定一个特定的资源实现必须创建和使用。


unadorned 
英 /ˌʌnəˈdɔːnd/  美 /ˌʌnəˈdɔːrnd/  全球(美国)  
adj. 朴素的;未装饰的


While the Resource interface is used a lot with Spring and by Spring, it is actually very useful to use as a general utility class by itself in your own code, for access to resources, even when your code does not know or care about any other parts of Spring. While this couples your code to Spring, it really only couples it to this small set of utility classes, which serve as a more capable replacement for URL and can be considered equivalent to any other library you would use for this purpose.

虽然在Spring和Spring中经常使用资源接口,但是在您自己的代码中
作为一个通用实用程序类来使用它来访问资源实际上是非常有用的,
即使您的代码不知道或不关心Spring的任何其他部分。
虽然这将您的代码与Spring结合在一起,但实际上它只将它与这一小
组实用程序类结合在一起,这些实用程序类可以更有效地替代URL,
并且可以认为与为此目的使用的任何其他库是等效的。

The Resource abstraction does not replace functionality. It wraps it where possible. For example, a UrlResource wraps a URL and uses the wrapped URL to do its work.

资源抽象不会取代功能。它在可能的地方把它包装起来。
例如,UrlResource包装了一个URL并使用包装后的URL来完成其工作。

2.3. Built-in Resource Implementations

Spring includes the following Resource implementations:

2.3. 内置的资源实现
Spring包括以下资源实现:

  • UrlResource
  • ClassPathResource
  • FileSystemResource
  • ServletContextResource
  • InputStreamResource
  • ByteArrayResource
2.3.1. UrlResource

UrlResource wraps a java.net.URL and can be used to access any object that is normally accessible with a URL, such as files, an HTTP target, an FTP target, and others. All URLs have a standardized String representation, such that appropriate standardized prefixes are used to indicate one URL type from another. This includes file: for accessing filesystem paths, http: for accessing resources through the HTTP protocol, ftp: for accessing resources through FTP, and others.

UrlResource包装了java.net.URL,通常可以用来访问可以通过URL访问的
任何对象,比如文件、HTTP目标、FTP目标和其他。
所有URL都有标准化的字符串表示,这样就可以使用适当的标准化前缀来
表示不同类型的URL。
这包括file:用于访问文件系统路径,http:用于通过http协议访问资源,
ftp:用于通过ftp访问资源,等等。

A UrlResource is created by Java code by explicitly using the UrlResource constructor but is often created implicitly when you call an API method that takes a String argument meant to represent a path. For the latter case, a JavaBeans PropertyEditor ultimately decides which type of Resource to create. If the path string contains well-known (to it, that is) prefix (such as classpath:), it creates an appropriate specialized Resource for that prefix. However, if it does not recognize the prefix, it assume the string is a standard URL string and creates a UrlResource.

UrlResource是由Java代码显式使用UrlResource构造函数创建的,
但通常是在调用API方法时隐式创建的,该API方法接受表示路径的
字符串参数。
对于后一种情况,JavaBeans PropertyEditor最终决定创建哪种
类型的资源。
如果路径字符串包含众所周知的前缀(例如classpath:),它将为
该前缀创建一个适当的专用资源。
但是,如果不能识别前缀,则假定字符串是标准的URL字符串,
并创建UrlResource。

2.3.2. ClassPathResource

This class represents a resource that should be obtained from the classpath. It uses either the thread context class loader, a given class loader, or a given class for loading resources.

2.3.2. ClassPathResource
该类表示应从类路径获取的资源。
它使用线程上下文类装入器、给定的类装入器或给定的类装入资源。

This Resource implementation supports resolution as java.io.File if the class path resource resides in the file system but not for classpath resources that reside in a jar and have not been expanded (by the servlet engine or whatever the environment is) to the filesystem. To address this, the various Resource implementations always support resolution as a java.net.URL.

这个资源实现支持在文件系统中java.io.File的解析,但不适用于驻留
在jar中的类路径资源,并且没有(由servlet引擎或任何环境)扩展到文件系统。
为了解决这个问题,各种资源实现总是支持作为java.net.URL的解析。

A ClassPathResource is created by Java code by explicitly using the ClassPathResource constructor but is often created implicitly when you call an API method that takes a String argument meant to represent a path. For the latter case, a JavaBeans PropertyEditor recognizes the special prefix, classpath:, on the string path and creates a ClassPathResource in that case.

ClassPathResource是由Java代码显式使用ClassPathResource构造函数创建的,
但通常是在调用API方法时隐式创建的,该API方法接受表示路径的字符串参数。
对于后一种情况,JavaBeans PropertyEditor识别字符串路径上的特殊前缀
classpath:,并在这种情况下创建ClassPathResource。

2.3.3. FileSystemResource

This is a Resource implementation for java.io.File and java.nio.file.Path handles. It supports resolution as a File and as a URL.

2.3.3. FileSystemResource
这是java.io.File的资源实现 并且 由java.nio.file.Path处理。
它支持File和URL格式的解析。

2.3.4. ServletContextResource

This is a Resource implementation for ServletContext resources that interprets relative paths within the relevant web application’s root directory.

2.3.4. ServletContextResource
这是ServletContext资源的一个资源实现,它解释相关web应用程序根目录中的相对路径。

It always supports stream access and URL access but allows java.io.File access only when the web application archive is expanded and the resource is physically on the filesystem. Whether or not it is expanded and on the filesystem or accessed directly from the JAR or somewhere else like a database (which is conceivable) is actually dependent on the Servlet container.

它始终支持流访问和URL访问,但仅当扩展web应用程序归档并且资源
在文件系统上物理时才允许java.io.File访问。
不管它是在文件系统上进行扩展,还是直接从JAR或其他地方(如数据库)
访问它,实际上都取决于Servlet容器。

2.3.5. InputStreamResource

An InputStreamResource is a Resource implementation for a given InputStream. It should be used only if no specific Resource implementation is applicable. In particular, prefer ByteArrayResource or any of the file-based Resource implementations where possible.

2.3.5. InputStreamResource
InputStreamResource是给定InputStream的资源实现。
只有在没有适用的特定资源实现时才应该使用它。
特别是,尽可能使用ByteArrayResource或任何基于文件的资源实现。

In contrast to other Resource implementations, this is a descriptor for an already-opened resource. Therefore, it returns true from isOpen(). Do not use it if you need to keep the resource descriptor somewhere or if you need to read a stream multiple times.

与其他资源实现相比,这是一个针对已打开资源的描述符。
因此,它从isOpen()返回true。如果需要在某个地方保存
资源描述符,或者需要多次读取流,请不要使用它。

2.3.6. ByteArrayResource

This is a Resource implementation for a given byte array. It creates a ByteArrayInputStream for the given byte array.
It is useful for loading content from any given byte array without having to resort to a single-use InputStreamResource.

2.3.6. ByteArrayResource
这是给定字节数组的资源实现。
它为给定的字节数组创建ByteArrayInputStream。
它用于从任何给定的字节数组加载内容,而不必求助于
一次性使用的InputStreamResource。

2.4. The ResourceLoader

The ResourceLoader interface is meant to be implemented by objects that can return (that is, load) Resource instances. The following listing shows the ResourceLoader interface definition:

2.4. ResourceLoader
ResourceLoader接口是由可以返回(即加载)资源实例的对象实现的。
下面的清单显示了ResourceLoader接口定义:

public interface ResourceLoader {

    Resource getResource(String location);
}

All application contexts implement the ResourceLoader interface. Therefore, all application contexts may be used to obtain Resource instances.

所有应用程序上下文都实现ResourceLoader接口。
因此,可以使用所有应用程序上下文来获取资源实例。

When you call getResource() on a specific application context, and the location path specified doesn’t have a specific prefix, you get back a Resource type that is appropriate to that particular application context. For example, assume the following snippet of code was executed against a ClassPathXmlApplicationContext instance:

当您在特定的应用程序上下文上调用getResource()时,
指定的位置路径没有特定的前缀,您将得到一个适合于
该特定应用程序上下文的资源类型。
例如,假设下面的代码片段是针对
ClassPathXmlApplicationContext实例执行的:

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");

Against a ClassPathXmlApplicationContext, that code returns a ClassPathResource. If the same method were executed against a FileSystemXmlApplicationContext instance, it would return a FileSystemResource. For a WebApplicationContext, it would return a ServletContextResource. It would similarly return appropriate objects for each context.

根据ClassPathXmlApplicationContext,该代码返回ClassPathResource。
如果对FileSystemXmlApplicationContext实例执行相同的方法,
它将返回一个FileSystemResource。
对于WebApplicationContext,它将返回一个ServletContextResource。
它同样会为每个上下文返回适当的对象。

As a result, you can load resources in a fashion appropriate to the particular application context.

因此,您可以以适合于特定应用程序上下文的方式加载资源。

On the other hand, you may also force ClassPathResource to be used, regardless of the application context type, by specifying the special classpath: prefix, as the following example shows:

另一方面,你也可以强制ClassPathResource被使用,不管应用程序的
上下文类型是什么,通过指定特殊的classpath:前缀,如下面的例子所示:

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");

Similarly, you can force a UrlResource to be used by specifying any of the standard java.net.URL prefixes. The following pair of examples use the file and http prefixes:

类似地,您可以通过指定任何标准的java.net.URL前缀来强制使用UrlResource。
下面两个例子使用了文件和http前缀:

Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");

The following table summarizes the strategy for converting String objects to Resource objects:

下表总结了字符串对象转换为资源对象的策略:

Table 10. Resource strings

PrefixExampleExplanation
classpath:classpath:com/myapp/config.xmlLoaded from the classpath.
file:file:///data/config.xmlLoaded as a URL from the filesystem. See also FileSystemResource Caveats.
http:https://myserver/logo.pngLoaded as a URL.
(none)/data/config.xmlDepends on the underlying ApplicationContext.

2.5. The Resource

LoaderAware interface

The ResourceLoaderAware interface is a special callback interface which identifies components that expect to be provided with a ResourceLoader reference. The following listing shows the definition of the ResourceLoaderAware interface:

ResourceLoaderAware接口是一个特殊的回调接口,它标识期望
通过ResourceLoader引用提供的组件。
下面的清单显示了ResourceLoaderAware接口的定义:

public interface ResourceLoaderAware {
    void setResourceLoader(ResourceLoader resourceLoader);
}

When a class implements ResourceLoaderAware and is deployed into an application context (as a Spring-managed bean), it is recognized as ResourceLoaderAware by the application context. The application context then invokes setResourceLoader(ResourceLoader), supplying itself as the argument (remember, all application contexts in Spring implement the ResourceLoader interface).

当一个类实现ResourceLoaderAware并被部署到应用程序上下文中
(作为spring管理的bean)时,应用程序上下文中将它识别为
ResourceLoaderAware。
然后,应用程序上下文调用setResourceLoader(ResourceLoader),
将自己作为参数提供(记住,Spring中的所有应用程序上下文都实现
ResourceLoader接口)。

Since an ApplicationContext is a ResourceLoader, the bean could also implement the ApplicationContextAware interface and use the supplied application context directly to load resources. However, in general, it is better to use the specialized ResourceLoader interface if that is all you need. The code would be coupled only to the resource loading interface (which can be considered a utility interface) and not to the whole Spring ApplicationContext interface.

由于ApplicationContext是一个ResourceLoader, bean还可以
实现ApplicationContextAware接口,并直接使用提供的应用程序
上下文来加载资源。
但是,一般来说,如果您只需要使用专门的ResourceLoader接口,
那么使用它会更好。
代码只会耦合到资源加载接口(可以认为是一个实用程序接口),
而不会耦合到整个Spring ApplicationContext接口。

In application components, you may also rely upon autowiring of the ResourceLoader as an alternative to implementing the ResourceLoaderAware interface. The “traditional” constructor and byType autowiring modes (as described in Autowiring Collaborators) are capable of providing a ResourceLoader for either a constructor argument or a setter method parameter, respectively. For more flexibility (including the ability to autowire fields and multiple parameter methods), consider using the annotation-based autowiring features. In that case, the ResourceLoader is autowired into a field, constructor argument, or method parameter that expects the ResourceLoader type as long as the field, constructor, or method in question carries the @Autowired annotation. For more information, see Using @Autowired.

在应用程序组件中,你也可以依靠ResourceLoader的自动装配
来实现ResourceLoaderAware接口。
“传统的”构造函数和byType自动装配模式(如在自动装配协作器中所描述的)
能够分别为构造函数参数或setter方法参数提供一个ResourceLoader。
为了获得更大的灵活性(包括自动装配字段和多个参数方法的能力),考虑使用
基于注释的自动装配特性。
在这种情况下,ResourceLoader被自动写入一个字段、构造函数参数或方法
参数,这些参数期望ResourceLoader类型,只要相关的字段、构造函数或
方法带有@Autowired注解。更多信息,请参见使用@Autowired。

2.6. Resources as Dependencies

If the bean itself is going to determine and supply the resource path through some sort of dynamic process, it probably makes sense for the bean to use the ResourceLoader interface to load resources. For example, consider the loading of a template of some sort, where the specific resource that is needed depends on the role of the user. If the resources are static, it makes sense to eliminate the use of the ResourceLoader interface completely, have the bean expose the Resource properties it needs, and expect them to be injected into it.

2.6. 资源依赖关系
如果bean本身要通过某种动态过程来确定和提供资源路径,那么bean
使用ResourceLoader接口来加载资源可能是有意义的。
例如,考虑加载某种类型的模板,其中所需的特定资源取决于用户的角色。
如果资源是静态的,那么完全消除对ResourceLoader接口的使用,
让bean公开它需要的资源属性,并期望它们被注入其中是有意义的。

What makes it trivial to then inject these properties is that all application contexts register and use a special JavaBeans PropertyEditor, which can convert String paths to Resource objects. So, if myBean has a template property of type Resource, it can be configured with a simple string for that resource, as the following example shows:

所有应用程序上下文注册并使用一个特殊的JavaBeans PropertyEditor,
它可以将字符串路径转换为资源对象,这使得注入这些属性变得非常简单。
因此,如果myBean有一个Resource类型的模板属性,它可以为该资源
配置一个简单的字符串,如下面的示例所示:

<bean id="myBean" class="...">
    <property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>

Note that the resource path has no prefix. Consequently, because the application context itself is going to be used as the ResourceLoader, the resource itself is loaded through a ClassPathResource, a FileSystemResource, or a ServletContextResource, depending on the exact type of the context.

请注意,资源路径没有前缀。
因此,由于应用程序上下文本身将被用作ResourceLoader,
因此根据上下文的确切类型,资源本身将通过ClassPathResource、
FileSystemResource或ServletContextResource加载。

If you need to force a specific Resource type to be used, you can use a prefix. The following two examples show how to force a ClassPathResource and a UrlResource (the latter being used to access a filesystem file):

如果需要强制使用特定的资源类型,您可以使用前缀。
下面两个例子展示了如何强制执行ClassPathResource
和UrlResource(后者用于访问文件系统文件):

<property name="template" value="classpath:some/resource/path/myTemplate.txt">
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>

2.7. Application Contexts and Resource Paths

This section covers how to create application contexts with resources, including shortcuts that work with XML, how to use wildcards, and other details.

应用程序上下文和资源路径本节介绍如何创建带有资源的应用程序上下文,
包括使用XML的快捷方式、如何使用通配符以及其他细节。

2.7.1. Constructing Application Contexts

An application context constructor (for a specific application context type) generally takes a string or array of strings as the location paths of the resources, such as XML files that make up the definition of the context.

2.7.1. 构建应用程序上下文应用程序
上下文构造函数(针对特定的应用程序上下文类型)通常接受一个字符串
或字符串数组作为资源的位置路径,例如组成上下文定义的XML文件。

When such a location path does not have a prefix, the specific Resource type built from that path and used to load the bean definitions depends on and is appropriate to the specific application context. For example, consider the following example, which creates a ClassPathXmlApplicationContext:

当这样的位置路径没有前缀时,从该路径构建的用于加载bean定义的特定
资源类型依赖于特定的应用程序上下文,并且适合于特定的应用程序上下文。
例如,考虑下面的示例,它创建了一个ClassPathXmlApplicationContext:

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

The bean definitions are loaded from the classpath, because a ClassPathResource is used. However, consider the following example, which creates a FileSystemXmlApplicationContext:

bean定义是从类路径加载的,因为使用了ClassPathResource。
但是,考虑下面的示例,它创建了一个FileSystemXmlApplicationContext:

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

Now the bean definition is loaded from a filesystem location (in this case, relative to the current working directory).
Note that the use of the special classpath prefix or a standard URL prefix on the location path overrides the default type of Resource created to load the definition. Consider the following example:

现在,从文件系统位置(在本例中,相对于当前工作目录)加载bean定义。
注意,在位置路径上使用特殊的类路径前缀或标准URL前缀将覆盖为
加载定义而创建的默认资源类型。考虑下面的例子:

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

Using FileSystemXmlApplicationContext loads the bean definitions from the classpath. However, it is still a FileSystemXmlApplicationContext. If it is subsequently used as a ResourceLoader, any unprefixed paths are still treated as filesystem paths.

使用FileSystemXmlApplicationContext从类路径加载bean定义。
但是,它仍然是一个FileSystemXmlApplicationContext。
如果它随后被用作ResourceLoader,那么任何没有前缀的路径
仍然被视为文件系统路径。

Constructing ClassPathXmlApplicationContext Instances — Shortcuts

The ClassPathXmlApplicationContext exposes a number of constructors to enable convenient instantiation. The basic idea is that you can supply merely a string array that contains only the filenames of the XML files themselves (without the leading path information) and also supplies a Class. The ClassPathXmlApplicationContext then derives the path information from the supplied class.

构造ClassPathXmlApplicationContext实例—快捷键
ClassPathXmlApplicationContext公开了许多构造函数来启用方便的实例化。
基本思想是,您可以仅提供一个字符串数组,其中只包含XML文件
本身的文件名(不包含前导路径信息),还可以提供一个类。
然后ClassPathXmlApplicationContext从提供的类派生路径信息。

Consider the following directory layout:

考虑以下目录布局:

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

The following example shows how a ClassPathXmlApplicationContext instance composed of the beans defined in files named services.xml and daos.xml (which are on the classpath) can be instantiated:

下面的示例展示了如何实例化ClassPathXmlApplicationContext实例,
该实例由命名为services.xml和dao .xml(在类路径上)的文件中定义的bean组成:

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

See the ClassPathXmlApplicationContext javadoc for details on the various constructors.

有关各种构造函数的详细信息,请参阅ClassPathXmlApplicationContext javadoc。

2.7.2. Wildcards in Application Context Constructor Resource Paths

The resource paths in application context constructor values may be simple paths (as shown earlier), each of which has a one-to-one mapping to a target Resource or, alternately, may contain the special “classpath*:” prefix or internal Ant-style regular expressions (matched by using Spring’s PathMatcher utility). Both of the latter are effectively wildcards.

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

One use for this mechanism is when you need to do component-style application assembly. All components can ‘publish’ context definition fragments to a well-known location path, and, when the final application context is created using the same path prefixed with classpath*:, all component fragments are automatically picked up.

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

Note that this wildcarding is specific to the use of resource paths in application context constructors (or when you use the PathMatcher utility class hierarchy directly) and is resolved at construction time. It has nothing to do with the Resource type itself. You cannot use the classpath*: prefix to construct an actual Resource, as a resource points to just one resource at a time.

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

Ant-style Patterns

Path locations can contain Ant-style patterns, as the following example shows:

Ant样式的模式
基于模式路径位置可以包含ant样式的模式,如下面的例子所示:

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

When the path location contains an Ant-style pattern, the resolver follows a more complex procedure to try to resolve the wildcard. It produces a Resource for the path up to the last non-wildcard segment and obtains a URL from it. If this URL is not a jar: URL or container-specific variant (such as zip: in WebLogic, wsjar in WebSphere, and so on), a java.io.File is obtained from it and used to resolve the wildcard by traversing the filesystem. In the case of a jar URL, the resolver either gets a java.net.JarURLConnection from it or manually parses the jar URL and then traverses the contents of the jar file to resolve the wildcards.

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

Implications on Portability

If the specified path is already a file URL (either implicitly because the base ResourceLoader is a filesystem one or explicitly), wildcarding is guaranteed to work in a completely portable fashion.

影响可移植性
如果指定的路径已经是文件URL
(可能是隐式的,因为基本ResourceLoader是文件系统URL,也可能是显式的),
那么可以保证通配符以完全可移植的方式工作。

If the specified path is a classpath location, the resolver must obtain the last non-wildcard path segment URL by making a Classloader.getResource() call. Since this is just a node of the path (not the file at the end), it is actually undefined (in the ClassLoader javadoc) exactly what sort of a URL is returned in this case. In practice, it is always a java.io.File representing the directory (where the classpath resource resolves to a filesystem location) or a jar URL of some sort (where the classpath resource resolves to a jar location). Still, there is a portability concern on this operation.

如果指定的路径是类路径位置,则解析器必须通过调用
Classloader.getResource()来获取最后一个非通配符路径段URL。
由于这只是路径的一个节点(而不是最后的文件),因此在这种情况下,
它实际上没有确切定义(在类加载器javadoc中)返回何种类型的URL。
实际上,它总是java.io.File表示目录(其中类路径资源解析为文件系统位置)
或某种类型的jar URL(其中类路径资源解析为jar位置)的文件。
不过,这个操作还有一个可移植性问题。

If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to get a java.net.JarURLConnection from it or manually parse the jar URL, to be able to walk the contents of the jar and resolve the wildcard. This does work in most environments but fails in others, and we strongly recommend that the wildcard resolution of resources coming from jars be thoroughly tested in your specific environment before you rely on it.

如果获得了最后一个非通配符段的jar URL,那么解析器必须能够从中获得
java.net.JarURLConnection,或者手动解析jar URL,以便能够遍历jar的
内容并解析通配符。
这在大多数环境中可以工作,但在其他环境中会失败,我们强烈建议在依赖
于jar资源的通配符解析之前,在您的特定环境中彻底测试它。

The classpath*: Prefix

When constructing an XML-based application context, a location string may use the special classpath*: prefix, as the following example shows:

classpath *:前缀
在构造基于xml的应用程序上下文时,位置字符串可能使用特殊的
classpath*:前缀,如下面的示例所示:

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

This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens through a call to ClassLoader.getResources(…​)) and then merged to form the final application context definition.

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

The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ, especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar on the classpath: getClass().getClassLoader().getResources(""). Try this test with files that have the same name but are placed inside two different locations. In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.

通配符类路径依赖于基础类加载器的getResources()方法。
由于大多数应用程序服务器现在都提供它们自己的类加载器实现,
所以行为可能会有所不同,尤其是在处理jar文件时。
检查classpath*是否工作的一个简单测试是使用类加载器从类路径的
jar中加载一个文件:
getClass(). getclassloader (). getresources ("<someFileInsideTheJar>")。
请对具有相同名称但位于两个不同位置的文件进行此测试。
如果返回了不适当的结果,请检查应用服务器文档中可能影响类加载器行为的设置。

You can also combine the classpath*: prefix with a PathMatcher pattern in the rest of the location path (for example, classpath*:META-INF/* -beans.xml). In this case, the resolution strategy is fairly simple: A ClassLoader.getResources() call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy and then, off each resource, the same PathMatcher resolution strategy described earlier is used for the wildcard subpath.

您还可以将classpath*:前缀与路径匹配器模式组合在位置路径的其余部分
(例如,classpath*:META-INF/* -beans.xml)。
在这种情况下,解决策略是相当简单的:
一个ClassLoader.getResources()调用用于non-wildcard路径段
最后一个类加载器层次结构中的所有匹配的资源,然后每个资源,
前面描述的相同PathMatcher解决策略用于通配符子路径。

Other Notes Relating to Wildcards

Note that classpath*:, when combined with Ant-style patterns, only works reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern such as classpath*😗 .xml might not retrieve files from the root of jar files but rather only from the root of expanded directories.

与通配符有关的其他说明
注意,当classpath*:与Ant样式的模式结合使用时,在模式开始之前只能
可靠地在至少一个根目录下工作,除非实际的目标文件驻留在文件系统中。
这意味着classpath*:* .xml之类的模式可能不会从jar文件的根目录检索文件,
而只是从展开目录的根目录检索文件。

Spring’s ability to retrieve classpath entries originates from the JDK’s ClassLoader.getResources() method, which only returns file system locations for an empty string (indicating potential roots to search). Spring evaluates URLClassLoader runtime configuration and the java.class.path manifest in jar files as well, but this is not guaranteed to lead to portable behavior.

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

The scanning of classpath packages requires the presence of corresponding directory entries in the classpath. When you build JARs with Ant, do not activate the files-only switch of the JAR task. Also, classpath directories may not get exposed based on security policies in some environments — for example, stand-alone applications on JDK 1.7.0_45 and higher (which requires ‘Trusted-Library’ to be set up in your manifests. See https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).

类路径包的扫描要求类路径中存在相应的目录项。
当您使用Ant构建JAR时,不要激活JAR任务的文件切换。
另外,在某些环境中,基于安全策略,类路径目录可能不会公开
——例如,JDK 1.7.0_45或更高版本上的独立应用程序
(需要在清单中设置“可信库”)。
见https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。

On JDK 9’s module path (Jigsaw), Spring’s classpath scanning generally works as expected. Putting resources into a dedicated directory is highly recommendable here as well, avoiding the aforementioned portability problems with searching the jar file root level.

在JDK 9的模块路径(Jigsaw)上,Spring的类路径扫描通常按预期工作。
这里也高度推荐将资源放在专用目录中,以避免搜索jar文件根级别时出现的
可移植性问题。

Ant-style patterns with classpath: resources are not guaranteed to find matching resources if the root package to search is available in multiple class path locations. Consider the following example of a resource location:

带有类路径的Ant样式模式:如果要搜索的根包在多个类路径位置中可用,
则资源不能保证找到匹配的资源。考虑以下资源位置的例子:

com/mycompany/package1/service-context.xml

Now consider an Ant-style path that someone might use to try to find that file:

现在考虑一个Ant样式的路径,有人可能会使用它来尝试寻找该文件:

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

Such a resource may be in only one location, but when a path such as the preceding example is used to try to resolve it, the resolver works off the (first) URL returned by getResource(“com/mycompany”);. If this base package node exists in multiple classloader locations, the actual end resource may not be there. Therefore, in such a case you should prefer using classpath*: with the same Ant-style pattern, which searches all class path locations that contain the root package.

这样的资源可能只位于一个位置,但是当使用像前面示例那样的路径
试图解析它时,解析器将从getResource("com/mycompany");
返回的(第一个)URL中工作。
如果此基包节点存在于多个类加载器位置,则实际的最终资源可能不存在。
因此,在这种情况下,您应该更喜欢使用classpath*:带有相同的Ant样式的
模式,它搜索包含根包的所有类路径位置。

2.7.3. FileSystemResource Caveats

A FileSystemResource that is not attached to a FileSystemApplicationContext (that is, when a FileSystemApplicationContext is not the actual ResourceLoader) treats absolute and relative paths as you would expect. Relative paths are relative to the current working directory, while absolute paths are relative to the root of the filesystem.

2.7.3.FileSystemResource说明
没有附加到FileSystemApplicationContext
(也就是说,当FileSystemApplicationContext不是实际的ResourceLoader时)
的FileSystemResource将像您预期的那样处理绝对路径和相对路径。
相对路径相对于当前工作目录,而绝对路径相对于文件系统的根目录。


caveat 
英 /ˈkæviæt/  美 /ˈkæviæt/  全球(美国)  
n. 警告;中止诉讼手续的申请;货物出门概不退换;停止支付的广告

For backwards compatibility (historical) reasons however, this changes when the FileSystemApplicationContext is the ResourceLoader. The FileSystemApplicationContext forces all attached FileSystemResource instances to treat all location paths as relative, whether they start with a leading slash or not. In practice, this means the following examples are equivalent:

然而,由于向后兼容性(历史上的)原因,当FileSystemApplicationContext是
ResourceLoader时,这一点会改变。
FileSystemApplicationContext强制所有附加的FileSystemResource实例将
所有位置路径视为相对路径,无论它们是否以首斜杠开始。
实际上,这意味着下面的例子是等价的:

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

The following examples are also equivalent (even though it would make sense for them to be different, as one case is relative and the other absolute):

下面的例子也是相同的
(尽管它们看起来是不同的,因为一种情况是相对的,另一种情况是绝对的):

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

In practice, if you need true absolute filesystem paths, you should avoid using absolute paths with FileSystemResource or FileSystemXmlApplicationContext and force the use of a UrlResource by using the file: URL prefix. The following examples show how to do so:

在实践中,如果需要真正的绝对文件系统路径,应该避免使用绝对路径
与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");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值