diff --git a/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java b/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java index 4ee1eb73acd..364e88ca106 100644 --- a/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java +++ b/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java @@ -26,6 +26,8 @@ import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PlaceholderConfigurerSupport; import org.springframework.context.EnvironmentAware; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurablePropertyResolver; import org.springframework.core.env.Environment; @@ -240,16 +242,37 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS } @Override - public @Nullable Object getProperty(String name) { + // Declare String as covariant return type, since a String is actually required. + public @Nullable String getProperty(String name) { for (PropertySource propertySource : super.source.getPropertySources()) { Object candidate = propertySource.getProperty(name); if (candidate != null) { - return candidate; + return convertToString(candidate); } } return null; } + /** + * Convert the supplied value to a {@link String} using the {@link ConversionService} + * from the {@link Environment}. + *

This is a modified version of + * {@link org.springframework.core.env.AbstractPropertyResolver#convertValueIfNecessary(Object, Class)}. + * @param value the value to convert + * @return the converted value, or the original value if no conversion is necessary + * @since 6.2.8 + */ + private @Nullable String convertToString(Object value) { + if (value instanceof String string) { + return string; + } + ConversionService conversionService = super.source.getConversionService(); + if (conversionService == null) { + conversionService = DefaultConversionService.getSharedInstance(); + } + return conversionService.convert(value, String.class); + } + @Override public String toString() { return "ConfigurableEnvironmentPropertySource {propertySources=" + super.source.getPropertySources() + "}"; @@ -275,7 +298,8 @@ public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerS } @Override - public @Nullable Object getProperty(String name) { + // Declare String as covariant return type, since a String is actually required. + public @Nullable String getProperty(String name) { return super.source.getProperty(name); } diff --git a/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java b/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java index 8e8cdef9455..71c9eeea73b 100644 --- a/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java +++ b/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java @@ -25,7 +25,6 @@ import java.util.Properties; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -98,7 +97,6 @@ class PropertySourcesPlaceholderConfigurerTests { * used by the {@code Environment} is applied during placeholder resolution * against a {@link PropertySource} registered in the {@code Environment}. */ - @Disabled("Disabled until gh-34936 is resolved") @Test // gh-34936 void replacementFromEnvironmentPropertiesWithConversion() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory();