如果 Bean 本身要通过某种动态过程来确定和提供资源路径,那么 Bean 使用 ResourceLoader 或 ResourcePatternResolver 接口来加载资源可能是有意义的。例如,考虑加载某种模板,其中需要的特定资源取决于用户的角色。如果资源是静态的,那么完全不使用 ResourceLoader 接口(或 ResourcePatternResolver 接口)是有意义的,让 Bean 暴露它所需要的资源属性,并期望它们被注入其中。
然后注入这些属性的琐碎之处在于,所有的应用程序上下文都注册并使用一个特殊的 JavaBeans PropertyEditor,它可以将字符串路径转换为资源对象。例如,下面的 MyBean 类有一个资源类型的模板属性:
package example;
public class MyBean {
private Resource template;
public setTemplate(Resource template) {
this.template = template;
}
// ...
}
在 XML 配置文件中,模板属性可以用该资源的一个简单字符串来配置,如下例所示:
<bean id="myBean" class="example.MyBean">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
请注意,资源路径没有前缀。因此,由于应用程序上下文本身将被用作资源加载器,所以资源将通过ClassPathResource、FileSystemResource 或 ServletContextResource 加载,这取决于应用程序上下文的具体类型。
如果你需要强制使用一个特定的资源类型,你可以使用一个前缀。下面两个例子显示了如何强制使用ClassPathResource 和 UrlResource(后者用于访问文件系统中的一个文件):
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
另一个
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
如果 MyBean 类被重构以用于注解驱动的配置,myTemplate.txt 的路径可以存储在一个名为 template.path
的键下,例如,在一个提供给 Spring 环境的属性文件中(见 环境抽象)。然后,模板路径可以通过 @Value
注解用属性占位符来引用(见使用 @Value)。Spring 将以字符串的形式检索模板路径的值,一个特殊的 PropertyEditor 将把字符串转换为 Resource 对象,注入到 MyBean 构造函数中。下面的例子演示了如何实现这一点:
@Component
public class MyBean {
private final Resource template;
public MyBean(@Value("${template.path}") Resource template) {
this.template = template;
}
// ...
}
如果我们想支持在 classpath 的多个位置,例如在 classpath 的多个 jars 中的同一路径下发现的多个模板,我们可以使用特殊的 classpath*
: 前缀和通配符来定义 templates.path 键为classpath*:/config/templates/*.txt
。如果我们重新定义 MyBean 类如下,Spring 将把模板路径模式转换为一个资源对象数组,可以注入 MyBean 构造函数中:
@Component
public class MyBean {
private final Resource[] templates;
public MyBean(@Value("${templates.path}") Resource[] templates) {
this.templates = templates;
}
// ...
}