From 9baf23ccd5dd44c339538a5dc900c1d418542de5 Mon Sep 17 00:00:00 2001 From: Laurent Martelli Date: Tue, 4 Jul 2023 11:47:06 +0100 Subject: [PATCH 1/2] Test that ImportsContextCustomizer can support @AliasFor Add test to ensure that `ImportsContextCustomizer` can support `@AliasFor` annotations. See gh-34917 --- .../ImportsContextCustomizerTests.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java index f047bf98406..fb475ad81a5 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/ImportsContextCustomizerTests.java @@ -33,6 +33,7 @@ import org.springframework.boot.context.annotation.DeterminableImports; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.annotation.AliasFor; import org.springframework.core.type.AnnotationMetadata; import static org.assertj.core.api.Assertions.assertThat; @@ -41,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link ImportsContextCustomizer}. * * @author Andy Wilkinson + * @author Laurent Martelli */ class ImportsContextCustomizerTests { @@ -80,6 +82,30 @@ class ImportsContextCustomizerTests { .isEqualTo(new ImportsContextCustomizer(SecondJUnitAnnotatedTestClass.class)); } + @Test + void customizersForClassesWithDifferentImportsAreNotEqual() { + assertThat(new ImportsContextCustomizer(FirstAnnotatedTestClass.class)) + .isNotEqualTo(new ImportsContextCustomizer(SecondAnnotatedTestClass.class)); + } + + @Test + void customizersForClassesWithDifferentMetaImportsAreNotEqual() { + assertThat(new ImportsContextCustomizer(FirstMetaAnnotatedTestClass.class)) + .isNotEqualTo(new ImportsContextCustomizer(SecondMetaAnnotatedTestClass.class)); + } + + @Test + void customizersForClassesWithDifferentAliasedImportsAreNotEqual() { + assertThat(new ImportsContextCustomizer(FirstAliasAnnotatedTestClass.class)) + .isNotEqualTo(new ImportsContextCustomizer(SecondAliasAnnotatedTestClass.class)); + } + + @Test + void importsCanBeScatteredOnMultipleAnnotations() { + assertThat(new ImportsContextCustomizer(SingleImportAnnotationTestClass.class)) + .isEqualTo(new ImportsContextCustomizer(MultipleImportAnnotationTestClass.class)); + } + @Import(TestImportSelector.class) @Indicator1 static class FirstImportSelectorAnnotatedClass { @@ -152,6 +178,17 @@ class ImportsContextCustomizerTests { } + @Import({ FirstImportedClass.class, SecondImportedClass.class }) + static class SingleImportAnnotationTestClass { + + } + + @FirstMetaImport + @Import(SecondImportedClass.class) + static class MultipleImportAnnotationTestClass { + + } + @Retention(RetentionPolicy.RUNTIME) @interface Indicator1 { @@ -162,6 +199,65 @@ class ImportsContextCustomizerTests { } + @Retention(RetentionPolicy.RUNTIME) + @Import(AliasFor.class) + public @interface AliasedImport { + + @AliasFor(annotation = Import.class) + Class[] value(); + + } + + @Retention(RetentionPolicy.RUNTIME) + @Import(FirstImportedClass.class) + public @interface FirstMetaImport { + + } + + @Retention(RetentionPolicy.RUNTIME) + @Import(SecondImportedClass.class) + public @interface SecondMetaImport { + + } + + static class FirstImportedClass { + + } + + static class SecondImportedClass { + + } + + @AliasedImport(FirstImportedClass.class) + static class FirstAliasAnnotatedTestClass { + + } + + @AliasedImport(SecondImportedClass.class) + static class SecondAliasAnnotatedTestClass { + + } + + @FirstMetaImport + static class FirstMetaAnnotatedTestClass { + + } + + @SecondMetaImport + static class SecondMetaAnnotatedTestClass { + + } + + @Import(FirstImportedClass.class) + static class FirstAnnotatedTestClass { + + } + + @Import(SecondImportedClass.class) + static class SecondAnnotatedTestClass { + + } + static class TestImportSelector implements ImportSelector { @Override From 5d0640a35636368d149ea35b3e3c7017f1ddab5d Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 4 Jul 2023 11:57:52 +0100 Subject: [PATCH 2/2] Use MergedAnnotations for `@AliasFor` support Update `ImportsContextCustomizer` to use `MergedAnnotations` so that `@AliasFor` can be supported. See gh-34917 --- .../boot/test/context/ImportsContextCustomizer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java index e068632bd2a..447d7849aac 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ImportsContextCustomizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2023 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. @@ -43,6 +43,9 @@ import org.springframework.context.annotation.ImportSelector; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; import org.springframework.core.annotation.Order; import org.springframework.core.style.ToStringCreator; import org.springframework.core.type.AnnotationMetadata; @@ -251,7 +254,9 @@ class ImportsContextCustomizer implements ContextCustomizer { private void collectElementAnnotations(AnnotatedElement element, Set annotations, Set> seen) { - for (Annotation annotation : element.getDeclaredAnnotations()) { + for (MergedAnnotation mergedAnnotation : MergedAnnotations.from(element, + SearchStrategy.DIRECT)) { + Annotation annotation = mergedAnnotation.synthesize(); if (!isIgnoredAnnotation(annotation)) { annotations.add(annotation); collectClassAnnotations(annotation.annotationType(), annotations, seen);