001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.context.annotation;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Repeatable;
022import java.lang.annotation.Retention;
023import java.lang.annotation.RetentionPolicy;
024import java.lang.annotation.Target;
025
026import org.springframework.core.io.support.PropertySourceFactory;
027
028/**
029 * Annotation providing a convenient and declarative mechanism for adding a
030 * {@link org.springframework.core.env.PropertySource PropertySource} to Spring's
031 * {@link org.springframework.core.env.Environment Environment}. To be used in
032 * conjunction with @{@link Configuration} classes.
033 *
034 * <h3>Example usage</h3>
035 *
036 * <p>Given a file {@code app.properties} containing the key/value pair
037 * {@code testbean.name=myTestBean}, the following {@code @Configuration} class
038 * uses {@code @PropertySource} to contribute {@code app.properties} to the
039 * {@code Environment}'s set of {@code PropertySources}.
040 *
041 * <pre class="code">
042 * &#064;Configuration
043 * &#064;PropertySource("classpath:/com/myco/app.properties")
044 * public class AppConfig {
045 *
046 *     &#064;Autowired
047 *     Environment env;
048 *
049 *     &#064;Bean
050 *     public TestBean testBean() {
051 *         TestBean testBean = new TestBean();
052 *         testBean.setName(env.getProperty("testbean.name"));
053 *         return testBean;
054 *     }
055 * }</pre>
056 *
057 * <p>Notice that the {@code Environment} object is
058 * {@link org.springframework.beans.factory.annotation.Autowired @Autowired} into the
059 * configuration class and then used when populating the {@code TestBean} object. Given
060 * the configuration above, a call to {@code testBean.getName()} will return "myTestBean".
061 *
062 * <h3>Resolving <code>${...}</code> placeholders in {@code <bean>} and {@code @Value} annotations</h3>
063 *
064 * <p>In order to resolve ${...} placeholders in {@code <bean>} definitions or {@code @Value}
065 * annotations using properties from a {@code PropertySource}, you must ensure that an
066 * appropriate <em>embedded value resolver</em> is registered in the {@code BeanFactory}
067 * used by the {@code ApplicationContext}. This happens automatically when using
068 * {@code <context:property-placeholder>} in XML. When using {@code @Configuration} classes
069 * this can be achieved by explicitly registering a {@code PropertySourcesPlaceholderConfigurer}
070 * via a {@code static} {@code @Bean} method. Note, however, that explicit registration
071 * of a {@code PropertySourcesPlaceholderConfigurer} via a {@code static} {@code @Bean}
072 * method is typically only required if you need to customize configuration such as the
073 * placeholder syntax, etc. See the "Working with externalized values" section of
074 * {@link Configuration @Configuration}'s javadocs and "a note on
075 * BeanFactoryPostProcessor-returning {@code @Bean} methods" of {@link Bean @Bean}'s
076 * javadocs for details and examples.
077 *
078 * <h3>Resolving ${...} placeholders within {@code @PropertySource} resource locations</h3>
079 *
080 * <p>Any ${...} placeholders present in a {@code @PropertySource} {@linkplain #value()
081 * resource location} will be resolved against the set of property sources already
082 * registered against the environment. For example:
083 *
084 * <pre class="code">
085 * &#064;Configuration
086 * &#064;PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
087 * public class AppConfig {
088 *
089 *     &#064;Autowired
090 *     Environment env;
091 *
092 *     &#064;Bean
093 *     public TestBean testBean() {
094 *         TestBean testBean = new TestBean();
095 *         testBean.setName(env.getProperty("testbean.name"));
096 *         return testBean;
097 *     }
098 * }</pre>
099 *
100 * <p>Assuming that "my.placeholder" is present in one of the property sources already
101 * registered, e.g. system properties or environment variables, the placeholder will
102 * be resolved to the corresponding value. If not, then "default/path" will be used as a
103 * default. Expressing a default value (delimited by colon ":") is optional.  If no
104 * default is specified and a property cannot be resolved, an {@code
105 * IllegalArgumentException} will be thrown.
106 *
107 * <h3>A note on property overriding with @PropertySource</h3>
108 *
109 * <p>In cases where a given property key exists in more than one {@code .properties}
110 * file, the last {@code @PropertySource} annotation processed will 'win' and override.
111 *
112 * <p>For example, given two properties files {@code a.properties} and
113 * {@code b.properties}, consider the following two configuration classes
114 * that reference them with {@code @PropertySource} annotations:
115 *
116 * <pre class="code">
117 * &#064;Configuration
118 * &#064;PropertySource("classpath:/com/myco/a.properties")
119 * public class ConfigA { }
120 *
121 * &#064;Configuration
122 * &#064;PropertySource("classpath:/com/myco/b.properties")
123 * public class ConfigB { }
124 * </pre>
125 *
126 * <p>The override ordering depends on the order in which these classes are registered
127 * with the application context.
128 *
129 * <pre class="code">
130 * AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
131 * ctx.register(ConfigA.class);
132 * ctx.register(ConfigB.class);
133 * ctx.refresh();
134 * </pre>
135 *
136 * <p>In the scenario above, the properties in {@code b.properties} will override any
137 * duplicates that exist in {@code a.properties}, because {@code ConfigB} was registered
138 * last.
139 *
140 * <p>In certain situations, it may not be possible or practical to tightly control
141 * property source ordering when using {@code @PropertySource} annotations. For example,
142 * if the {@code @Configuration} classes above were registered via component-scanning,
143 * the ordering is difficult to predict. In such cases - and if overriding is important -
144 * it is recommended that the user fall back to using the programmatic PropertySource API.
145 * See {@link org.springframework.core.env.ConfigurableEnvironment ConfigurableEnvironment}
146 * and {@link org.springframework.core.env.MutablePropertySources MutablePropertySources}
147 * javadocs for details.
148 *
149 * <p><b>NOTE: This annotation is repeatable according to Java 8 conventions.</b>
150 * However, all such {@code @PropertySource} annotations need to be declared at the same
151 * level: either directly on the configuration class or as meta-annotations within the
152 * same custom annotation. Mixing of direct annotations and meta-annotations is not
153 * recommended since direct annotations will effectively override meta-annotations.
154 *
155 * @author Chris Beams
156 * @author Juergen Hoeller
157 * @author Phillip Webb
158 * @author Sam Brannen
159 * @since 3.1
160 * @see PropertySources
161 * @see Configuration
162 * @see org.springframework.core.env.PropertySource
163 * @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()
164 * @see org.springframework.core.env.MutablePropertySources
165 */
166@Target(ElementType.TYPE)
167@Retention(RetentionPolicy.RUNTIME)
168@Documented
169@Repeatable(PropertySources.class)
170public @interface PropertySource {
171
172        /**
173         * Indicate the name of this property source. If omitted, the {@link #factory()}
174         * will generate a name based on the underlying resource (in the case of
175         * {@link org.springframework.core.io.support.DefaultPropertySourceFactory}:
176         * derived from the resource description through a corresponding name-less
177         * {@link org.springframework.core.io.support.ResourcePropertySource} constructor).
178         * @see org.springframework.core.env.PropertySource#getName()
179         * @see org.springframework.core.io.Resource#getDescription()
180         */
181        String name() default "";
182
183        /**
184         * Indicate the resource location(s) of the properties file to be loaded.
185         * <p>Both traditional and XML-based properties file formats are supported
186         * &mdash; for example, {@code "classpath:/com/myco/app.properties"}
187         * or {@code "file:/path/to/file.xml"}.
188         * <p>Resource location wildcards (e.g. *&#42;/*.properties) are not permitted;
189         * each location must evaluate to exactly one {@code .properties} resource.
190         * <p>${...} placeholders will be resolved against any/all property sources already
191         * registered with the {@code Environment}. See {@linkplain PropertySource above}
192         * for examples.
193         * <p>Each location will be added to the enclosing {@code Environment} as its own
194         * property source, and in the order declared.
195         */
196        String[] value();
197
198        /**
199         * Indicate if failure to find the a {@link #value() property resource} should be
200         * ignored.
201         * <p>{@code true} is appropriate if the properties file is completely optional.
202         * Default is {@code false}.
203         * @since 4.0
204         */
205        boolean ignoreResourceNotFound() default false;
206
207        /**
208         * A specific character encoding for the given resources, e.g. "UTF-8".
209         * @since 4.3
210         */
211        String encoding() default "";
212
213        /**
214         * Specify a custom {@link PropertySourceFactory}, if any.
215         * <p>By default, a default factory for standard resource files will be used.
216         * @since 4.3
217         * @see org.springframework.core.io.support.DefaultPropertySourceFactory
218         * @see org.springframework.core.io.support.ResourcePropertySource
219         */
220        Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
221
222}