From df6feb3e2a796e09997cc6660a787b741d719c70 Mon Sep 17 00:00:00 2001 From: artsiom Date: Wed, 25 Jul 2018 23:39:18 +0300 Subject: [PATCH 1/2] Make SpringBootConfigurationFinder public and usable with other annotations See gh-13904 --- .../SpringBootConfigurationFinder.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java index 54f07aaa49..728669bc5f 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java @@ -16,6 +16,7 @@ package org.springframework.boot.test.context; +import java.lang.annotation.Annotation; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -29,21 +30,34 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Internal utility class to scan for a {@link SpringBootConfiguration} class. + * Utility class to scan for a {@link SpringBootConfiguration} or custom annotation. * * @author Phillip Webb + * @author Artsiom Yudovin + * @since 2.1.0 */ -final class SpringBootConfigurationFinder { +public final class SpringBootConfigurationFinder { private static final Map> cache = Collections .synchronizedMap(new Cache(40)); private final ClassPathScanningCandidateComponentProvider scanner; - SpringBootConfigurationFinder() { + /** + * Default constructor initializing finder to scan for a {@link SpringBootConfiguration} annotation. + */ + public SpringBootConfigurationFinder() { + this(SpringBootConfiguration.class); + } + + /** + * Customiable constructor allow to provide the custom annotation to scan for. + * @param annotationType Annotation to scan for. + */ + public SpringBootConfigurationFinder(Class annotationType) { this.scanner = new ClassPathScanningCandidateComponentProvider(false); this.scanner.addIncludeFilter( - new AnnotationTypeFilter(SpringBootConfiguration.class)); + new AnnotationTypeFilter(annotationType)); this.scanner.setResourcePattern("*.class"); } From f78017977796961adb9e0e1ebc9363c1f6dca7a0 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Thu, 26 Jul 2018 17:20:37 +0200 Subject: [PATCH 2/2] Polish contribution Closes gh-13904 --- ...nFinder.java => AnnotatedClassFinder.java} | 37 +++++++++++-------- .../SpringBootTestContextBootstrapper.java | 2 +- ...ts.java => AnnotatedClassFinderTests.java} | 8 ++-- .../test/context/example/ExampleConfig.java | 4 +- .../test/context/example/scan/Example.java | 4 +- .../example/scan/sub/SubExampleConfig.java | 6 +-- 6 files changed, 35 insertions(+), 26 deletions(-) rename spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/{SpringBootConfigurationFinder.java => AnnotatedClassFinder.java} (70%) rename spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/{SpringBootConfigurationFinderTests.java => AnnotatedClassFinderTests.java} (90%) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/AnnotatedClassFinder.java similarity index 70% rename from spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java rename to spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/AnnotatedClassFinder.java index 728669bc5f..d2510b9ef0 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/AnnotatedClassFinder.java @@ -23,20 +23,20 @@ import java.util.Map; import java.util.Set; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Utility class to scan for a {@link SpringBootConfiguration} or custom annotation. + * Utility class to find a class annotated with a particular annotation in a hierarchy. * * @author Phillip Webb * @author Artsiom Yudovin + * @author Stephane Nicoll * @since 2.1.0 */ -public final class SpringBootConfigurationFinder { +public final class AnnotatedClassFinder { private static final Map> cache = Collections .synchronizedMap(new Cache(40)); @@ -44,28 +44,35 @@ public final class SpringBootConfigurationFinder { private final ClassPathScanningCandidateComponentProvider scanner; /** - * Default constructor initializing finder to scan for a {@link SpringBootConfiguration} annotation. + * Create a new instance with the {@code annotationType} to find. + * @param annotationType the annotation to find */ - public SpringBootConfigurationFinder() { - this(SpringBootConfiguration.class); - } - - /** - * Customiable constructor allow to provide the custom annotation to scan for. - * @param annotationType Annotation to scan for. - */ - public SpringBootConfigurationFinder(Class annotationType) { + public AnnotatedClassFinder(Class annotationType) { + Assert.notNull(annotationType, "AnnotationType must not be null"); this.scanner = new ClassPathScanningCandidateComponentProvider(false); - this.scanner.addIncludeFilter( - new AnnotationTypeFilter(annotationType)); + this.scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType)); this.scanner.setResourcePattern("*.class"); } + /** + * Find the first {@link Class} that is annotated with the target annotation, starting + * from the package defined by the given {@code source} up to the root. + * @param source the source class to use to initiate the search + * @return the first {@link Class} annotated with the target annotation within the + * hierarchy defined by the given {@code source} or {@code null} if none is found. + */ public Class findFromClass(Class source) { Assert.notNull(source, "Source must not be null"); return findFromPackage(ClassUtils.getPackageName(source)); } + /** + * Find the first {@link Class} that is annotated with the target annotation, starting + * from the package defined by the given {@code source} up to the root. + * @param source the source package to use to initiate the search + * @return the first {@link Class} annotated with the target annotation within the + * hierarchy defined by the given {@code source} or {@code null} if none is found. + */ public Class findFromPackage(String source) { Assert.notNull(source, "Source must not be null"); Class configuration = cache.get(source); diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java index 3ee521bed7..f9f3c259cc 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java @@ -238,7 +238,7 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr if (containsNonTestComponent(classes) || mergedConfig.hasLocations()) { return classes; } - Class found = new SpringBootConfigurationFinder() + Class found = new AnnotatedClassFinder(SpringBootConfiguration.class) .findFromClass(mergedConfig.getTestClass()); Assert.state(found != null, "Unable to find a @SpringBootConfiguration, you need to use " diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AnnotatedClassFinderTests.java similarity index 90% rename from spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java rename to spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AnnotatedClassFinderTests.java index d1899fca71..67a088d803 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/AnnotatedClassFinderTests.java @@ -20,22 +20,24 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.example.ExampleConfig; import org.springframework.boot.test.context.example.scan.Example; import static org.assertj.core.api.Assertions.assertThat; /** - * Tests for {@link SpringBootConfigurationFinder}. + * Tests for {@link AnnotatedClassFinder}. * * @author Phillip Webb */ -public class SpringBootConfigurationFinderTests { +public class AnnotatedClassFinderTests { @Rule public ExpectedException thrown = ExpectedException.none(); - private SpringBootConfigurationFinder finder = new SpringBootConfigurationFinder(); + private AnnotatedClassFinder finder = new AnnotatedClassFinder( + SpringBootConfiguration.class); @Test public void findFromClassWhenSourceIsNullShouldThrowException() { diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java index c7aecf45ea..e9a8582d8f 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java @@ -17,10 +17,10 @@ package org.springframework.boot.test.context.example; import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; +import org.springframework.boot.test.context.AnnotatedClassFinderTests; /** - * Example config used in {@link SpringBootConfigurationFinderTests}. + * Example config used in {@link AnnotatedClassFinderTests}. * * @author Phillip Webb */ diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java index ab96ac6cd2..535f4d2fc7 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java @@ -16,10 +16,10 @@ package org.springframework.boot.test.context.example.scan; -import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; +import org.springframework.boot.test.context.AnnotatedClassFinderTests; /** - * Example class used in {@link SpringBootConfigurationFinderTests}. + * Example class used in {@link AnnotatedClassFinderTests}. * * @author Phillip Webb */ diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java index 21813a3300..7bf52b7459 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java @@ -17,11 +17,11 @@ package org.springframework.boot.test.context.example.scan.sub; import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; +import org.springframework.boot.test.context.AnnotatedClassFinderTests; /** - * Example config used in {@link SpringBootConfigurationFinderTests}. Should not be found - * since scanner should only search upwards. + * Example config used in {@link AnnotatedClassFinderTests}. Should not be found since + * scanner should only search upwards. * * @author Phillip Webb */