spring-context中@PropertySources和@PropertySource的源码解析说明
spring版本为5.0.11
@PropertySource加载指定的属性文件(*.properties)到 Spring 的 Environment 中。
- @PropertySource 和 @Value 组合使用,可以将自定义属性文件中的属性变量值注入到当前类的使用@Value注解的成员变量中。
- @PropertySource 和 @ConfigurationProperties 组合使用,可以将属性文件与一个Java类绑定,将属性文件中的变量值注入到该Java类的成员变量中
@PropertySources注解就是@PropertySource的数组集合
@PropertySource源码
/** * 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, e.g. 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 @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. * * <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 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 within the * same custom annotation. Mixing of 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, a name will * be generated based on the description of the underlying resource. * @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. * <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} 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(); /** * 表明如果没发现资源应当忽视,默认是false * Indicate if failure to find the a {@link #value() property resource} should be * ignored. * <p>{@code true} is appropriate if the properties file is completely optional. * 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 */ String encoding() default ""; /** * 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; }
@PropertySources源码
/** * Container annotation that aggregates several {@link PropertySource} annotations. * 聚合多个@PropertySource注解的容器注解 * <p>Can be used natively, declaring several nested {@link PropertySource} annotations. * Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>, * where {@link PropertySource} can simply be declared several times on the same * {@linkplain ElementType#TYPE type}, implicitly generating this container annotation. * * @author Phillip Webb * @since 4.0 * @see PropertySource */ @Target({ElementType.TYPE})//只能标注在类上 @Retention(RetentionPolicy.RUNTIME) @Documented public @interface PropertySources { PropertySource[] value(); }
示例一:@PropertySource + @Value
@PropertySource(value = {"classpath:/user1.properties"}) @Component public class TestPropertySource { @Value("${user1.name}") private String name; @Value("${user1.age}") private int age; public User getUser(){ User user=new User(); user.setName(name); user.setAge(age); return user; } }
示例二:@PropertySource 和 @ConfigurationProperties
@Component @PropertySource(value = {"classpath:/user1.properties"}) @ConfigurationProperties(prefix = "user1") public class User1Properties { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User1Properties{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试
@Autowired private TestPropertySource testPropertySource; @Test public void test2(){ System.out.println(testPropertySource.getUser()); } @Resource private User1Properties user1Properties; @Test public void test3(){ System.out.println(user1Properties); }