From f963d0f190b60d56653a1dd4fd5119fb3ba70969 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Wed, 5 Sep 2012 21:10:06 +0200 Subject: [PATCH] Register environment in all bean factories in a hierarchy Prior to this change, AbstractApplicationContext#prepareBeanFactory registered a bean named 'environment' once and only once within a given ApplicationContext hierarchy. This worked fine with the expectation that the Environment object is always delegated downward to children of that hierarchy. However, with SPR-9444 and the introduction of ConfigurableEnvironment#merge, this expectation was violated; each member of an application context hierarchy now maintains its own distinct Environment instance, which means that by extension that each application context's underlying BeanFactory should have its own 'environment' bean pointing to that context's environment instance. This problem could manifest in getting the wrong environment instance when calling #getBean(Environment) or when @Autowiring an Environment instance, for example into a @Configuration class. As reported in SPR-9756, this could result in false negative property lookups or incorrect results when checking whether a profile is active. This commit ensures that every bean factory in an application hierarchy has an 'environment' bean referring to the object returned from the enclosing ApplicationContext#getEnvironment method. Issue: SPR-9756, SPR-9444 --- .../support/AbstractApplicationContext.java | 4 +- .../support/EnvironmentIntegrationTests.java | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 spring-context/src/test/java/org/springframework/context/support/EnvironmentIntegrationTests.java diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java index 8f3be1847d1..726a172aa9c 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -566,7 +566,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader } // Register default environment beans. - if (!beanFactory.containsBean(ENVIRONMENT_BEAN_NAME)) { + if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } diff --git a/spring-context/src/test/java/org/springframework/context/support/EnvironmentIntegrationTests.java b/spring-context/src/test/java/org/springframework/context/support/EnvironmentIntegrationTests.java new file mode 100644 index 00000000000..dbe93cabaf6 --- /dev/null +++ b/spring-context/src/test/java/org/springframework/context/support/EnvironmentIntegrationTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.context.support; + +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; + +import static org.junit.Assert.*; + +import static org.hamcrest.CoreMatchers.*; + +/** + * Tests covering the integration of {@link Environment} into {@link ApplicationContext} + * hierarchies. + * + * @author Chris Beams + */ +public class EnvironmentIntegrationTests { + + @SuppressWarnings("unchecked") + @Test + public void repro() { + ConfigurableApplicationContext parent = new GenericApplicationContext(); + parent.refresh(); + + AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext(); + child.setParent(parent); + child.refresh(); + + ConfigurableEnvironment env = child.getBean(ConfigurableEnvironment.class); + assertThat("unknown env", env, anyOf( + sameInstance(parent.getEnvironment()), + sameInstance(child.getEnvironment()))); + assertThat("expected child ctx env", env, sameInstance(child.getEnvironment())); + } +}