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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@ -78,7 +79,8 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
String prefix = extractPrefix(type); String prefix = extractPrefix(type);
String name = (StringUtils.hasText(prefix) ? prefix + "-" + type.getName() String name = (StringUtils.hasText(prefix) ? prefix + "-" + type.getName()
: type.getName()); : type.getName());
if (!registry.containsBeanDefinition(name)) { if (!containsBeanDefinition(
(ConfigurableListableBeanFactory) registry, name)) {
registerBeanDefinition(registry, type, name); registerBeanDefinition(registry, type, name);
} }
} }
@ -119,6 +121,23 @@ class EnableConfigurationPropertiesImportSelector implements ImportSelector {
+ " annotation found on '" + type.getName() + "'."); + " 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 @Test
public void testBindingWithParentContext() { public void testBindingWithParentContext() {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext parent =
new AnnotationConfigApplicationContext();
parent.register(TestConfiguration.class); parent.register(TestConfiguration.class);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(parent,
"name=parent");
parent.refresh(); parent.refresh();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"name=foo");
this.context.setParent(parent); this.context.setParent(parent);
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"name=child");
this.context.register(TestConfiguration.class, TestConsumer.class); this.context.register(TestConfiguration.class, TestConsumer.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBeanNamesForType(TestProperties.class).length) assertThat(this.context.getBeanNamesForType(TestProperties.class).length)
.isEqualTo(0);
assertThat(parent.getBeanNamesForType(TestProperties.class).length)
.isEqualTo(1); .isEqualTo(1);
assertThat(parent.getBeanNamesForType(TestProperties.class).length).isEqualTo(1); assertThat(this.context.getBean(TestConsumer.class).getName())
assertThat(this.context.getBean(TestConsumer.class).getName()).isEqualTo("foo"); .isEqualTo("parent");
parent.close();
} }
@Test @Test

Loading…
Cancel
Save