From 5f49d4a8d70cd126bdce8eef42026053c301bd84 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 15 Sep 2020 10:51:30 -0700 Subject: [PATCH] Rename @ConfigurationPropertiesImport Rename `@ConfigurationPropertiesImport` to `@ImportAsConfigurationPropertiesBean` and also refine the registrar so that it can be used with type directly annotated with `@ConfigurationProperties`. Closes gh-23172 --- .../docs/asciidoc/spring-boot-features.adoc | 10 +-- ...figurationMetadataAnnotationProcessor.java | 66 +++++++++++-------- .../MetadataGenerationEnvironment.java | 26 ++++---- .../PropertyDescriptorResolver.java | 2 +- .../ImportBeanTests.java | 17 +++-- .../MetadataGenerationEnvironmentFactory.java | 4 +- ...figurationMetadataAnnotationProcessor.java | 12 ++-- ... ImportAsConfigurationPropertiesBean.java} | 8 +-- ...ImportAsConfigurationPropertiesBeans.java} | 6 +- .../importbean/ImportAnnotatedJavaBean.java | 29 ++++++++ ...rtJavaBeanConfigurationPropertiesBean.java | 4 +- ...ltipleTypeConfigurationPropertiesBean.java | 5 +- ...rtRepeatedConfigurationPropertiesBean.java | 6 +- ...alueObjectConfigurationPropertiesBean.java | 4 +- .../importbean/ImportedAnnotatedJavaBean.java | 39 +++++++++++ .../ConfigurationPropertiesBeanRegistrar.java | 14 ++-- .../ConfigurationPropertiesScanRegistrar.java | 2 +- .../EnableConfigurationProperties.java | 2 +- ...nableConfigurationPropertiesRegistrar.java | 4 +- ... ImportAsConfigurationPropertiesBean.java} | 26 ++++++-- ...ConfigurationPropertiesBeanRegistrar.java} | 29 +++++--- ...ImportAsConfigurationPropertiesBeans.java} | 15 +++-- ...igurationPropertiesBeanRegistrarTests.java | 10 +-- ...rtAsConfigurationPropertiesBeanTests.java} | 44 +++++++++---- ...nfigurationPropertiesBeanRegistrarTests.kt | 6 +- 25 files changed, 260 insertions(+), 130 deletions(-) rename spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/{ConfigurationPropertiesImport.java => ImportAsConfigurationPropertiesBean.java} (84%) rename spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/{ConfigurationPropertiesImports.java => ImportAsConfigurationPropertiesBeans.java} (84%) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportAnnotatedJavaBean.java create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportedAnnotatedJavaBean.java rename spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/{ConfigurationPropertiesImport.java => ImportAsConfigurationPropertiesBean.java} (78%) rename spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/{ConfigurationPropertiesImportRegistrar.java => ImportAsConfigurationPropertiesBeanRegistrar.java} (60%) rename spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/{ConfigurationPropertiesImports.java => ImportAsConfigurationPropertiesBeans.java} (71%) rename spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/{ConfigurationPropertiesImportTests.java => ImportAsConfigurationPropertiesBeanTests.java} (72%) diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc index d569cb9d8ca..5fe73f9cc8d 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc @@ -1227,7 +1227,7 @@ Spring Boot provides infrastructure to bind `@ConfigurationProperties` types and You can either enable configuration properties on a class-by-class basis or enable configuration property scanning that works in a similar manner to component scanning. Sometimes, classes annotated with `@ConfigurationProperties` might not be suitable for scanning, for example, if you're developing your own auto-configuration or you want to enable them conditionally. -In these cases, specify the list of types to process using the `@EnableConfigurationProperties` or `@ConfigurationPropertiesImport` annotations. +In these cases, specify the list of types to process using the `@EnableConfigurationProperties` or `@ImportAsConfigurationPropertiesBean` annotations. This can be done on any `@Configuration` class, as shown in the following example: [source,java,indent=0] @@ -1253,7 +1253,7 @@ If you want to define specific packages to scan, you can do so as shown in the f [NOTE] ==== -When the `@ConfigurationProperties` bean is registered using configuration property scanning or via `@EnableConfigurationProperties` or `@ConfigurationPropertiesImport`, the bean has a conventional name: `-`, where `` is the environment key prefix specified in the `@ConfigurationProperties` annotation and `` is the fully qualified name of the bean. +When the `@ConfigurationProperties` bean is registered using configuration property scanning or via `@EnableConfigurationProperties` or `@ImportAsConfigurationPropertiesBean`, the bean has a conventional name: `-`, where `` is the environment key prefix specified in the `@ConfigurationProperties` annotation and `` is the fully qualified name of the bean. If the annotation does not provide any prefix, only the fully qualified name of the bean is used. The bean name in the example above is `acme-com.example.AcmeProperties`. @@ -1333,18 +1333,18 @@ To configure a bean from the `Environment` properties, add `@ConfigurationProper Any JavaBean property defined with the `another` prefix is mapped onto that `ExampleItem` bean in manner similar to the preceding `AcmeProperties` example. If you want to use constructor binding with a third-party class, you can't use a `@Bean` method since Spring will need to create the object instance. -For those situations, you can use an `@ConfigurationPropertiesImport` annotation on your `@Configuration` or `@SpringBootApplication` class. +For those situations, you can use an `@ImportAsConfigurationPropertiesBean` annotation on your `@Configuration` or `@SpringBootApplication` class. [source,java,indent=0] ---- @SpringBootApplication - @ConfigurationPropertiesImport(type = ExampleItem.class, prefix = "another") + @ImportAsConfigurationPropertiesBean(type = ExampleItem.class, prefix = "another") public class MyApp { ... } ---- -TIP: `@ConfigurationPropertiesImport` also works for JavaBean bindings as long as the type has a single no-arg constructor +TIP: `@ImportAsConfigurationPropertiesBean` also works for JavaBean bindings as long as the type has a single no-arg constructor diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index 696af70b3f7..ca6e9dff375 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -80,9 +80,9 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor static final String NAME_ANNOTATION = "org.springframework.boot.context.properties.bind.Name"; - static final String CONFIGURATION_PROPERTIES_IMPORT_ANNOATION = "org.springframework.boot.context.properties.ConfigurationPropertiesImport"; + static final String IMPORT_AS_CONFIGURATION_PROPERTIES_BEAN_ANNOATION = "org.springframework.boot.context.properties.ImportAsConfigurationPropertiesBean"; - static final String CONFIGURATION_PROPERTIES_IMPORTS_ANNOATION = "org.springframework.boot.context.properties.ConfigurationPropertiesImports"; + static final String IMPORT_AS_CONFIGURATION_PROPERTIES_BEANS_ANNOATION = "org.springframework.boot.context.properties.ImportAsConfigurationPropertiesBeans"; private static final Set SUPPORTED_OPTIONS = Collections .unmodifiableSet(Collections.singleton(ADDITIONAL_METADATA_LOCATIONS_OPTION)); @@ -125,12 +125,12 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor return NAME_ANNOTATION; } - protected String configurationPropertiesImportAnnotation() { - return CONFIGURATION_PROPERTIES_IMPORT_ANNOATION; + protected String importAsConfigurationPropertiesBeanAnnotation() { + return IMPORT_AS_CONFIGURATION_PROPERTIES_BEAN_ANNOATION; } - protected String configurationPropertiesImportsAnnotation() { - return CONFIGURATION_PROPERTIES_IMPORTS_ANNOATION; + protected String importAsConfigurationPropertiesBeansAnnotation() { + return IMPORT_AS_CONFIGURATION_PROPERTIES_BEANS_ANNOATION; } @Override @@ -151,8 +151,8 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor this.metadataEnv = new MetadataGenerationEnvironment(env, configurationPropertiesAnnotation(), nestedConfigurationPropertyAnnotation(), deprecatedConfigurationPropertyAnnotation(), constructorBindingAnnotation(), defaultValueAnnotation(), endpointAnnotation(), - readOperationAnnotation(), nameAnnotation(), configurationPropertiesImportAnnotation(), - configurationPropertiesImportsAnnotation()); + readOperationAnnotation(), nameAnnotation(), importAsConfigurationPropertiesBeanAnnotation(), + importAsConfigurationPropertiesBeansAnnotation()); } @Override @@ -160,7 +160,7 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor this.metadataCollector.processing(roundEnv); processConfigurationProperties(roundEnv); processEndpoint(roundEnv); - processConfigurationPropertiesImport(roundEnv); + processImportAsConfigurationProperties(roundEnv); if (roundEnv.processingOver()) { try { writeMetaData(); @@ -188,22 +188,22 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } } - private void processConfigurationPropertiesImport(RoundEnvironment roundEnv) { - TypeElement configurationPropertiesImportType = this.metadataEnv - .getConfigurationPropertiesImportAnnotationElement(); - TypeElement configurationPropertiesImportsType = this.metadataEnv - .getConfigurationPropertiesImportsAnnotationElement(); - if (configurationPropertiesImportType == null && configurationPropertiesImportsType == null) { + private void processImportAsConfigurationProperties(RoundEnvironment roundEnv) { + TypeElement importAsConfigurationPropertiesBeanType = this.metadataEnv + .getImportAsConfigurationPropertiesBeansAnnotation(); + TypeElement importAsConfigurationPropertiesBeansType = this.metadataEnv + .getImportAsConfigurationPropertiesBeansAnnotationElement(); + if (importAsConfigurationPropertiesBeanType == null && importAsConfigurationPropertiesBeansType == null) { return; } Set elements = new LinkedHashSet<>(); - if (configurationPropertiesImportType != null) { - elements.addAll(roundEnv.getElementsAnnotatedWith(configurationPropertiesImportType)); + if (importAsConfigurationPropertiesBeanType != null) { + elements.addAll(roundEnv.getElementsAnnotatedWith(importAsConfigurationPropertiesBeanType)); } - if (configurationPropertiesImportsType != null) { - elements.addAll(roundEnv.getElementsAnnotatedWith(configurationPropertiesImportsType)); + if (importAsConfigurationPropertiesBeansType != null) { + elements.addAll(roundEnv.getElementsAnnotatedWith(importAsConfigurationPropertiesBeansType)); } - elements.forEach(this::processConfigurationPropertiesImport); + elements.forEach(this::processImportAsConfigurationPropertiesBean); } private Map> getElementsAnnotatedOrMetaAnnotatedWith(RoundEnvironment roundEnv, @@ -314,18 +314,28 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor } } - private void processConfigurationPropertiesImport(Element element) { - this.metadataEnv.getConfigurationPropertiesImportAnnotations(element) - .forEach(this::processConfigurationPropertiesImport); + private void processImportAsConfigurationPropertiesBean(Element element) { + this.metadataEnv.getImportAsConfigurationPropertiesBeanAnnotations(element) + .forEach(this::processImportAsConfigurationPropertiesBean); } @SuppressWarnings("unchecked") - private void processConfigurationPropertiesImport(AnnotationMirror annotation) { + private void processImportAsConfigurationPropertiesBean(AnnotationMirror annotation) { String prefix = getPrefix(annotation); - List types = (List) this.metadataEnv.getAnnotationElementValues(annotation).get("type"); - for (TypeMirror type : types) { - Element element = this.metadataEnv.getTypeUtils().asElement(type); - processAnnotatedTypeElement(prefix, (TypeElement) element, true, new Stack<>()); + processImportAsConfigurationPropertiesBeanTypes(prefix, + (List) this.metadataEnv.getAnnotationElementValues(annotation).get("type")); + processImportAsConfigurationPropertiesBeanTypes(prefix, + (List) this.metadataEnv.getAnnotationElementValues(annotation).get("value")); + } + + private void processImportAsConfigurationPropertiesBeanTypes(String prefix, List types) { + if (types != null) { + for (TypeMirror type : types) { + Element element = this.metadataEnv.getTypeUtils().asElement(type); + AnnotationMirror annotation = this.metadataEnv.getConfigurationPropertiesAnnotation(element); + prefix = (annotation != null) ? getPrefix(annotation) : prefix; + processAnnotatedTypeElement(prefix, (TypeElement) element, true, new Stack<>()); + } } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java index ea5f207d0e0..0e0682abfee 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironment.java @@ -97,15 +97,15 @@ class MetadataGenerationEnvironment { private final String nameAnnotation; - private final String configurationPropertiesImportAnnotation; + private final String importAsConfigurationPropertiesBeanAnnotation; - private final String configurationPropertiesImportsAnnotation; + private final String importAsConfigurationPropertiesBeansAnnotation; MetadataGenerationEnvironment(ProcessingEnvironment environment, String configurationPropertiesAnnotation, String nestedConfigurationPropertyAnnotation, String deprecatedConfigurationPropertyAnnotation, String constructorBindingAnnotation, String defaultValueAnnotation, String endpointAnnotation, - String readOperationAnnotation, String nameAnnotation, String configurationPropertiesImportAnnotation, - String configurationPropertiesImportsAnnotation) { + String readOperationAnnotation, String nameAnnotation, String importAsConfigurationPropertiesBeanAnnotation, + String importAsConfigurationPropertiesBeansAnnotation) { this.typeUtils = new TypeUtils(environment); this.elements = environment.getElementUtils(); this.messager = environment.getMessager(); @@ -118,8 +118,8 @@ class MetadataGenerationEnvironment { this.endpointAnnotation = endpointAnnotation; this.readOperationAnnotation = readOperationAnnotation; this.nameAnnotation = nameAnnotation; - this.configurationPropertiesImportAnnotation = configurationPropertiesImportAnnotation; - this.configurationPropertiesImportsAnnotation = configurationPropertiesImportsAnnotation; + this.importAsConfigurationPropertiesBeanAnnotation = importAsConfigurationPropertiesBeanAnnotation; + this.importAsConfigurationPropertiesBeansAnnotation = importAsConfigurationPropertiesBeansAnnotation; } private static FieldValuesParser resolveFieldValuesParser(ProcessingEnvironment env) { @@ -265,12 +265,12 @@ class MetadataGenerationEnvironment { return this.elements.getTypeElement(this.configurationPropertiesAnnotation); } - TypeElement getConfigurationPropertiesImportAnnotationElement() { - return this.elements.getTypeElement(this.configurationPropertiesImportAnnotation); + TypeElement getImportAsConfigurationPropertiesBeansAnnotation() { + return this.elements.getTypeElement(this.importAsConfigurationPropertiesBeanAnnotation); } - TypeElement getConfigurationPropertiesImportsAnnotationElement() { - return this.elements.getTypeElement(this.configurationPropertiesImportsAnnotation); + TypeElement getImportAsConfigurationPropertiesBeansAnnotationElement() { + return this.elements.getTypeElement(this.importAsConfigurationPropertiesBeansAnnotation); } AnnotationMirror getConfigurationPropertiesAnnotation(Element element) { @@ -297,13 +297,13 @@ class MetadataGenerationEnvironment { return getAnnotation(element, this.nameAnnotation); } - List getConfigurationPropertiesImportAnnotations(Element element) { + List getImportAsConfigurationPropertiesBeanAnnotations(Element element) { List annotations = new ArrayList<>(); - AnnotationMirror importBean = getAnnotation(element, this.configurationPropertiesImportAnnotation); + AnnotationMirror importBean = getAnnotation(element, this.importAsConfigurationPropertiesBeanAnnotation); if (importBean != null) { annotations.add(importBean); } - AnnotationMirror importBeans = getAnnotation(element, this.configurationPropertiesImportsAnnotation); + AnnotationMirror importBeans = getAnnotation(element, this.importAsConfigurationPropertiesBeansAnnotation); if (importBeans != null) { AnnotationValue value = importBeans.getElementValues().values().iterator().next(); for (Object contained : (List) value.getValue()) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptorResolver.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptorResolver.java index 2d4a8d6ab6f..48812c5cb1c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptorResolver.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/PropertyDescriptorResolver.java @@ -50,7 +50,7 @@ class PropertyDescriptorResolver { * factory method}, if any. * @param type the target type * @param fromImport it the type was imported via a - * {@code @ConfigurationPropertiesImport} + * {@code @ImportAsConfigurationPropertiesBean} * @param factoryMethod the method that triggered the metadata for that {@code type} * or {@code null} * @return the candidate properties for metadata generation diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ImportBeanTests.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ImportBeanTests.java index a7ac43f3ef7..fcdf385f932 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ImportBeanTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/ImportBeanTests.java @@ -20,20 +20,22 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; import org.springframework.boot.configurationprocessor.metadata.Metadata; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImport; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImports; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBeans; +import org.springframework.boot.configurationsample.importbean.ImportAnnotatedJavaBean; import org.springframework.boot.configurationsample.importbean.ImportJavaBeanConfigurationPropertiesBean; import org.springframework.boot.configurationsample.importbean.ImportMultipleTypeConfigurationPropertiesBean; import org.springframework.boot.configurationsample.importbean.ImportRepeatedConfigurationPropertiesBean; import org.springframework.boot.configurationsample.importbean.ImportValueObjectConfigurationPropertiesBean; +import org.springframework.boot.configurationsample.importbean.ImportedAnnotatedJavaBean; import org.springframework.boot.configurationsample.importbean.ImportedJavaBean; import org.springframework.boot.configurationsample.importbean.ImportedValueObject; import static org.assertj.core.api.Assertions.assertThat; /** - * Tests for {@link ConfigurationPropertiesImport} and - * {@link ConfigurationPropertiesImports}. + * Tests for {@link ImportAsConfigurationPropertiesBean} and + * {@link ImportAsConfigurationPropertiesBeans}. * * @author Phillip Webb */ @@ -69,4 +71,11 @@ public class ImportBeanTests extends AbstractMetadataGenerationTests { assertThat(metadata).has(Metadata.withProperty("jb.name", String.class).fromSource(ImportedJavaBean.class)); } + @Test + void importAnnotatedJavaBean() { + ConfigurationMetadata metadata = compile(ImportAnnotatedJavaBean.class); + assertThat(metadata) + .has(Metadata.withProperty("test.name", String.class).fromSource(ImportedAnnotatedJavaBean.class)); + } + } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironmentFactory.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironmentFactory.java index dba47d05283..50b740646d0 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironmentFactory.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/MetadataGenerationEnvironmentFactory.java @@ -40,8 +40,8 @@ class MetadataGenerationEnvironmentFactory implements Function[] type(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ConfigurationPropertiesImports.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ImportAsConfigurationPropertiesBeans.java similarity index 84% rename from spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ConfigurationPropertiesImports.java rename to spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ImportAsConfigurationPropertiesBeans.java index ec3651c5cf0..f279aa65b0a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ConfigurationPropertiesImports.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/ImportAsConfigurationPropertiesBeans.java @@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Alternative to Spring Boot's {@code ConfigurationPropertiesImports} for testing + * Alternative to Spring Boot's {@code ImportAsConfigurationPropertiesBeans} for testing * (removes the need for a dependency on the real annotation). * * @author Phillip Webb @@ -31,8 +31,8 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface ConfigurationPropertiesImports { +public @interface ImportAsConfigurationPropertiesBeans { - ConfigurationPropertiesImport[] value(); + ImportAsConfigurationPropertiesBean[] value(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportAnnotatedJavaBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportAnnotatedJavaBean.java new file mode 100644 index 00000000000..fdd9f69da0d --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportAnnotatedJavaBean.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2020 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.configurationsample.importbean; + +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; + +/** + * An import of a java bean. + * + * @author Phillip Webb + */ +@ImportAsConfigurationPropertiesBean(type = ImportedAnnotatedJavaBean.class) +public class ImportAnnotatedJavaBean { + +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportJavaBeanConfigurationPropertiesBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportJavaBeanConfigurationPropertiesBean.java index 14aae652cc0..a4e596abf35 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportJavaBeanConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportJavaBeanConfigurationPropertiesBean.java @@ -16,14 +16,14 @@ package org.springframework.boot.configurationsample.importbean; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImport; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; /** * An import of a java bean. * * @author Phillip Webb */ -@ConfigurationPropertiesImport(type = ImportedJavaBean.class, prefix = "importbean") +@ImportAsConfigurationPropertiesBean(type = ImportedJavaBean.class, prefix = "importbean") public class ImportJavaBeanConfigurationPropertiesBean { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportMultipleTypeConfigurationPropertiesBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportMultipleTypeConfigurationPropertiesBean.java index dd0e09cbefd..5e0bde77eaa 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportMultipleTypeConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportMultipleTypeConfigurationPropertiesBean.java @@ -16,14 +16,15 @@ package org.springframework.boot.configurationsample.importbean; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImport; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; /** * An import of a java bean and a value object. * * @author Phillip Webb */ -@ConfigurationPropertiesImport(type = { ImportedJavaBean.class, ImportedValueObject.class }, prefix = "importbean") +@ImportAsConfigurationPropertiesBean(type = { ImportedJavaBean.class, ImportedValueObject.class }, + prefix = "importbean") public class ImportMultipleTypeConfigurationPropertiesBean { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportRepeatedConfigurationPropertiesBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportRepeatedConfigurationPropertiesBean.java index 466bded40f8..1e225521911 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportRepeatedConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportRepeatedConfigurationPropertiesBean.java @@ -16,15 +16,15 @@ package org.springframework.boot.configurationsample.importbean; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImport; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; /** * An import of a java bean and a value object. * * @author Phillip Webb */ -@ConfigurationPropertiesImport(type = ImportedJavaBean.class, prefix = "jb") -@ConfigurationPropertiesImport(type = ImportedValueObject.class, prefix = "vo") +@ImportAsConfigurationPropertiesBean(type = ImportedJavaBean.class, prefix = "jb") +@ImportAsConfigurationPropertiesBean(type = ImportedValueObject.class, prefix = "vo") public class ImportRepeatedConfigurationPropertiesBean { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportValueObjectConfigurationPropertiesBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportValueObjectConfigurationPropertiesBean.java index 98653852bd1..66d58edf62a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportValueObjectConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportValueObjectConfigurationPropertiesBean.java @@ -16,14 +16,14 @@ package org.springframework.boot.configurationsample.importbean; -import org.springframework.boot.configurationsample.ConfigurationPropertiesImport; +import org.springframework.boot.configurationsample.ImportAsConfigurationPropertiesBean; /** * An import of a value object. * * @author Phillip Webb */ -@ConfigurationPropertiesImport(type = ImportedValueObject.class, prefix = "importbean") +@ImportAsConfigurationPropertiesBean(type = ImportedValueObject.class, prefix = "importbean") public class ImportValueObjectConfigurationPropertiesBean { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportedAnnotatedJavaBean.java b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportedAnnotatedJavaBean.java new file mode 100644 index 00000000000..f7dad4ded40 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/importbean/ImportedAnnotatedJavaBean.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2020 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.configurationsample.importbean; + +import org.springframework.boot.configurationsample.ConfigurationProperties; + +/** + * Java bean that can be imported. + * + * @author Phillip Webb + */ +@ConfigurationProperties(prefix = "test") +public class ImportedAnnotatedJavaBean { + + private String name; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrar.java index 2da022bffc9..b78672f5505 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrar.java @@ -46,17 +46,11 @@ final class ConfigurationPropertiesBeanRegistrar { this.beanFactory = (BeanFactory) this.registry; } - void register(Class type) { - MergedAnnotation annotation = MergedAnnotations - .from(type, SearchStrategy.TYPE_HIERARCHY).get(ConfigurationProperties.class); - register(type, annotation); - } - - void register(Class type, MergedAnnotation annotation) { - register(type, annotation, false); - } - void register(Class type, MergedAnnotation annotation, boolean deduceBindConstructor) { + MergedAnnotation typeAnnotation = MergedAnnotations + .from(type, SearchStrategy.TYPE_HIERARCHY).get(ConfigurationProperties.class); + annotation = (!typeAnnotation.isPresent()) ? annotation : typeAnnotation; + annotation = (annotation != null) ? annotation : MergedAnnotation.missing(); String name = getName(type, annotation); if (!containsBeanDefinition(name)) { registerBeanDefinition(name, type, annotation, deduceBindConstructor); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanRegistrar.java index 9ba5338b225..cdc94d1d16a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanRegistrar.java @@ -108,7 +108,7 @@ class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegist private void register(ConfigurationPropertiesBeanRegistrar registrar, Class type) { if (!isComponent(type)) { - registrar.register(type); + registrar.register(type, null, false); } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationProperties.java index 9bf352f23ef..1b2d51488ff 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationProperties.java @@ -51,7 +51,7 @@ public @interface EnableConfigurationProperties { * {@link ConfigurationProperties @ConfigurationProperties} annotated beans with * Spring. Standard Spring Beans will also be scanned regardless of this value. * @return {@code @ConfigurationProperties} annotated beans to register - * @see ConfigurationPropertiesImport + * @see ImportAsConfigurationPropertiesBean */ Class[] value() default {}; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.java index 6b990d583e7..e4f0da6e504 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.java @@ -37,7 +37,9 @@ class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegi public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { registerInfrastructureBeans(registry); ConfigurationPropertiesBeanRegistrar beanRegistrar = new ConfigurationPropertiesBeanRegistrar(registry); - getTypes(metadata).forEach(beanRegistrar::register); + for (Class type : getTypes(metadata)) { + beanRegistrar.register(type, null, false); + } } private Set> getTypes(AnnotationMetadata metadata) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImport.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBean.java similarity index 78% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImport.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBean.java index eae18055a6a..442b53d767c 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImport.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBean.java @@ -28,15 +28,19 @@ import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AliasFor; /** - * Indicates one or more {@link ConfigurationProperties @ConfigurationProperties} classes - * to import as Spring Beans. Typically used on {@link Configuration @Configuration} - * classes to expose third-party classes as configuration property beans. + * Imports classes as {@link ConfigurationProperties @ConfigurationProperties} beans. Can + * be used to import {@link ConfigurationProperties @ConfigurationProperties} annotated + * types or third-party classes as configuration property beans. *

* Classes imported via this annotation that have a default constructor will use * {@code setter} binding, those with a non-default constructor will use * {@link ConstructorBinding @ConstructorBinding}. If you are looking to inject beans into * a constructor, you should use a regular {@link Configuration @Configuration} class * {@code @Bean} method instead. + *

+ * The {@code @ConfigurationProperties} alias attributes defined on this class will only + * be used if the imported class is not itself annotated + * with{@code @ConfigurationProperties}. * * @author Phillip Webb * @since 2.4.0 @@ -46,15 +50,23 @@ import org.springframework.core.annotation.AliasFor; @Documented @EnableConfigurationProperties @ConfigurationProperties -@Repeatable(ConfigurationPropertiesImports.class) -@Import(ConfigurationPropertiesImportRegistrar.class) -public @interface ConfigurationPropertiesImport { +@Repeatable(ImportAsConfigurationPropertiesBeans.class) +@Import(ImportAsConfigurationPropertiesBeanRegistrar.class) +public @interface ImportAsConfigurationPropertiesBean { /** * One or more types that should be imported as a bean. * @return the types to import */ - Class[] type(); + @AliasFor("type") + Class[] value() default {}; + + /** + * One or more types that should be imported as a bean. + * @return the types to import + */ + @AliasFor("value") + Class[] type() default {}; /** * The prefix of the properties that are valid to bind to this object. A valid prefix diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportRegistrar.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanRegistrar.java similarity index 60% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportRegistrar.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanRegistrar.java index e3c2199ba2b..d2d60c4a2b0 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportRegistrar.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanRegistrar.java @@ -22,41 +22,50 @@ import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; /** * {@link ImportBeanDefinitionRegistrar} for - * {@link ConfigurationPropertiesImport @ConfigurationPropertiesImport}. + * {@link ImportAsConfigurationPropertiesBean @ImportAsConfigurationPropertiesBean}. * * @author Phillip Webb */ -class ConfigurationPropertiesImportRegistrar implements ImportBeanDefinitionRegistrar { +class ImportAsConfigurationPropertiesBeanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { - ConfigurationPropertiesBeanRegistrar registrar = new ConfigurationPropertiesBeanRegistrar(registry); - MergedAnnotations annotations = importingClassMetadata.getAnnotations(); - registerBeans(registrar, annotations.get(ConfigurationPropertiesImports.class)); - registerBean(registrar, annotations.get(ConfigurationPropertiesImport.class)); + try { + ConfigurationPropertiesBeanRegistrar registrar = new ConfigurationPropertiesBeanRegistrar(registry); + MergedAnnotations annotations = importingClassMetadata.getAnnotations(); + registerBeans(registrar, annotations.get(ImportAsConfigurationPropertiesBeans.class)); + registerBean(registrar, annotations.get(ImportAsConfigurationPropertiesBean.class)); + } + catch (RuntimeException ex) { + throw new IllegalStateException("Unable process @ImportAsConfigurationPropertiesBean annotations from " + + importingClassMetadata.getClassName(), ex); + } } private void registerBeans(ConfigurationPropertiesBeanRegistrar registrar, - MergedAnnotation annotation) { + MergedAnnotation annotation) { if (!annotation.isPresent()) { return; } - for (MergedAnnotation containedAnnotation : annotation - .getAnnotationArray(MergedAnnotation.VALUE, ConfigurationPropertiesImport.class)) { + for (MergedAnnotation containedAnnotation : annotation + .getAnnotationArray(MergedAnnotation.VALUE, ImportAsConfigurationPropertiesBean.class)) { registerBean(registrar, containedAnnotation); } } private void registerBean(ConfigurationPropertiesBeanRegistrar registrar, - MergedAnnotation annotation) { + MergedAnnotation annotation) { if (!annotation.isPresent()) { return; } Class[] types = annotation.getClassArray("type"); + Assert.state(!ObjectUtils.isEmpty(types), "@ImportAsConfigurationPropertiesBean must declare types to import"); MergedAnnotation configurationPropertiesAnnotation = MergedAnnotations .from(annotation.synthesize()).get(ConfigurationProperties.class); for (Class type : types) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImports.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeans.java similarity index 71% rename from spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImports.java rename to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeans.java index c1b45eec220..53a1aaf2c34 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesImports.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeans.java @@ -25,24 +25,27 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; /** - * Container annotation that aggregates several {@link ConfigurationPropertiesImport} + * Container annotation that aggregates several + * {@link ImportAsConfigurationPropertiesBean @ImportAsConfigurationPropertiesBean} * annotations. * * @author Phillip Webb * @since 2.4.0 - * @see ConfigurationPropertiesImport + * @see ImportAsConfigurationPropertiesBean */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @EnableConfigurationProperties -@Import(ConfigurationPropertiesImportRegistrar.class) -public @interface ConfigurationPropertiesImports { +@Import(ImportAsConfigurationPropertiesBeanRegistrar.class) +public @interface ImportAsConfigurationPropertiesBeans { /** - * The contained {@link ConfigurationPropertiesImport} annotations. + * The contained + * {@link ImportAsConfigurationPropertiesBean @ImportAsConfigurationPropertiesBean} + * annotations. * @return the contained annotations */ - ConfigurationPropertiesImport[] value(); + ImportAsConfigurationPropertiesBean[] value(); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrarTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrarTests.java index 0d8b3a3bf60..a5fd9989775 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrarTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrarTests.java @@ -43,7 +43,7 @@ class ConfigurationPropertiesBeanRegistrarTests { @Test void registerWhenNotAlreadyRegisteredAddBeanDefinition() { String beanName = "beancp-" + BeanConfigurationProperties.class.getName(); - this.registrar.register(BeanConfigurationProperties.class); + this.registrar.register(BeanConfigurationProperties.class, null, false); BeanDefinition definition = this.registry.getBeanDefinition(beanName); assertThat(definition).isNotNull(); assertThat(definition.getBeanClassName()).isEqualTo(BeanConfigurationProperties.class.getName()); @@ -53,7 +53,7 @@ class ConfigurationPropertiesBeanRegistrarTests { void registerWhenAlreadyContainsNameDoesNotReplace() { String beanName = "beancp-" + BeanConfigurationProperties.class.getName(); this.registry.registerBeanDefinition(beanName, new GenericBeanDefinition()); - this.registrar.register(BeanConfigurationProperties.class); + this.registrar.register(BeanConfigurationProperties.class, null, false); BeanDefinition definition = this.registry.getBeanDefinition(beanName); assertThat(definition).isNotNull(); assertThat(definition.getBeanClassName()).isNull(); @@ -62,14 +62,14 @@ class ConfigurationPropertiesBeanRegistrarTests { @Test void registerWhenNoAnnotationThrowsException() { assertThatIllegalStateException() - .isThrownBy(() -> this.registrar.register(NoAnnotationConfigurationProperties.class)) + .isThrownBy(() -> this.registrar.register(NoAnnotationConfigurationProperties.class, null, false)) .withMessageContaining("No ConfigurationProperties annotation found"); } @Test void registerWhenValueObjectRegistersValueObjectBeanDefinition() { String beanName = "valuecp-" + ValueObjectConfigurationProperties.class.getName(); - this.registrar.register(ValueObjectConfigurationProperties.class); + this.registrar.register(ValueObjectConfigurationProperties.class, null, false); BeanDefinition definition = this.registry.getBeanDefinition(beanName); assertThat(definition).isInstanceOf(ConfigurationPropertiesValueObjectBeanDefinition.class); } @@ -77,7 +77,7 @@ class ConfigurationPropertiesBeanRegistrarTests { @Test void registerWhenNotValueObjectRegistersConfigurationPropertiesBeanDefinition() { String beanName = MultiConstructorBeanConfigurationProperties.class.getName(); - this.registrar.register(MultiConstructorBeanConfigurationProperties.class); + this.registrar.register(MultiConstructorBeanConfigurationProperties.class, null, false); BeanDefinition definition = this.registry.getBeanDefinition(beanName); assertThat(definition).isExactlyInstanceOf(ConfigurationPropertiesBeanDefinition.class); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanTests.java similarity index 72% rename from spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportTests.java rename to spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanTests.java index fdaee1f4473..ca4c2dd0a43 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesImportTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ImportAsConfigurationPropertiesBeanTests.java @@ -26,11 +26,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** - * Tests for {@link ConfigurationPropertiesImport}. + * Tests for {@link ImportAsConfigurationPropertiesBean}. * * @author Phillip Webb */ -class ConfigurationPropertiesImportTests { +class ImportAsConfigurationPropertiesBeanTests { @Test void importJavaBean() { @@ -57,7 +57,8 @@ class ConfigurationPropertiesImportTests { try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "test.name=spring"); context.register(MultiConstructorValueObjectConfig.class); - assertThatIllegalStateException().isThrownBy(context::refresh).withMessageContaining("Unable to deduce"); + assertThatIllegalStateException().isThrownBy(context::refresh).havingCause() + .withMessageContaining("Unable to deduce"); } } @@ -80,13 +81,23 @@ class ConfigurationPropertiesImportTests { "vo.value=boot"); context.register(ImportRepeatedAnnotationsConfig.class); context.refresh(); - // assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring"); - // assertThat(context.getBean(ValueObject.class).getValue()).isEqualTo("boot"); + assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring"); + assertThat(context.getBean(ValueObject.class).getValue()).isEqualTo("boot"); + } + } + + @Test + void importAnnoatedBeanConfig() { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "onbean.name=spring"); + context.register(ImportAnnotatedClassConfig.class); + context.refresh(); + assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring"); } } @Configuration - @ConfigurationPropertiesImport(prefix = "test", type = JavaBean.class) + @ImportAsConfigurationPropertiesBean(prefix = "test", type = JavaBean.class) static class JavaBeanConfig { } @@ -106,7 +117,7 @@ class ConfigurationPropertiesImportTests { } @Configuration - @ConfigurationPropertiesImport(prefix = "test", type = ValueObject.class) + @ImportAsConfigurationPropertiesBean(prefix = "test", type = ValueObject.class) static class ValueObjectConfig { } @@ -126,7 +137,7 @@ class ConfigurationPropertiesImportTests { } @Configuration - @ConfigurationPropertiesImport(prefix = "test", type = MultiConstructorValueObject.class) + @ImportAsConfigurationPropertiesBean(prefix = "test", type = MultiConstructorValueObject.class) static class MultiConstructorValueObjectConfig { } @@ -145,16 +156,27 @@ class ConfigurationPropertiesImportTests { } @Configuration - @ConfigurationPropertiesImport(type = { ValueObject.class, JavaBean.class }, prefix = "test") + @ImportAsConfigurationPropertiesBean(type = { ValueObject.class, JavaBean.class }, prefix = "test") static class ImportMultipleTypesConfig { } @Configuration - @ConfigurationPropertiesImport(type = ValueObject.class, prefix = "vo") - @ConfigurationPropertiesImport(type = JavaBean.class, prefix = "jb") + @ImportAsConfigurationPropertiesBean(type = ValueObject.class, prefix = "vo") + @ImportAsConfigurationPropertiesBean(type = JavaBean.class, prefix = "jb") static class ImportRepeatedAnnotationsConfig { } + @Configuration + @ImportAsConfigurationPropertiesBean(AnnotatedJavaBean.class) + static class ImportAnnotatedClassConfig { + + } + + @ConfigurationProperties(prefix = "onbean") + static class AnnotatedJavaBean extends JavaBean { + + } + } diff --git a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesBeanRegistrarTests.kt b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesBeanRegistrarTests.kt index 709af3ed05d..38d40a9dd01 100644 --- a/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesBeanRegistrarTests.kt +++ b/spring-boot-project/spring-boot/src/test/kotlin/org/springframework/boot/context/properties/KotlinConfigurationPropertiesBeanRegistrarTests.kt @@ -20,7 +20,7 @@ class KotlinConfigurationPropertiesBeanRegistrarTests { @Test fun `type with default constructor should register generic bean definition`() { - this.registrar.register(FooProperties::class.java) + this.registrar.register(FooProperties::class.java, null, false) val beanDefinition = this.beanFactory.getBeanDefinition( "foo-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$FooProperties") assertThat(beanDefinition).isExactlyInstanceOf(ConfigurationPropertiesBeanDefinition::class.java) @@ -28,7 +28,7 @@ class KotlinConfigurationPropertiesBeanRegistrarTests { @Test fun `type with primary constructor and no autowired should register configuration properties bean definition`() { - this.registrar.register(BarProperties::class.java) + this.registrar.register(BarProperties::class.java, null, false) val beanDefinition = this.beanFactory.getBeanDefinition( "bar-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$BarProperties") assertThat(beanDefinition).isExactlyInstanceOf( @@ -37,7 +37,7 @@ class KotlinConfigurationPropertiesBeanRegistrarTests { @Test fun `type with no primary constructor should register generic bean definition`() { - this.registrar.register(BingProperties::class.java) + this.registrar.register(BingProperties::class.java, null, false) val beanDefinition = this.beanFactory.getBeanDefinition( "bing-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$BingProperties") assertThat(beanDefinition).isExactlyInstanceOf(ConfigurationPropertiesBeanDefinition::class.java)