If the bean will independently determine and provide the path to resources through some dynamic process, it probably
makes sense to use the ResourceLoader
or ResourcePatternResolver
interface to load
resources. For example, consider loading a template where the specific resource needed depends on the user's role.
If the resources are static, then it makes sense to completely abandon the use of the ResourceLoader
interface (or the ResourcePatternResolver
interface), let the bean expose the Resource
properties that it needs, and expects them to be embedded in it.
What makes it trivial to subsequently implement these properties is that all application contexts register and use a
special PropertyEditor
JavaBeans class that can convert String
paths to objects Resource
.
For example, the following class MyBean
has a property template
of type
Resource
.
package example;
public class MyBean {
private Resource template;
public setTemplate(Resource template) {
this.template = template;
}
// ...
}
class MyBean(var template: Resource)
In an XML configuration file, the template
property can be configured with a simple string for a given
resource, as shown in the following example:
<bean id="myBean" class="example.MyBean">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
Note that the resource path does not have a prefix. Therefore, since the application context itself will be used as a
ResourceLoader
, the resource is loaded via ClassPathResource
,
FileSystemResource
or ServletContextResource
depending on the exact type of application
context.
If you need to force the use of a specific Resource
type, you can use a prefix. The following two
examples show how to force the use of ClassPathResource
and UrlResource
(the latter is
used to access a file on the file system):
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
If the MyBean
class is refactored (redesigned) for use with annotation-driven configuration, the path to
myTemplate.txt
can be stored in a key named template.path
- for example, in the
properties file available for Environment
in Spring. The template path can then be referenced with the
@Value
annotation using the property placeholder. Spring will receive the template path value as a
string, and a special PropertyEditor
will convert the string into a Resource
object, which
will be injected into the MyBean
constructor. The following example shows how to achieve this.
@Component
public class MyBean {
private final Resource template;
public MyBean(@Value("${template.path}") Resource template) {
this.template = template;
}
// ...
}
@Component
class MyBean(@Value("\${template.path}") private val template: Resource)
If we want to support multiple templates found in the same path in multiple places on the classpath - for example, in
multiple jars on the classpath - we can use a special prefix classpath*:
and wildcards to define the
templates.path
key as classpath*:/config/templates/*.txt
. If we override the
MyBean
class as follows, Spring converts the template path template into an array of
Resource
objects that can be injected into the MyBean
constructor.
@Component
public class MyBean {
private final Resource[] templates;
public MyBean(@Value("${templates.path}") Resource[] templates) {
this.templates = templates;
}
// ...
}
@Component
class MyBean(@Value("\${templates.path}") private val templates: Resource[])