提交 c4e9ce8d 编写于 作者: J Juergen Hoeller

Clarified repeatable PropertySource annotation vs use as meta-annotation

Issue: SPR-16592
上级 3988dd9e
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -298,18 +298,23 @@ public class AnnotationConfigUtils { ...@@ -298,18 +298,23 @@ public class AnnotationConfigUtils {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata, static Set<AnnotationAttributes> attributesForRepeatable(
String containerClassName, String annotationClassName) { AnnotationMetadata metadata, String containerClassName, String annotationClassName) {
Set<AnnotationAttributes> result = new LinkedHashSet<>(); Set<AnnotationAttributes> result = new LinkedHashSet<>();
// Direct annotation present?
addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false)); addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
// Container annotation present?
Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false); Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
if (container != null && container.containsKey("value")) { if (container != null && container.containsKey("value")) {
for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) { for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
addAttributesIfNotNull(result, containedAttributes); addAttributesIfNotNull(result, containedAttributes);
} }
} }
// Return merged result
return Collections.unmodifiableSet(result); return Collections.unmodifiableSet(result);
} }
......
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -42,6 +42,7 @@ import org.springframework.core.io.support.PropertySourceFactory; ...@@ -42,6 +42,7 @@ import org.springframework.core.io.support.PropertySourceFactory;
* &#064;Configuration * &#064;Configuration
* &#064;PropertySource("classpath:/com/myco/app.properties") * &#064;PropertySource("classpath:/com/myco/app.properties")
* public class AppConfig { * public class AppConfig {
*
* &#064;Autowired * &#064;Autowired
* Environment env; * Environment env;
* *
...@@ -53,8 +54,8 @@ import org.springframework.core.io.support.PropertySourceFactory; ...@@ -53,8 +54,8 @@ import org.springframework.core.io.support.PropertySourceFactory;
* } * }
* }</pre> * }</pre>
* *
* Notice that the {@code Environment} object is @{@link * Notice that the {@code Environment} object is
* org.springframework.beans.factory.annotation.Autowired Autowired} into the * {@link org.springframework.beans.factory.annotation.Autowired @Autowired} into the
* configuration class and then used when populating the {@code TestBean} object. Given * configuration class and then used when populating the {@code TestBean} object. Given
* the configuration above, a call to {@code testBean.getName()} will return "myTestBean". * the configuration above, a call to {@code testBean.getName()} will return "myTestBean".
* *
...@@ -79,6 +80,7 @@ import org.springframework.core.io.support.PropertySourceFactory; ...@@ -79,6 +80,7 @@ import org.springframework.core.io.support.PropertySourceFactory;
* &#064;Configuration * &#064;Configuration
* &#064;PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") * &#064;PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
* public class AppConfig { * public class AppConfig {
*
* &#064;Autowired * &#064;Autowired
* Environment env; * Environment env;
* *
...@@ -118,9 +120,9 @@ import org.springframework.core.io.support.PropertySourceFactory; ...@@ -118,9 +120,9 @@ import org.springframework.core.io.support.PropertySourceFactory;
* *
* The override ordering depends on the order in which these classes are registered * The override ordering depends on the order in which these classes are registered
* with the application context. * with the application context.
*
* <pre class="code"> * <pre class="code">
* AnnotationConfigApplicationContext ctx = * AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
* new AnnotationConfigApplicationContext();
* ctx.register(ConfigA.class); * ctx.register(ConfigA.class);
* ctx.register(ConfigB.class); * ctx.register(ConfigB.class);
* ctx.refresh(); * ctx.refresh();
...@@ -139,6 +141,12 @@ import org.springframework.core.io.support.PropertySourceFactory; ...@@ -139,6 +141,12 @@ import org.springframework.core.io.support.PropertySourceFactory;
* and {@link org.springframework.core.env.MutablePropertySources MutablePropertySources} * and {@link org.springframework.core.env.MutablePropertySources MutablePropertySources}
* javadocs for details. * 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 Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Phillip Webb * @author Phillip Webb
......
...@@ -8011,6 +8011,15 @@ be resolved to the corresponding value. If not, then "default/path" will be used ...@@ -8011,6 +8011,15 @@ be resolved to the corresponding value. If not, then "default/path" will be used
as a default. If no default is specified and a property cannot be resolved, an as a default. If no default is specified and a property cannot be resolved, an
`IllegalArgumentException` will be thrown. `IllegalArgumentException` will be thrown.
[NOTE]
====
The `@PropertySource` 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 within the
same custom annotation. Mixing of direct annotations and meta-annotations is not
recommended since direct annotations will effectively override meta-annotations.
====
=== Placeholder resolution in statements === Placeholder resolution in statements
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册