From 6158634d67eb6fee43adfff61aca9c98d35c0308 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 14 Mar 2018 18:53:50 +0100 Subject: [PATCH] Clarified repeatable PropertySource annotation vs use as meta-annotation Issue: SPR-16592 (cherry picked from commit c4e9ce8) --- .../annotation/AnnotationConfigUtils.java | 11 ++++++++--- .../context/annotation/PropertySource.java | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java index 764073b8737..491ed14c97b 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -287,18 +287,23 @@ public class AnnotationConfigUtils { } @SuppressWarnings("unchecked") - static Set attributesForRepeatable(AnnotationMetadata metadata, - String containerClassName, String annotationClassName) { + static Set attributesForRepeatable( + AnnotationMetadata metadata, String containerClassName, String annotationClassName) { Set result = new LinkedHashSet(); + + // Direct annotation present? addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false)); + // Container annotation present? Map container = metadata.getAnnotationAttributes(containerClassName, false); if (container != null && container.containsKey("value")) { for (Map containedAttributes : (Map[]) container.get("value")) { addAttributesIfNotNull(result, containedAttributes); } } + + // Return merged result return Collections.unmodifiableSet(result); } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/PropertySource.java b/spring-context/src/main/java/org/springframework/context/annotation/PropertySource.java index e4237110655..51ca200ebe5 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/PropertySource.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/PropertySource.java @@ -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"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import org.springframework.core.io.support.PropertySourceFactory; * @Configuration * @PropertySource("classpath:/com/myco/app.properties") * public class AppConfig { + * * @Autowired * Environment env; * @@ -53,8 +54,8 @@ import org.springframework.core.io.support.PropertySourceFactory; * } * } * - * Notice that the {@code Environment} object is @{@link - * org.springframework.beans.factory.annotation.Autowired Autowired} into the + * 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". * @@ -79,6 +80,7 @@ import org.springframework.core.io.support.PropertySourceFactory; * @Configuration * @PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties") * public class AppConfig { + * * @Autowired * 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 * with the application context. + * *
- * AnnotationConfigApplicationContext ctx =
- *     new AnnotationConfigApplicationContext();
+ * AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  * ctx.register(ConfigA.class);
  * ctx.register(ConfigB.class);
  * ctx.refresh();
@@ -139,6 +141,12 @@ import org.springframework.core.io.support.PropertySourceFactory;
  * and {@link org.springframework.core.env.MutablePropertySources MutablePropertySources}
  * javadocs for details.
  *
+ * 

NOTE: This annotation is repeatable according to Java 8 conventions. + * 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