/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.io.support.PropertySourceFactory;
Annotation providing a convenient and declarative mechanism for adding a PropertySource
to Spring's Environment
. To be used in conjunction with @Configuration
classes. Example usage
Given a file app.properties
containing the key/value pair testbean.name=myTestBean
, the following @Configuration
class uses @PropertySource
to contribute app.properties
to the Environment
's set of PropertySources
.
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
Notice that the Environment
object is @Autowired
into the configuration class and then used when populating the TestBean
object. Given the configuration above, a call to testBean.getName()
will return "myTestBean".
Resolving ${...}
placeholders in <bean>
and @Value
annotations
In order to resolve ${...} placeholders in <bean>
definitions or @Value
annotations using properties from a PropertySource
, you must ensure that an appropriate embedded value resolver is registered in the BeanFactory
used by the ApplicationContext
. This happens automatically when using <context:property-placeholder>
in XML. When using @Configuration
classes this can be achieved by explicitly registering a PropertySourcesPlaceholderConfigurer
via a static
@Bean
method. Note, however, that explicit registration of a PropertySourcesPlaceholderConfigurer
via a static
@Bean
method is typically only required if you need to customize configuration such as the placeholder syntax, etc. See the "Working with externalized values" section of @Configuration
's javadocs and "a note on BeanFactoryPostProcessor-returning @Bean
methods" of @Bean
's javadocs for details and examples.
Resolving ${...} placeholders within @PropertySource
resource locations
Any ${...} placeholders present in a @PropertySource
resource location will be resolved against the set of property sources already registered against the environment. For example:
@Configuration
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}
Assuming that "my.placeholder" is present in one of the property sources already registered — for example, system properties or environment variables — the placeholder will be resolved to the corresponding value. If not, then "default/path" will be used as a default. Expressing a default value (delimited by colon ":") is optional. If no default is specified and a property cannot be resolved, an
IllegalArgumentException
will be thrown.
A note on property overriding with @PropertySource
In cases where a given property key exists in more than one .properties
file, the last @PropertySource
annotation processed will 'win' and override any previous key with the same name.
For example, given two properties files a.properties
and b.properties
, consider the following two configuration classes that reference them with @PropertySource
annotations:
@Configuration
@PropertySource("classpath:/com/myco/a.properties")
public class ConfigA { }
@Configuration
@PropertySource("classpath:/com/myco/b.properties")
public class ConfigB { }
The override ordering depends on the order in which these classes are registered
with the application context.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConfigA.class);
ctx.register(ConfigB.class);
ctx.refresh();
In the scenario above, the properties in b.properties
will override any duplicates that exist in a.properties
, because ConfigB
was registered last.
In certain situations, it may not be possible or practical to tightly control property source ordering when using @PropertySource
annotations. For example, if the @Configuration
classes above were registered via component-scanning, the ordering is difficult to predict. In such cases — and if overriding is important — it is recommended that the user fall back to using the programmatic PropertySource
API. See
ConfigurableEnvironment
and
MutablePropertySources
javadocs for details.
NOTE: This annotation is repeatable according to Java 8 conventions. However, all such @PropertySource
annotations need to be declared at the same level: either directly on the configuration class or as meta-annotations on the same custom annotation. Mixing direct annotations and meta-annotations is not recommended since direct annotations will effectively override meta-annotations.
Author: Chris Beams, Juergen Hoeller, Phillip Webb, Sam Brannen See Also: Since: 3.1
/**
* Annotation providing a convenient and declarative mechanism for adding a
* {@link org.springframework.core.env.PropertySource PropertySource} to Spring's
* {@link org.springframework.core.env.Environment Environment}. To be used in
* conjunction with @{@link Configuration} classes.
*
* <h3>Example usage</h3>
*
* <p>Given a file {@code app.properties} containing the key/value pair
* {@code testbean.name=myTestBean}, the following {@code @Configuration} class
* uses {@code @PropertySource} to contribute {@code app.properties} to the
* {@code Environment}'s set of {@code PropertySources}.
*
* <pre class="code">
* @Configuration
* @PropertySource("classpath:/com/myco/app.properties")
* public class AppConfig {
*
* @Autowired
* Environment env;
*
* @Bean
* public TestBean testBean() {
* TestBean testBean = new TestBean();
* testBean.setName(env.getProperty("testbean.name"));
* return testBean;
* }
* }</pre>
*
* <p>Notice that the {@code Environment} object is
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired} into the
* configuration class and then used when populating the {@code TestBean} object. Given
* the configuration above, a call to {@code testBean.getName()} will return "myTestBean".
*
* <h3>Resolving <code>${...}</code> placeholders in {@code <bean>} and {@code @Value} annotations</h3>
*
* <p>In order to resolve ${...} placeholders in {@code <bean>} definitions or {@code @Value}
* annotations using properties from a {@code PropertySource}, you must ensure that an
* appropriate <em>embedded value resolver</em> is registered in the {@code BeanFactory}
* used by the {@code ApplicationContext}. This happens automatically when using
* {@code <context:property-placeholder>} in XML. When using {@code @Configuration} classes
* this can be achieved by explicitly registering a {@code PropertySourcesPlaceholderConfigurer}
* via a {@code static} {@code @Bean} method. Note, however, that explicit registration
* of a {@code PropertySourcesPlaceholderConfigurer} via a {@code static} {@code @Bean}
* method is typically only required if you need to customize configuration such as the
* placeholder syntax, etc. See the "Working with externalized values" section of
* {@link Configuration @Configuration}'s javadocs and "a note on
* BeanFactoryPostProcessor-returning {@code @Bean} methods" of {@link Bean @Bean}'s
* javadocs for details and examples.
*
* <h3>Resolving ${...} placeholders within {@code @PropertySource} resource locations</h3>
*
* <p>Any ${...} placeholders present in a {@code @PropertySource} {@linkplain #value()
* resource location} will be resolved against the set of property sources already
* registered against the environment. For example:
*
* <pre class="code">
* @Configuration
* @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
* public class AppConfig {
*
* @Autowired
* Environment env;
*
* @Bean
* public TestBean testBean() {
* TestBean testBean = new TestBean();
* testBean.setName(env.getProperty("testbean.name"));
* return testBean;
* }
* }</pre>
*
* <p>Assuming that "my.placeholder" is present in one of the property sources already
* registered — for example, system properties or environment variables —
* the placeholder will be resolved to the corresponding value. If not, then "default/path"
* will be used as a default. Expressing a default value (delimited by colon ":") is
* optional. If no default is specified and a property cannot be resolved, an {@code
* IllegalArgumentException} will be thrown.
*
* <h3>A note on property overriding with {@code @PropertySource}</h3>
*
* <p>In cases where a given property key exists in more than one {@code .properties}
* file, the last {@code @PropertySource} annotation processed will 'win' and override
* any previous key with the same name.
*
* <p>For example, given two properties files {@code a.properties} and
* {@code b.properties}, consider the following two configuration classes
* that reference them with {@code @PropertySource} annotations:
*
* <pre class="code">
* @Configuration
* @PropertySource("classpath:/com/myco/a.properties")
* public class ConfigA { }
*
* @Configuration
* @PropertySource("classpath:/com/myco/b.properties")
* public class ConfigB { }
* </pre>
*
* <p>The override ordering depends on the order in which these classes are registered
* with the application context.
*
* <pre class="code">
* AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
* ctx.register(ConfigA.class);
* ctx.register(ConfigB.class);
* ctx.refresh();
* </pre>
*
* <p>In the scenario above, the properties in {@code b.properties} will override any
* duplicates that exist in {@code a.properties}, because {@code ConfigB} was registered
* last.
*
* <p>In certain situations, it may not be possible or practical to tightly control
* property source ordering when using {@code @PropertySource} annotations. For example,
* if the {@code @Configuration} classes above were registered via component-scanning,
* the ordering is difficult to predict. In such cases — and if overriding is important
* — it is recommended that the user fall back to using the programmatic
* {@code PropertySource} API. See {@link org.springframework.core.env.ConfigurableEnvironment
* ConfigurableEnvironment} and {@link org.springframework.core.env.MutablePropertySources
* MutablePropertySources} javadocs for details.
*
* <p><b>NOTE: This annotation is repeatable according to Java 8 conventions.</b>
* However, all such {@code @PropertySource} annotations need to be declared at the same
* level: either directly on the configuration class or as meta-annotations on the
* same custom annotation. Mixing direct annotations and meta-annotations is not
* recommended since direct annotations will effectively override meta-annotations.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Phillip Webb
* @author Sam Brannen
* @since 3.1
* @see PropertySources
* @see Configuration
* @see org.springframework.core.env.PropertySource
* @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()
* @see org.springframework.core.env.MutablePropertySources
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
Indicate the name of this property source. If omitted, the factory
will generate a name based on the underlying resource (in the case of DefaultPropertySourceFactory
: derived from the resource description through a corresponding name-less ResourcePropertySource
constructor). See Also:
/**
* Indicate the name of this property source. If omitted, the {@link #factory}
* will generate a name based on the underlying resource (in the case of
* {@link org.springframework.core.io.support.DefaultPropertySourceFactory}:
* derived from the resource description through a corresponding name-less
* {@link org.springframework.core.io.support.ResourcePropertySource} constructor).
* @see org.springframework.core.env.PropertySource#getName()
* @see org.springframework.core.io.Resource#getDescription()
*/
String name() default "";
Indicate the resource location(s) of the properties file to be loaded.
Both traditional and XML-based properties file formats are supported — for example, "classpath:/com/myco/app.properties"
or "file:/path/to/file.xml"
.
Resource location wildcards (e.g. **/*.properties) are not permitted; each location must evaluate to exactly one .properties
or .xml
resource.
${...} placeholders will be resolved against any/all property sources already registered with the Environment
. See above for examples.
Each location will be added to the enclosing Environment
as its own property source, and in the order declared.
/**
* Indicate the resource location(s) of the properties file to be loaded.
* <p>Both traditional and XML-based properties file formats are supported
* — for example, {@code "classpath:/com/myco/app.properties"}
* or {@code "file:/path/to/file.xml"}.
* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;
* each location must evaluate to exactly one {@code .properties} or {@code .xml}
* resource.
* <p>${...} placeholders will be resolved against any/all property sources already
* registered with the {@code Environment}. See {@linkplain PropertySource above}
* for examples.
* <p>Each location will be added to the enclosing {@code Environment} as its own
* property source, and in the order declared.
*/
String[] value();
Indicate if a failure to find a property resource
should be ignored. true
is appropriate if the properties file is completely optional.
Default is false
.
Since: 4.0
/**
* Indicate if a failure to find a {@link #value property resource} should be
* ignored.
* <p>{@code true} is appropriate if the properties file is completely optional.
* <p>Default is {@code false}.
* @since 4.0
*/
boolean ignoreResourceNotFound() default false;
A specific character encoding for the given resources, e.g. "UTF-8".
Since: 4.3
/**
* A specific character encoding for the given resources, e.g. "UTF-8".
* @since 4.3
*/
String encoding() default "";
Specify a custom PropertySourceFactory
, if any. By default, a default factory for standard resource files will be used.
See Also: Since: 4.3
/**
* Specify a custom {@link PropertySourceFactory}, if any.
* <p>By default, a default factory for standard resource files will be used.
* @since 4.3
* @see org.springframework.core.io.support.DefaultPropertySourceFactory
* @see org.springframework.core.io.support.ResourcePropertySource
*/
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}