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 * @Configuration 043 * @PropertySource("classpath:/com/myco/app.properties") 044 * public class AppConfig { 045 * 046 * @Autowired 047 * Environment env; 048 * 049 * @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 * @Configuration 086 * @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") 087 * public class AppConfig { 088 * 089 * @Autowired 090 * Environment env; 091 * 092 * @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 * @Configuration 118 * @PropertySource("classpath:/com/myco/a.properties") 119 * public class ConfigA { } 120 * 121 * @Configuration 122 * @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 * — for example, {@code "classpath:/com/myco/app.properties"} 187 * or {@code "file:/path/to/file.xml"}. 188 * <p>Resource location wildcards (e.g. **/*.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}