Refactor ConfigurationPropertiesRebinder a bit
It's not super expensive, but it all adds up, and rebinding beans that don't need to be rebound is wasteful. This change should improve things in three places: The ConfigurationPropertiesRebinder has always done a pre-emptive re-bind on startup, which was a bit of a blunt instrument, since all we really wanted as to rebind the beans in the parent context (to the current context's Environment). The rebinding always happened twice for every bean because we explicitly called into the ConfigurationPropertiesPostProcessor directly as well as indirectly through the initialization callbacks. Rebinding in response to an EnvironmentChangeEvent was not able to distinguish between events published locally and by child contexts. The child context always binds the parent's beans anyway, so you don't need to do it twice.
This commit is contained in:
@@ -19,7 +19,9 @@ import javax.annotation.PostConstruct;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -33,17 +35,22 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = TestConfiguration.class)
|
||||
@ActiveProfiles("config")
|
||||
public class ConfigurationPropertiesRebinderIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private TestProperties properties;
|
||||
|
||||
@Autowired
|
||||
private ConfigProperties config;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationPropertiesRebinder rebinder;
|
||||
|
||||
@@ -54,44 +61,55 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
|
||||
@DirtiesContext
|
||||
public void testSimpleProperties() throws Exception {
|
||||
assertEquals("Hello scope!", this.properties.getMessage());
|
||||
assertEquals(2, this.properties.getCount());
|
||||
assertEquals(1, this.properties.getCount());
|
||||
// Change the dynamic property source...
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "message:Foo");
|
||||
// ...but don't refresh, so the bean stays the same:
|
||||
assertEquals("Hello scope!", this.properties.getMessage());
|
||||
assertEquals(2, this.properties.getCount());
|
||||
assertEquals(1, this.properties.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testRefreshInParent() throws Exception {
|
||||
assertEquals("main", this.config.getName());
|
||||
// Change the dynamic property source...
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "config.name=foo");
|
||||
// ...and then refresh, so the bean is re-initialized:
|
||||
this.rebinder.rebind();
|
||||
assertEquals("foo", this.config.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testRefresh() throws Exception {
|
||||
assertEquals(2, this.properties.getCount());
|
||||
assertEquals(1, this.properties.getCount());
|
||||
assertEquals("Hello scope!", this.properties.getMessage());
|
||||
// Change the dynamic property source...
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "message:Foo");
|
||||
// ...and then refresh, so the bean is re-initialized:
|
||||
this.rebinder.rebind();
|
||||
assertEquals("Foo", this.properties.getMessage());
|
||||
assertEquals(3, this.properties.getCount());
|
||||
assertEquals(2, this.properties.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testRefreshByName() throws Exception {
|
||||
assertEquals(2, this.properties.getCount());
|
||||
assertEquals(1, this.properties.getCount());
|
||||
assertEquals("Hello scope!", this.properties.getMessage());
|
||||
// Change the dynamic property source...
|
||||
EnvironmentTestUtils.addEnvironment(this.environment, "message:Foo");
|
||||
// ...and then refresh, so the bean is re-initialized:
|
||||
this.rebinder.rebind("properties");
|
||||
assertEquals("Foo", this.properties.getMessage());
|
||||
assertEquals(3, this.properties.getCount());
|
||||
assertEquals(2, this.properties.getCount());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@Import({ RefreshConfiguration.RebinderConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class })
|
||||
PropertyPlaceholderAutoConfiguration.class })
|
||||
protected static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -104,8 +122,8 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
|
||||
// Hack out a protected inner class for testing
|
||||
protected static class RefreshConfiguration extends RefreshAutoConfiguration {
|
||||
@Configuration
|
||||
protected static class RebinderConfiguration extends
|
||||
ConfigurationPropertiesRebinderAutoConfiguration {
|
||||
protected static class RebinderConfiguration
|
||||
extends ConfigurationPropertiesRebinderAutoConfiguration {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -142,4 +160,17 @@ public class ConfigurationPropertiesRebinderIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigurationProperties("config")
|
||||
@ConditionalOnMissingBean(ConfigProperties.class)
|
||||
public static class ConfigProperties {
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
@@ -52,7 +53,7 @@ public class LoggingRebinderTests {
|
||||
EnvironmentTestUtils.addEnvironment(environment,
|
||||
"logging.level.org.springframework.web=TRACE");
|
||||
this.rebinder.setEnvironment(environment);
|
||||
this.rebinder.onApplicationEvent(new EnvironmentChangeEvent(
|
||||
this.rebinder.onApplicationEvent(new EnvironmentChangeEvent(environment,
|
||||
Collections.singleton("logging.level.org.springframework.web")));
|
||||
assertTrue(this.logger.isTraceEnabled());
|
||||
}
|
||||
@@ -64,7 +65,7 @@ public class LoggingRebinderTests {
|
||||
EnvironmentTestUtils.addEnvironment(environment,
|
||||
"logging.level.org.springframework.web=trace");
|
||||
this.rebinder.setEnvironment(environment);
|
||||
this.rebinder.onApplicationEvent(new EnvironmentChangeEvent(
|
||||
this.rebinder.onApplicationEvent(new EnvironmentChangeEvent(environment,
|
||||
Collections.singleton("logging.level.org.springframework.web")));
|
||||
assertTrue(this.logger.isTraceEnabled());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user