diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationProperties.java index 7c8c41e05ad3..8fadb6690971 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationProperties.java @@ -39,6 +39,7 @@ * values are externalized. * * @author Dave Syer + * @author Yanming Zhou * @since 1.0.0 * @see ConfigurationPropertiesScan * @see ConstructorBinding @@ -69,6 +70,14 @@ @AliasFor("value") String prefix() default ""; + /** + * The prefix of the properties that {@link #prefix()} will inherit, It's used for + * configuring multiple beans which share common properties. + * @return the prefix of the properties to inherit + * @see #prefix() + */ + String inheritedPrefix() default ""; + /** * Flag to indicate that when binding to this object invalid fields should be ignored. * Invalid means invalid according to the binder that is used, and usually this means diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java index 392a7804bf3f..73f1bb8555d2 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java @@ -128,6 +128,7 @@ * @author Stephane Nicoll * @author Madhura Bhave * @author Vladislav Kisel + * @author Yanming Zhou */ @ExtendWith(OutputCaptureExtension.class) class ConfigurationPropertiesTests { @@ -1270,6 +1271,15 @@ void loadWhenBindingToJavaBeanWithConversionToCustomListImplementation() { assertThat(this.context.getBean(SetterBoundCustomListProperties.class).getValues()).containsExactly("a", "b"); } + @Test + void bindMultipleBeansUsingInheritedPrefix() { + load(InheritedPrefixConfiguration.class, "spring.service.host=127.0.0.1", "spring.service.port=6379", + "additional.service.port=6380"); + ServiceProperties properties = this.context.getBean("additionalServiceProperties", ServiceProperties.class); + assertThat(properties.getHost()).isEqualTo("127.0.0.1"); + assertThat(properties.getPort()).isEqualTo(6380); + } + private AnnotationConfigApplicationContext load(Class configuration, String... inlinedProperties) { return load(new Class[] { configuration }, inlinedProperties); } @@ -3310,4 +3320,40 @@ static final class CustomList extends ArrayList { } + @ConfigurationProperties(prefix = "spring.service") + static class ServiceProperties { + + private String host = "localhost"; + + private int port = 6379; + + String getHost() { + return this.host; + } + + void setHost(String host) { + this.host = host; + } + + int getPort() { + return this.port; + } + + void setPort(int port) { + this.port = port; + } + + } + + @EnableConfigurationProperties(ServiceProperties.class) + static class InheritedPrefixConfiguration { + + @Bean(autowireCandidate = false) // do not back off auto-configured one + @ConfigurationProperties(prefix = "additional.service", inheritedPrefix = "spring.service") + ServiceProperties additionalServiceProperties() { + return new ServiceProperties(); + } + + } + }