diff --git a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java index 6a75edcb1c4..6be02e76d2b 100644 --- a/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java +++ b/spring-core/src/main/java/org/springframework/core/env/AbstractEnvironment.java @@ -107,10 +107,9 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { private final Set defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles()); - private final MutablePropertySources propertySources = new MutablePropertySources(); + private final MutablePropertySources propertySources; - private final ConfigurablePropertyResolver propertyResolver = - new PropertySourcesPropertyResolver(this.propertySources); + private final ConfigurablePropertyResolver propertyResolver; /** @@ -121,9 +120,44 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment { * @see #customizePropertySources(MutablePropertySources) */ public AbstractEnvironment() { - customizePropertySources(this.propertySources); + this(new MutablePropertySources()); } + /** + * Create a new {@code Environment} instance with a specific + * {@link MutablePropertySources} instance, calling back to + * {@link #customizePropertySources(MutablePropertySources)} during + * construction to allow subclasses to contribute or manipulate + * {@link PropertySource} instances as appropriate. + * @since 5.3.4 + * @see #customizePropertySources(MutablePropertySources) + */ + protected AbstractEnvironment(MutablePropertySources propertySources) { + this.propertySources = propertySources; + this.propertyResolver = createPropertyResolver(propertySources); + customizePropertySources(propertySources); + } + + + /** + * Factory method used to create the {@link ConfigurablePropertyResolver} + * instance used by the Environment. + * @since 5.3.4 + * @see #getPropertyResolver() + */ + protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { + return new PropertySourcesPropertyResolver(propertySources); + } + + /** + * Return the {@link ConfigurablePropertyResolver} being used by the + * {@link Environment}. + * @since 5.3.4 + * @see #createPropertyResolver(MutablePropertySources) + */ + protected final ConfigurablePropertyResolver getPropertyResolver() { + return this.propertyResolver; + } /** * Customize the set of {@link PropertySource} objects to be searched by this diff --git a/spring-core/src/main/java/org/springframework/core/env/StandardEnvironment.java b/spring-core/src/main/java/org/springframework/core/env/StandardEnvironment.java index fc4570684d9..5b6c60ada23 100644 --- a/spring-core/src/main/java/org/springframework/core/env/StandardEnvironment.java +++ b/spring-core/src/main/java/org/springframework/core/env/StandardEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -60,6 +60,14 @@ public class StandardEnvironment extends AbstractEnvironment { public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties"; + public StandardEnvironment() { + } + + protected StandardEnvironment(MutablePropertySources propertySources) { + super(propertySources); + } + + /** * Customize the set of property sources with those appropriate for any standard * Java environment: diff --git a/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java b/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java index dd7bac24ee0..a1666abcfb1 100644 --- a/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java +++ b/spring-core/src/test/java/org/springframework/core/env/CustomEnvironmentTests.java @@ -129,6 +129,41 @@ class CustomEnvironmentTests { assertThat(env.getDefaultProfiles()).containsExactly(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME); } + @Test + public void withCustomMutablePropertySources() { + class CustomMutablePropertySources extends MutablePropertySources {} + MutablePropertySources propertySources = new CustomMutablePropertySources(); + ConfigurableEnvironment env = new AbstractEnvironment(propertySources) {}; + assertThat(env.getPropertySources()).isInstanceOf(CustomMutablePropertySources.class); + } + + @Test + void withCustomPropertyResolver() { + class CustomPropertySourcesPropertyResolver extends PropertySourcesPropertyResolver { + public CustomPropertySourcesPropertyResolver( + PropertySources propertySources) { + super(propertySources); + } + + @Override + public String getProperty(String key) { + return super.getProperty(key)+"-test"; + } + } + ConfigurableEnvironment env = new AbstractEnvironment() { + @Override + protected ConfigurablePropertyResolver createPropertyResolver( + MutablePropertySources propertySources) { + return new CustomPropertySourcesPropertyResolver(propertySources); + } + }; + Map values = new LinkedHashMap<>(); + values.put("spring", "framework"); + PropertySource propertySource = new MapPropertySource("test", values); + env.getPropertySources().addFirst(propertySource); + assertThat(env.getProperty("spring")).isEqualTo("framework-test"); + } + private Profiles defaultProfile() { return Profiles.of(AbstractEnvironment.RESERVED_DEFAULT_PROFILE_NAME); } diff --git a/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java b/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java index c3177c711e8..00b09095e37 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/StandardServletEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -54,6 +54,14 @@ public class StandardServletEnvironment extends StandardEnvironment implements C public static final String JNDI_PROPERTY_SOURCE_NAME = "jndiProperties"; + public StandardServletEnvironment() { + } + + protected StandardServletEnvironment(MutablePropertySources propertySources) { + super(propertySources); + } + + /** * Customize the set of property sources with those contributed by superclasses as * well as those appropriate for standard servlet-based environments: