Clarified repeatable PropertySource annotation vs use as meta-annotation
Issue: SPR-16592
This commit is contained in:
parent
3988dd9ebb
commit
c4e9ce8d0e
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* 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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
* @Configuration
|
* @Configuration
|
||||||
* @PropertySource("classpath:/com/myco/app.properties")
|
* @PropertySource("classpath:/com/myco/app.properties")
|
||||||
* public class AppConfig {
|
* public class AppConfig {
|
||||||
|
*
|
||||||
* @Autowired
|
* @Autowired
|
||||||
* Environment env;
|
* Environment env;
|
||||||
*
|
*
|
||||||
|
@ -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;
|
||||||
* @Configuration
|
* @Configuration
|
||||||
* @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
|
* @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
|
||||||
* public class AppConfig {
|
* public class AppConfig {
|
||||||
|
*
|
||||||
* @Autowired
|
* @Autowired
|
||||||
* Environment env;
|
* Environment env;
|
||||||
*
|
*
|
||||||
|
@ -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;
|
||||||
* 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
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue