diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java index cc9e8ac7a23..86d6c7617e2 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java @@ -35,6 +35,7 @@ import org.springframework.util.StringUtils; * {@link PropertyMapping @PropertyMapping}. * * @author Phillip Webb + * @author Andy Wilkinson * @since 1.4.0 */ public class AnnotationsPropertySource extends EnumerablePropertySource> { @@ -60,14 +61,16 @@ public class AnnotationsPropertySource extends EnumerablePropertySource private void collectProperties(Class source, Map properties) { if (source != null) { - for (Annotation annotation : source.getDeclaredAnnotations()) { + for (Annotation annotation : AnnotationUtils.getAnnotations(source)) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - PropertyMapping typeMapping = AnnotationUtils.getAnnotation( - annotation.annotationType(), PropertyMapping.class); + annotation.annotationType().getAnnotation(PropertyMapping.class); + PropertyMapping typeMapping = annotation.annotationType() + .getAnnotation(PropertyMapping.class); for (Method attribute : annotation.annotationType() .getDeclaredMethods()) { collectProperties(annotation, attribute, typeMapping, properties); } + collectProperties(annotation.annotationType(), properties); } } collectProperties(source.getSuperclass(), properties); diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java index bec497f5c33..3d6cd38137b 100644 --- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java @@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link AnnotationsPropertySource}. * * @author Phillip Webb + * @author Andy Wilkinson */ public class AnnotationsPropertySourceTests { @@ -133,6 +134,26 @@ public class AnnotationsPropertySourceTests { assertThat(source.getPropertyNames()).contains("camel-case-to-kebab-case"); } + @Test + public void propertiesFromMetaAnnotationsAreMapped() throws Exception { + AnnotationsPropertySource source = new AnnotationsPropertySource( + PropertiesFromSingleMetaAnnotation.class); + assertThat(source.getPropertyNames()).containsExactly("value"); + assertThat(source.getProperty("value")).isEqualTo("foo"); + } + + @Test + public void propertiesFromMultipleMetaAnnotationsAreMappedUsingTheirOwnPropertyMapping() + throws Exception { + AnnotationsPropertySource source = new AnnotationsPropertySource( + PropertiesFromMultipleMetaAnnotations.class); + assertThat(source.getPropertyNames()).containsExactly("value", "test.value", + "test.example"); + assertThat(source.getProperty("value")).isEqualTo("alpha"); + assertThat(source.getProperty("test.value")).isEqualTo("bravo"); + assertThat(source.getProperty("test.example")).isEqualTo("charlie"); + } + static class NoAnnotation { } @@ -262,4 +283,28 @@ public class AnnotationsPropertySourceTests { } + @PropertiesFromSingleMetaAnnotationAnnotation + static class PropertiesFromSingleMetaAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + @TypeLevelAnnotation("foo") + static @interface PropertiesFromSingleMetaAnnotationAnnotation { + + } + + @PropertiesFromMultipleMetaAnnotationsAnnotation + static class PropertiesFromMultipleMetaAnnotations { + + } + + @Retention(RetentionPolicy.RUNTIME) + @TypeLevelAnnotation("alpha") + @TypeLevelWithPrefixAnnotation("bravo") + @TypeAndAttributeLevelWithPrefixAnnotation("charlie") + static @interface PropertiesFromMultipleMetaAnnotationsAnnotation { + + } + }