From 9fb65e57c0189913bd39f63005b839f6416000c0 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Mon, 22 Apr 2019 18:37:29 -0700 Subject: [PATCH] ConfigurationPropertiesScan should account for conditions Fixes gh-16612 --- .../ConfigurationPropertiesScanRegistrar.java | 23 ++++- .../ConfigurationPropertiesScanTests.java | 86 +++++++++++++++++++ .../scan/valid/a/AScanConfiguration.java | 29 +++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanTests.java 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 94c6fbe461..f17317e679 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 @@ -22,11 +22,15 @@ import java.util.Set; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.stereotype.Component; @@ -39,7 +43,12 @@ import org.springframework.util.StringUtils; * * @author Madhura Bhave */ -class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegistrar { +class ConfigurationPropertiesScanRegistrar + implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware { + + private Environment environment; + + private ResourceLoader resourceLoader; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, @@ -72,6 +81,8 @@ class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegist BeanDefinitionRegistry registry) { ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( false); + scanner.setEnvironment(this.environment); + scanner.setResourceLoader(this.resourceLoader); scanner.addIncludeFilter(new AnnotationTypeFilter(ConfigurationProperties.class)); for (String basePackage : packages) { if (StringUtils.hasText(basePackage)) { @@ -111,4 +122,14 @@ class ConfigurationPropertiesScanRegistrar implements ImportBeanDefinitionRegist } } + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanTests.java new file mode 100644 index 0000000000..96e996134d --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesScanTests.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2019 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.context.properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import org.springframework.boot.context.properties.scan.valid.a.AScanConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.DefaultResourceLoader; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willCallRealMethod; + +/** + * Integration tests for {@link ConfigurationPropertiesScan}. + * + * @author Madhura Bhave + */ +public class ConfigurationPropertiesScanTests { + + private AnnotationConfigApplicationContext context; + + @Before + public void setup() { + this.context = new AnnotationConfigApplicationContext(); + } + + @After + public void teardown() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void scanImportBeanRegistrarShouldBeEnvironmentAware() { + // this.context.getEnvironment().addActiveProfile("test"); + load(TestConfiguration.class); + assertThat(this.context.containsBean( + "profile-org.springframework.boot.context.properties.scan.valid.a.AScanConfiguration$MyProfileProperties")) + .isTrue(); + } + + @Test + public void scanImportBeanRegistrarShouldBeResourceLoaderAware() { + DefaultResourceLoader resourceLoader = Mockito.mock(DefaultResourceLoader.class); + this.context.setResourceLoader(resourceLoader); + willCallRealMethod().given(resourceLoader).getClassLoader(); + given(resourceLoader.getResource("test")) + .willReturn(new ByteArrayResource("test".getBytes())); + load(TestConfiguration.class); + assertThat(this.context.containsBean( + "resource-org.springframework.boot.context.properties.scan.valid.a.AScanConfiguration$MyResourceProperties")) + .isTrue(); + } + + private void load(Class... classes) { + this.context.register(classes); + this.context.refresh(); + } + + @ConfigurationPropertiesScan(basePackageClasses = AScanConfiguration.class) + static class TestConfiguration { + + } + +} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/scan/valid/a/AScanConfiguration.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/scan/valid/a/AScanConfiguration.java index f798ed4542..dafebc3583 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/scan/valid/a/AScanConfiguration.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/scan/valid/a/AScanConfiguration.java @@ -16,6 +16,12 @@ package org.springframework.boot.context.properties.scan.valid.a; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Profile; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.type.AnnotatedTypeMetadata; /** * @author Madhura Bhave @@ -27,4 +33,27 @@ public class AScanConfiguration { } + @Profile("test") + @ConfigurationProperties(prefix = "profile") + static class MyProfileProperties { + + } + + @Conditional(TestResourceCondition.class) + @ConfigurationProperties(prefix = "resource") + static class MyResourceProperties { + + } + + static class TestResourceCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + ByteArrayResource resource = (ByteArrayResource) context.getResourceLoader() + .getResource("test"); + return (new String(resource.getByteArray())).equals("test"); + } + + } + }