Introduce AbstractEnvironment#customizePropertySources
This new hook in the AbstractEnvironment lifecycle allows for more explicit and predictable customization of property sources by subclasses. See Javadoc and existing implementations for detail. Issue: SPR-8354
This commit is contained in:
parent
c4a13507f0
commit
7271ba8182
|
|
@ -74,8 +74,92 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
|
||||||
private Set<String> activeProfiles = new LinkedHashSet<String>();
|
private Set<String> activeProfiles = new LinkedHashSet<String>();
|
||||||
private Set<String> defaultProfiles = new LinkedHashSet<String>(this.getReservedDefaultProfiles());
|
private Set<String> defaultProfiles = new LinkedHashSet<String>(this.getReservedDefaultProfiles());
|
||||||
|
|
||||||
private MutablePropertySources propertySources = new MutablePropertySources();
|
private final MutablePropertySources propertySources = new MutablePropertySources();
|
||||||
private ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
|
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(propertySources);
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractEnvironment() {
|
||||||
|
this.customizePropertySources(propertySources);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize the set of {@link PropertySource} objects to be searched by this
|
||||||
|
* {@code Environment} during calls to {@link #getProperty(String)} and related
|
||||||
|
* methods.
|
||||||
|
*
|
||||||
|
* <p>Subclasses that override this method are encouraged to add property
|
||||||
|
* sources using {@link MutablePropertySources#addLast(PropertySource)} such that
|
||||||
|
* further subclasses may call {@code super.customizePropertySources()} with
|
||||||
|
* predictable results. For example:
|
||||||
|
* <pre class="code">
|
||||||
|
* public class Level1Environment extends AbstractEnvironment {
|
||||||
|
* @Override
|
||||||
|
* protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
|
* super.customizePropertySources(propertySources); // no-op from base class
|
||||||
|
* propertySources.addLast(new PropertySourceA(...));
|
||||||
|
* propertySources.addLast(new PropertySourceB(...));
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public class Level2Environment extends Level1Environment {
|
||||||
|
* @Override
|
||||||
|
* protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
|
* super.customizePropertySources(propertySources); // add all from superclass
|
||||||
|
* propertySources.addLast(new PropertySourceC(...));
|
||||||
|
* propertySources.addLast(new PropertySourceD(...));
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* In this arrangement, properties will be resolved against sources A, B, C, D in that
|
||||||
|
* order. That is to say that property source "A" has precedence over property source
|
||||||
|
* "D". If the {@code Level2Environment} subclass wished to give property sources C
|
||||||
|
* and D higher precedence than A and B, it could simply call
|
||||||
|
* {@code super.customizePropertySources} after, rather than before adding its own:
|
||||||
|
* <pre>
|
||||||
|
* public class Level2Environment extends Level1Environment {
|
||||||
|
* @Override
|
||||||
|
* protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
|
* propertySources.addLast(new PropertySourceC(...));
|
||||||
|
* propertySources.addLast(new PropertySourceD(...));
|
||||||
|
* super.customizePropertySources(propertySources); // add all from superclass
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* The search order is now C, D, A, B as desired.
|
||||||
|
*
|
||||||
|
* <p>Beyond these recommendations, subclasses may use any of the <code>add*</code>,
|
||||||
|
* {@code remove}, or {@code replace} methods exposed by {@link MutablePropertySources}
|
||||||
|
* in order to create the exact arrangement of property sources desired.
|
||||||
|
*
|
||||||
|
* <p>The base implementation in {@link AbstractEnvironment#customizePropertySources}
|
||||||
|
* registers no property sources.
|
||||||
|
*
|
||||||
|
* <p>Note that clients of any {@link ConfigurableEnvironment} may further customize
|
||||||
|
* property sources via the {@link #getPropertySources()} accessor, typically within
|
||||||
|
* an {@link org.springframework.context.ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializer}. For example:
|
||||||
|
* <pre>
|
||||||
|
* ConfigurableEnvironment env = new StandardEnvironment();
|
||||||
|
* env.getPropertySources().addLast(new PropertySourceX(...));
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see MutablePropertySources
|
||||||
|
* @see PropertySourcesPropertyResolver
|
||||||
|
* @see org.springframework.context.ApplicationContextInitializer
|
||||||
|
*/
|
||||||
|
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the set of reserved default profile names. This implementation returns
|
||||||
|
* {@value #RESERVED_DEFAULT_PROFILE_NAME}. Subclasses may override in order to
|
||||||
|
* customize the set of reserved names.
|
||||||
|
* @see #RESERVED_DEFAULT_PROFILE_NAME
|
||||||
|
* @see #doGetDefaultProfiles()
|
||||||
|
*/
|
||||||
|
protected Set<String> getReservedDefaultProfiles() {
|
||||||
|
return Collections.singleton(RESERVED_DEFAULT_PROFILE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,19 @@ public interface ConfigurableEnvironment extends Environment, ConfigurableProper
|
||||||
void setDefaultProfiles(String... profiles);
|
void setDefaultProfiles(String... profiles);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link PropertySources} for this environment in mutable form
|
* Return the {@link PropertySources} for this {@code Environment} in mutable form,
|
||||||
|
* allowing for manipulation of the set of {@link PropertySource} objects that should
|
||||||
|
* be searched when resolving properties against this {@code Environment} object.
|
||||||
|
* The various {@link MutablePropertySources} methods such as
|
||||||
|
* {@link MutablePropertySources#addFirst addFirst},
|
||||||
|
* {@link MutablePropertySources#addFirst addLast},
|
||||||
|
* {@link MutablePropertySources#addFirst addBefore} and
|
||||||
|
* {@link MutablePropertySources#addFirst addAfter} allow for fine-grained control
|
||||||
|
* over property source ordering. This is useful, for example, in ensuring that
|
||||||
|
* certain user-defined property sources have search precedence over default property
|
||||||
|
* sources such as the set of system properties or the set of system environment
|
||||||
|
* variables.
|
||||||
|
* @see DefaultEnvironment#DefaultEnvironment()
|
||||||
*/
|
*/
|
||||||
MutablePropertySources getPropertySources();
|
MutablePropertySources getPropertySources();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,17 +83,21 @@ public class DefaultEnvironment extends AbstractEnvironment {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@code Environment} populated with property sources in the following order:
|
* Customize the set of property sources with those appropriate for any standard Java
|
||||||
|
* environment:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
|
* <li>{@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME}
|
||||||
* <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}
|
* <li>{@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will
|
* <p>Properties present in {@value #SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME} will
|
||||||
* take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}.
|
* take precedence over those in {@value #SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME}.
|
||||||
|
* @see #getSystemProperties()
|
||||||
|
* @see #getSystemEnvironment()
|
||||||
*/
|
*/
|
||||||
public DefaultEnvironment() {
|
@Override
|
||||||
getPropertySources().addFirst(new MapPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
|
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
getPropertySources().addFirst(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
|
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
|
||||||
|
propertySources.addLast(new MapPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.springframework.core.env.DefaultEnvironment;
|
import org.springframework.core.env.DefaultEnvironment;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.env.PropertySource.StubPropertySource;
|
import org.springframework.core.env.PropertySource.StubPropertySource;
|
||||||
import org.springframework.web.context.support.DefaultWebEnvironment;
|
import org.springframework.web.context.support.DefaultWebEnvironment;
|
||||||
|
|
@ -49,8 +50,8 @@ public class DefaultPortletEnvironment extends DefaultEnvironment {
|
||||||
public static final String PORTLET_CONFIG_PROPERTY_SOURCE_NAME = "portletConfigInitParams";
|
public static final String PORTLET_CONFIG_PROPERTY_SOURCE_NAME = "portletConfigInitParams";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@code Environment} populated with the property sources contributed by
|
* Customize the set of property sources with those contributed by superclasses as
|
||||||
* superclasses as well as:
|
* well as those appropriate for standard portlet-based environments:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME}
|
* <li>{@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME}
|
||||||
* <li>{@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME}
|
* <li>{@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME}
|
||||||
|
|
@ -58,22 +59,25 @@ public class DefaultPortletEnvironment extends DefaultEnvironment {
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>Properties present in {@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME} will
|
* <p>Properties present in {@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME} will
|
||||||
* take precedence over those in {@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME},
|
* take precedence over those in {@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME},
|
||||||
* which takes precedence over those in .
|
* which takes precedence over those in
|
||||||
* Properties in either will take precedence over system properties and environment
|
* {@linkplain DefaultWebEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME "servletContextInitParams"}.
|
||||||
* variables.
|
* <p>Properties in any of the above will take precedence over system properties and environment
|
||||||
|
* variables contributed by the {@link DefaultEnvironment} superclass.
|
||||||
* <p>The property sources are added as stubs for now, and will be
|
* <p>The property sources are added as stubs for now, and will be
|
||||||
* {@linkplain PortletApplicationContextUtils#initPortletPropertySources fully initialized}
|
* {@linkplain PortletApplicationContextUtils#initPortletPropertySources fully initialized}
|
||||||
* once the actual {@link PortletConfig}, {@link PortletContext}, and {@link ServletContext}
|
* once the actual {@link PortletConfig}, {@link PortletContext}, and {@link ServletContext}
|
||||||
* objects are available.
|
* objects are available.
|
||||||
* @see DefaultEnvironment#DefaultEnvironment
|
* @see DefaultEnvironment#customizePropertySources
|
||||||
* @see PortletConfigPropertySource
|
* @see PortletConfigPropertySource
|
||||||
* @see PortletContextPropertySource
|
* @see PortletContextPropertySource
|
||||||
* @see AbstractRefreshablePortletApplicationContext#initPropertySources
|
* @see AbstractRefreshablePortletApplicationContext#initPropertySources
|
||||||
* @see PortletApplicationContextUtils#initPortletPropertySources
|
* @see PortletApplicationContextUtils#initPortletPropertySources
|
||||||
*/
|
*/
|
||||||
public DefaultPortletEnvironment() {
|
@Override
|
||||||
this.getPropertySources().addFirst(new StubPropertySource(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
this.getPropertySources().addFirst(new StubPropertySource(PORTLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
propertySources.addLast(new StubPropertySource(PORTLET_CONFIG_PROPERTY_SOURCE_NAME));
|
||||||
this.getPropertySources().addFirst(new StubPropertySource(PORTLET_CONFIG_PROPERTY_SOURCE_NAME));
|
propertySources.addLast(new StubPropertySource(PORTLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||||
|
propertySources.addLast(new StubPropertySource(DefaultWebEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||||
|
super.customizePropertySources(propertySources);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.springframework.core.env.DefaultEnvironment;
|
import org.springframework.core.env.DefaultEnvironment;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.env.PropertySource.StubPropertySource;
|
import org.springframework.core.env.PropertySource.StubPropertySource;
|
||||||
import org.springframework.core.env.PropertySources;
|
import org.springframework.core.env.PropertySources;
|
||||||
|
|
@ -53,8 +54,8 @@ public class DefaultWebEnvironment extends DefaultEnvironment {
|
||||||
public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
|
public static final String SERVLET_CONFIG_PROPERTY_SOURCE_NAME = "servletConfigInitParams";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@code Environment} populated with the property sources contributed by
|
* Customize the set of property sources with those contributed by superclasses as
|
||||||
* superclasses as well as:
|
* well as those appropriate for standard servlet-based environments:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@value #SERVLET_CONFIG_PROPERTY_SOURCE_NAME}
|
* <li>{@value #SERVLET_CONFIG_PROPERTY_SOURCE_NAME}
|
||||||
* <li>{@value #SERVLET_CONTEXT_PROPERTY_SOURCE_NAME}
|
* <li>{@value #SERVLET_CONTEXT_PROPERTY_SOURCE_NAME}
|
||||||
|
|
@ -62,8 +63,8 @@ public class DefaultWebEnvironment extends DefaultEnvironment {
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>Properties present in {@value #SERVLET_CONFIG_PROPERTY_SOURCE_NAME} will
|
* <p>Properties present in {@value #SERVLET_CONFIG_PROPERTY_SOURCE_NAME} will
|
||||||
* take precedence over those in {@value #SERVLET_CONTEXT_PROPERTY_SOURCE_NAME}.
|
* take precedence over those in {@value #SERVLET_CONTEXT_PROPERTY_SOURCE_NAME}.
|
||||||
* Properties in either will take precedence over system properties and environment
|
* <p>Properties in any of the above will take precedence over system properties and environment
|
||||||
* variables.
|
* variables contributed by the {@link DefaultEnvironment} superclass.
|
||||||
* <p>The {@code Servlet}-related property sources are added as stubs for now, and will be
|
* <p>The {@code Servlet}-related property sources are added as stubs for now, and will be
|
||||||
* {@linkplain WebApplicationContextUtils#initServletPropertySources fully initialized}
|
* {@linkplain WebApplicationContextUtils#initServletPropertySources fully initialized}
|
||||||
* once the actual {@link ServletConfig} and {@link ServletContext} objects are available.
|
* once the actual {@link ServletConfig} and {@link ServletContext} objects are available.
|
||||||
|
|
@ -71,21 +72,21 @@ public class DefaultWebEnvironment extends DefaultEnvironment {
|
||||||
* property is present in any of the default property sources, a {@link JndiPropertySource} will
|
* property is present in any of the default property sources, a {@link JndiPropertySource} will
|
||||||
* be added as well, with precedence lower than servlet property sources, but higher than system
|
* be added as well, with precedence lower than servlet property sources, but higher than system
|
||||||
* properties and environment variables.
|
* properties and environment variables.
|
||||||
* @see DefaultEnvironment#DefaultEnvironment
|
* @see DefaultEnvironment#customizePropertySources
|
||||||
* @see ServletConfigPropertySource
|
* @see ServletConfigPropertySource
|
||||||
* @see ServletContextPropertySource
|
* @see ServletContextPropertySource
|
||||||
* @see org.springframework.jndi.JndiPropertySource
|
* @see org.springframework.jndi.JndiPropertySource
|
||||||
* @see org.springframework.context.support.AbstractApplicationContext#initPropertySources
|
* @see org.springframework.context.support.AbstractApplicationContext#initPropertySources
|
||||||
* @see WebApplicationContextUtils#initServletPropertySources
|
* @see WebApplicationContextUtils#initServletPropertySources
|
||||||
*/
|
*/
|
||||||
public DefaultWebEnvironment() {
|
@Override
|
||||||
getPropertySources().addFirst(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||||
getPropertySources().addFirst(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
|
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
|
||||||
|
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||||
|
super.customizePropertySources(propertySources);
|
||||||
|
|
||||||
Boolean jndiPropertySourceEnabled = this.getProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG, boolean.class);
|
if (this.getProperty(JndiPropertySource.JNDI_PROPERTY_SOURCE_ENABLED_FLAG, boolean.class, false)) {
|
||||||
if (jndiPropertySourceEnabled != null && jndiPropertySourceEnabled) {
|
propertySources.addAfter(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, new JndiPropertySource());
|
||||||
getPropertySources().addAfter(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, new JndiPropertySource());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue