From 73b01cff4ff2f96bedf4c9858d93591a0f22d4b3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 26 May 2016 12:32:02 +0100 Subject: [PATCH] Use spring.factories to declare each test slice's auto-config imports Closes gh-6001 --- .../ImportAutoConfiguration.java | 9 ++-- ...ImportAutoConfigurationImportSelector.java | 13 +++-- .../core/AutoConfigureCache.java | 3 +- .../autoconfigure/json/AutoConfigureJson.java | 4 +- .../orm/jpa/AutoConfigureDataJpa.java | 13 +---- .../orm/jpa/AutoConfigureTestDatabase.java | 2 +- .../jpa/AutoConfigureTestEntityManager.java | 2 +- .../restdocs/AutoConfigureRestDocs.java | 2 +- .../web/servlet/AutoConfigureMockMvc.java | 4 +- .../web/servlet/AutoConfigureWebMvc.java | 15 +----- .../main/resources/META-INF/spring.factories | 50 +++++++++++++++++++ 11 files changed, 74 insertions(+), 43 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfiguration.java index ef10838702..14adcc8aed 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfiguration.java @@ -26,7 +26,7 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; /** - * Import and apply the selected auto-configuration classes. Applies the same ordering + * Import and apply the specified auto-configuration classes. Applies the same ordering * rules as {@code @EnableAutoConfiguration} but restricts the auto-configuration classes * to the specified set, rather than consulting {@code spring.factories}. *

@@ -35,6 +35,7 @@ import org.springframework.context.annotation.Import; * and especially when writing tests. * * @author Phillip Webb + * @author Andy Wilkinson * @since 1.3.0 */ @Target(ElementType.TYPE) @@ -46,9 +47,11 @@ import org.springframework.context.annotation.Import; public @interface ImportAutoConfiguration { /** - * The auto-configuration classes that should be imported. + * The auto-configuration classes that should be imported. When empty, the classes are + * specified using an entry in {@code META-INF/spring.factories} where the key is the + * fully-qualified name of the annotated class. * @return the classes to import */ - Class[] value(); + Class[] value() default {}; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java index 4819b862bf..451a66d7f1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java @@ -27,6 +27,7 @@ import java.util.Set; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; @@ -77,19 +78,25 @@ class ImportAutoConfigurationImportSelector if (source != null && seen.add(source)) { for (Annotation annotation : source.getDeclaredAnnotations()) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - collectCandidateConfigurations(annotation, candidates, seen); + collectCandidateConfigurations(source, annotation, candidates, seen); } } collectCandidateConfigurations(source.getSuperclass(), candidates, seen); } } - private void collectCandidateConfigurations(Annotation annotation, + private void collectCandidateConfigurations(Class source, Annotation annotation, Set candidates, Set> seen) { if (ANNOTATION_NAMES.contains(annotation.annotationType().getName())) { String[] value = (String[]) AnnotationUtils .getAnnotationAttributes(annotation, true).get("value"); - candidates.addAll(Arrays.asList(value)); + if (value.length > 0) { + candidates.addAll(Arrays.asList(value)); + } + else { + candidates.addAll(SpringFactoriesLoader.loadFactoryNames(source, + getClass().getClassLoader())); + } } collectCandidateConfigurations(annotation.annotationType(), candidates, seen); } diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/core/AutoConfigureCache.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/core/AutoConfigureCache.java index d42d3d34d3..23e04fa5ae 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/core/AutoConfigureCache.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/core/AutoConfigureCache.java @@ -23,7 +23,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; import org.springframework.boot.autoconfigure.cache.CacheType; import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; import org.springframework.cache.support.NoOpCacheManager; @@ -39,7 +38,7 @@ import org.springframework.cache.support.NoOpCacheManager; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@ImportAutoConfiguration(CacheAutoConfiguration.class) +@ImportAutoConfiguration public @interface AutoConfigureCache { @PropertyMapping("spring.cache.type") diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/AutoConfigureJson.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/AutoConfigureJson.java index 2586a37aeb..555d445d2c 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/AutoConfigureJson.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/json/AutoConfigureJson.java @@ -23,8 +23,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; /** * {@link ImportAutoConfiguration Auto-configuration imports} for typical JSON tests. Most @@ -38,7 +36,7 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@ImportAutoConfiguration({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class }) +@ImportAutoConfiguration public @interface AutoConfigureJson { } diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureDataJpa.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureDataJpa.java index b1648879bf..febc304189 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureDataJpa.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureDataJpa.java @@ -23,13 +23,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration; -import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; -import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; -import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; /** * {@link ImportAutoConfiguration Auto-configuration imports} for typical Data JPA tests. @@ -44,11 +37,7 @@ import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfigu @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@ImportAutoConfiguration({ HibernateJpaAutoConfiguration.class, - JpaRepositoriesAutoConfiguration.class, TransactionAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - DataSourceAutoConfiguration.class, FlywayAutoConfiguration.class, - LiquibaseAutoConfiguration.class }) +@ImportAutoConfiguration public @interface AutoConfigureDataJpa { } diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestDatabase.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestDatabase.java index 837ba75ac4..ec728cdfaa 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestDatabase.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestDatabase.java @@ -38,7 +38,7 @@ import org.springframework.boot.test.autoconfigure.properties.PropertyMapping; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ImportAutoConfiguration(TestDatabaseAutoConfiguration.class) +@ImportAutoConfiguration @PropertyMapping("spring.test.database") public @interface AutoConfigureTestDatabase { diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestEntityManager.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestEntityManager.java index d307aec3c3..979766700d 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestEntityManager.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/orm/jpa/AutoConfigureTestEntityManager.java @@ -34,7 +34,7 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ImportAutoConfiguration(TestEntityManagerAutoConfiguration.class) +@ImportAutoConfiguration public @interface AutoConfigureTestEntityManager { } diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java index b2cbbb859b..b7f8dcfa32 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/restdocs/AutoConfigureRestDocs.java @@ -40,7 +40,7 @@ import org.springframework.context.annotation.Import; @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@ImportAutoConfiguration(RestDocsAutoConfiguration.class) +@ImportAutoConfiguration @Import(RestDocumentationContextProviderRegistrar.class) @PropertyMapping("spring.test.restdocs") public @interface AutoConfigureRestDocs { diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.java index f5f25385e1..69a4211df5 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.java @@ -42,9 +42,7 @@ import org.springframework.test.web.servlet.MvcResult; @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) -@ImportAutoConfiguration({ MockMvcAutoConfiguration.class, - MockMvcWebClientAutoConfiguration.class, MockMvcWebDriverAutoConfiguration.class, - MockMvcSecurityAutoConfiguration.class }) +@ImportAutoConfiguration @PropertyMapping("spring.test.mockmvc") public @interface AutoConfigureMockMvc { diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureWebMvc.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureWebMvc.java index 4d398e2fbb..79cab3dcc9 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureWebMvc.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureWebMvc.java @@ -23,15 +23,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; -import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration; -import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; -import org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; -import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration; -import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; -import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration; -import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; /** * {@link ImportAutoConfiguration Auto-configuration imports} for typical Spring MVC @@ -46,11 +37,7 @@ import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@ImportAutoConfiguration({ WebMvcAutoConfiguration.class, GsonAutoConfiguration.class, - JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, - FreeMarkerAutoConfiguration.class, GroovyTemplateAutoConfiguration.class, - MustacheAutoConfiguration.class, ThymeleafAutoConfiguration.class, - HypermediaAutoConfiguration.class }) +@ImportAutoConfiguration public @interface AutoConfigureWebMvc { } diff --git a/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories index 03cd4eaee3..8a10a5fe07 100644 --- a/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,3 +1,53 @@ +# AutoConfigureCache auto-configuration imports +org.springframework.boot.test.autoconfigure.core.AutoConfigureCache=\ +org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration + +# AutoConfigureDataJpa auto-configuration imports +org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa=\ +org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ +org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ +org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ +org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ +org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ +org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ +org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration + +# AutoConfigureJson auto-configuration imports +org.springframework.boot.test.autoconfigure.json.AutoConfigureJson=\ +org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ +org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration + +# AutoConfigureMockMvc auto-configuration imports +org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\ +org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,\ +org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration,\ +org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration,\ +org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration + +# AutoConfigureRestDocs auto-configuration imports +org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs=\ +org.springframework.boot.test.autoconfigure.restdocs.RestDocsAutoConfiguration + +# AutoConfigureTestDatabase auto-configuration imports +org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestDatabase=\ +org.springframework.boot.test.autoconfigure.orm.jpa.TestDataBaseAutoConfiguration + +# AutoConfigureTestEntityManager auto-configuration imports +org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestEntityManager=\ +org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration + +# AutoConfigureWebMvc auto-configuration imports +org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc=\ +org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ +org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ +org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ +org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ +org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ +org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ +org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ +org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration + # Spring Test ContextCustomizerFactories org.springframework.test.context.ContextCustomizerFactory=\ org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory,\