Merge branch '6.2.x'

This commit is contained in:
Sam Brannen
2025-05-11 13:53:40 +02:00
2 changed files with 143 additions and 36 deletions
@@ -16,11 +16,16 @@
package org.springframework.context.support;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -32,6 +37,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
@@ -90,14 +96,29 @@ class PropertySourcesPlaceholderConfigurerTests {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("foo");
}
@Test
void localPropertiesOverrideFalse() {
localPropertiesOverride(false);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void localPropertiesOverride(boolean override) {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${foo}")
.getBeanDefinition());
@Test
void localPropertiesOverrideTrue() {
localPropertiesOverride(true);
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setLocalOverride(override);
ppc.setProperties(new Properties() {{
setProperty("foo", "local");
}});
ppc.setEnvironment(new MockEnvironment().withProperty("foo", "enclosing"));
ppc.postProcessBeanFactory(bf);
if (override) {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("local");
}
else {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("enclosing");
}
}
@Test
@@ -283,28 +304,58 @@ class PropertySourcesPlaceholderConfigurerTests {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("bar");
}
@SuppressWarnings("serial")
private void localPropertiesOverride(boolean override) {
@Test // gh-34861
void withEnumerableAndNonEnumerablePropertySourcesInTheEnvironmentAndLocalProperties() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${foo}")
.addPropertyValue("name", "${foo:bogus}")
.addPropertyValue("jedi", "${local:false}")
.getBeanDefinition());
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
// 1) MockPropertySource is an EnumerablePropertySource.
MockPropertySource mockPropertySource = new MockPropertySource("mockPropertySource")
.withProperty("foo", "${bar}");
ppc.setLocalOverride(override);
// 2) PropertySource is not an EnumerablePropertySource.
PropertySource<?> rawPropertySource = new PropertySource<>("rawPropertySource", new Object()) {
@Override
public Object getProperty(String key) {
return ("bar".equals(key) ? "quux" : null);
}
};
MockEnvironment env = new MockEnvironment();
env.getPropertySources().addFirst(mockPropertySource);
env.getPropertySources().addLast(rawPropertySource);
PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setEnvironment(env);
// 3) Local properties are stored in a PropertiesPropertySource which is an EnumerablePropertySource.
ppc.setProperties(new Properties() {{
setProperty("foo", "local");
setProperty("local", "true");
}});
ppc.setEnvironment(new MockEnvironment().withProperty("foo", "enclosing"));
ppc.postProcessBeanFactory(bf);
if (override) {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("local");
}
else {
assertThat(bf.getBean(TestBean.class).getName()).isEqualTo("enclosing");
// Verify all properties can be resolved via the Environment.
assertThat(env.getProperty("foo")).isEqualTo("quux");
assertThat(env.getProperty("bar")).isEqualTo("quux");
// Verify that placeholder resolution works.
TestBean testBean = bf.getBean(TestBean.class);
assertThat(testBean.getName()).isEqualTo("quux");
assertThat(testBean.isJedi()).isTrue();
// Verify that the presence of a non-EnumerablePropertySource does not prevent
// accessing EnumerablePropertySources via getAppliedPropertySources().
List<String> propertyNames = new ArrayList<>();
for (PropertySource<?> propertySource : ppc.getAppliedPropertySources()) {
if (propertySource instanceof EnumerablePropertySource<?> enumerablePropertySource) {
Collections.addAll(propertyNames, enumerablePropertySource.getPropertyNames());
}
}
// Should not contain "foo" or "bar" from the Environment.
assertThat(propertyNames).containsOnly("local");
}
@Test