Introduce ConfigurableEnvironment#merge

Prior to this change, AbstractApplicationContext#setParent replaced the
child context's Environment with the parent's Environment if available.
This has the negative effect of potentially changing the type of the
child context's Environment, and in any case causes property sources
added directly against the child environment to be ignored. This
situation could easily occur if a WebApplicationContext child had a
non-web ApplicationContext set as its parent. In this case the parent
Environment type would (likely) be StandardEnvironment, while the child
Environment type would (likely) be StandardServletEnvironment. By
directly inheriting the parent environment, critical property sources
such as ServletContextPropertySource are lost entirely.

This commit introduces the concept of merging an environment through
the new ConfigurableEnvironment#merge method. Instead of replacing the
child's environment with the parent's,
AbstractApplicationContext#setParent now merges property sources as
well as active and default profile names from the parent into the
child. In this way, distinct environment objects are maintained with
specific types and property sources preserved. See #merge Javadoc for
additional details.

Issue: SPR-9444, SPR-9439
This commit is contained in:
Chris Beams
2012-05-26 14:09:21 +03:00
parent 5874383ef0
commit 9fcfd7e827
5 changed files with 92 additions and 7 deletions

View File

@@ -56,6 +56,47 @@ public class StandardEnvironmentTests {
private ConfigurableEnvironment environment = new StandardEnvironment();
@Test
public void merge() {
ConfigurableEnvironment child = new StandardEnvironment();
child.setActiveProfiles("c1", "c2");
child.getPropertySources().addLast(
new MockPropertySource("childMock")
.withProperty("childKey", "childVal")
.withProperty("bothKey", "childBothVal"));
ConfigurableEnvironment parent = new StandardEnvironment();
parent.setActiveProfiles("p1", "p2");
parent.getPropertySources().addLast(
new MockPropertySource("parentMock")
.withProperty("parentKey", "parentVal")
.withProperty("bothKey", "parentBothVal"));
assertThat(child.getProperty("childKey"), is("childVal"));
assertThat(child.getProperty("parentKey"), nullValue());
assertThat(child.getProperty("bothKey"), is("childBothVal"));
assertThat(parent.getProperty("childKey"), nullValue());
assertThat(parent.getProperty("parentKey"), is("parentVal"));
assertThat(parent.getProperty("bothKey"), is("parentBothVal"));
assertThat(child.getActiveProfiles(), equalTo(new String[]{"c1","c2"}));
assertThat(parent.getActiveProfiles(), equalTo(new String[]{"p1","p2"}));
child.merge(parent);
assertThat(child.getProperty("childKey"), is("childVal"));
assertThat(child.getProperty("parentKey"), is("parentVal"));
assertThat(child.getProperty("bothKey"), is("childBothVal"));
assertThat(parent.getProperty("childKey"), nullValue());
assertThat(parent.getProperty("parentKey"), is("parentVal"));
assertThat(parent.getProperty("bothKey"), is("parentBothVal"));
assertThat(child.getActiveProfiles(), equalTo(new String[]{"c1","c2","p1","p2"}));
assertThat(parent.getActiveProfiles(), equalTo(new String[]{"p1","p2"}));
}
@Test
public void propertySourceOrder() {
ConfigurableEnvironment env = new StandardEnvironment();