Reuse `ConfigurationProperties` bean defined in parent

This commit makes sure that if a `ConfigurationProperties` annotated bean
already exists in the parent context, a new one is not created in the
child anymore.

This makes sure that a single bean exists in a parent/child hierarchy if
`@EnableConfigurationProperties` is processed in both context on the same
class.

Closes gh-8187
pull/8204/head
Stephane Nicoll 8 years ago
parent 98d2ed85e4
commit 1061afbe00

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -19,6 +19,7 @@ package org.springframework.boot.context.properties;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -78,7 +79,8 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
String prefix = extractPrefix(type);
String name = (StringUtils.hasText(prefix) ? prefix + "-" + type.getName()
: type.getName());
if (!registry.containsBeanDefinition(name)) {
if (!containsBeanDefinition(
(ConfigurableListableBeanFactory) registry, name)) {
registerBeanDefinition(registry, type, name);
}
}
@ -119,6 +121,23 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
+ " annotation found on '" + type.getName() + "'.");
}
private boolean containsBeanDefinition(
ConfigurableListableBeanFactory beanFactory, String name) {
boolean result = beanFactory.containsBeanDefinition(name);
if (result) {
return true;
}
if (beanFactory
.getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
return containsBeanDefinition(
(ConfigurableListableBeanFactory) beanFactory
.getParentBeanFactory(),
name);
}
return false;
}
}
}

@ -290,18 +290,24 @@ public class EnableConfigurationPropertiesTests {
@Test
public void testBindingWithParentContext() {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
AnnotationConfigApplicationContext parent =
new AnnotationConfigApplicationContext();
parent.register(TestConfiguration.class);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(parent,
"name=parent");
parent.refresh();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"name=foo");
this.context.setParent(parent);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"name=child");
this.context.register(TestConfiguration.class, TestConsumer.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(TestProperties.class).length)
.isEqualTo(0);
assertThat(parent.getBeanNamesForType(TestProperties.class).length)
.isEqualTo(1);
assertThat(parent.getBeanNamesForType(TestProperties.class).length).isEqualTo(1);
assertThat(this.context.getBean(TestConsumer.class).getName()).isEqualTo("foo");
assertThat(this.context.getBean(TestConsumer.class).getName())
.isEqualTo("parent");
parent.close();
}
@Test

Loading…
Cancel
Save