M1 cut of environment, profiles and property work (SPR-7508)

Decomposed Environment interface into PropertySources, PropertyResolver
objects

    Environment interface and implementations are still present, but
    simpler.

    PropertySources container aggregates PropertySource objects;
    PropertyResolver provides search, conversion, placeholder
    replacement. Single implementation for now is
    PropertySourcesPlaceholderResolver

Renamed EnvironmentAwarePropertyPlaceholderConfigurer to
PropertySourcesPlaceholderConfigurer

    <context:property-placeholder/> now registers PSPC by default, else
    PPC if systemPropertiesMode* settings are involved

Refined configuration and behavior of default profiles

    See Environment interface Javadoc for details

Added Portlet implementations of relevant interfaces:

    * DefaultPortletEnvironment
    * PortletConfigPropertySource, PortletContextPropertySource
    * Integrated each appropriately throughout Portlet app contexts

Added protected 'createEnvironment()' method to AbstractApplicationContext

    Subclasses can override at will to supply a custom Environment
    implementation.  In practice throughout the framework, this is how
    Web- and Portlet-related ApplicationContexts override use of the
    DefaultEnvironment and swap in DefaultWebEnvironment or
    DefaultPortletEnvironment as appropriate.

Introduced "stub-and-replace" behavior for Servlet- and Portlet-based
PropertySource implementations

    Allows for early registration and ordering of the stub, then
    replacement with actual backing object at refresh() time.

    Added AbstractApplicationContext.initPropertySources() method to
    support stub-and-replace behavior. Called from within existing
    prepareRefresh() method so as to avoid impact with
    ApplicationContext implementations that copy and modify AAC's
    refresh() method (e.g.: Spring DM).

    Added methods to WebApplicationContextUtils and
    PortletApplicationContextUtils to support stub-and-replace behavior

Added comprehensive Javadoc for all new or modified types and members

Added XSD documentation for all new or modified elements and attributes

    Including nested <beans>, <beans profile="..."/>, and changes for
    certain attributes type from xsd:IDREF to xsd:string

Improved fix for detecting non-file based Resources in
PropertiesLoaderSupport (SPR-7547, SPR-7552)

    Technically unrelated to environment work, but grouped in with
    this changeset for convenience.

Deprecated (removed) context:property-placeholder
'system-properties-mode' attribute from spring-context-3.1.xsd

    Functionality is preserved for those using schemas up to and including
    spring-context-3.0.  For 3.1, system-properties-mode is no longer
    supported as it conflicts with the idea of managing a set of property
    sources within the context's Environment object. See Javadoc in
    PropertyPlaceholderConfigurer, AbstractPropertyPlaceholderConfigurer
    and PropertySourcesPlaceholderConfigurer for details.

Introduced CollectionUtils.toArray(Enumeration<E>, A[])

Work items remaining for 3.1 M2:

    Consider repackaging PropertySource* types; eliminate internal use
    of SystemPropertyUtils and deprecate

    Further work on composition of Environment interface; consider
    repurposing existing PlaceholderResolver interface to obviate need
    for resolve[Required]Placeholder() methods currently in Environment.

    Ensure configurability of placeholder prefix, suffix, and value
    separator when working against an AbstractPropertyResolver

    Add JNDI-based Environment / PropertySource implementatinos

    Consider support for @Profile at the @Bean level

    Provide consistent logging for the entire property resolution
    lifecycle; consider issuing all such messages against a dedicated
    logger with a single category.

    Add reference documentation to cover the featureset.
This commit is contained in:
Chris Beams
2011-01-03 09:04:34 +00:00
parent b130a36af7
commit b3ff9be78f
111 changed files with 3439 additions and 1715 deletions

View File

@@ -152,7 +152,7 @@ public interface BeanFactory {
/**
* Return the bean instance that uniquely matches the given object type, if any.
* @param requiredType type the bean must match; can be an interface or superclass.
* {@literal null} is disallowed.
* {@code null} is disallowed.
* <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
* but may also be translated into a conventional by-name lookup based on the name
* of the given type. For more extensive retrieval operations across sets of beans,

View File

@@ -432,7 +432,6 @@ public class SingletonBeanFactoryLocator implements BeanFactoryLocator {
protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// TODO SPR-7508: consider whether to allow for setEnvironment() here (where would it come from?)
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {

View File

@@ -29,26 +29,87 @@ import org.springframework.util.StringValueResolver;
/**
* TODO SPR-7508: document.
* Abstract base class for property resource configurers that resolve placeholders
* in bean definition property values. Implementations <em>pull</em> values from a
* properties file or other {@linkplain org.springframework.core.env.PropertySource
* property source} into bean definitions.
*
* <p>The default placeholder syntax follows the Ant / Log4J / JSP EL style:
*
*<pre class="code">${...}</pre>
*
* Example XML bean definition:
*
*<pre class="code">{@code
*<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
* <property name="driverClassName" value="}${driver}{@code"/>
* <property name="url" value="jdbc:}${dbname}{@code"/>
*</bean>
*}</pre>
*
* Example properties file:
*
* <pre class="code"> driver=com.mysql.jdbc.Driver
* dbname=mysql:mydb</pre>
*
* Annotated bean definitions may take advantage of property replacement using
* the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
*
*<pre class="code">@Value("${person.age}")</pre>
*
* Implementations check simple property values, lists, maps, props, and bean names
* in bean references. Furthermore, placeholder values can also cross-reference
* other placeholders, like:
*
*<pre class="code">rootPath=myrootdir
*subPath=${rootPath}/subdir</pre>
*
* In contrast to {@link PropertyOverrideConfigurer}, subclasses of this type allow
* filling in of explicit placeholders in bean definitions.
*
* <p>If a configurer cannot resolve a placeholder, a {@link BeanDefinitionStoreException}
* will be thrown. If you want to check against multiple properties files, specify multiple
* resources via the {@link #setLocations locations} property. You can also define multiple
* configurers, each with its <em>own</em> placeholder syntax. Use {@link
* #ignoreUnresolvablePlaceholders} to intentionally suppress throwing an exception if a
* placeholder cannot be resolved.
*
* <p>Default property values can be defined globally for each configurer instance
* via the {@link #setProperties properties} property, or on a property-by-property basis
* using the default value separator which is {@code ":"} by default and
* customizable via {@link #setValueSeparator(String)}.
*
* <p>Example XML property with default value:
*
*<pre class="code">{@code
* <property name="url" value="jdbc:}${dbname:defaultdb}{@code"/>
*}</pre>
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see PropertyPlaceholderConfigurer
* @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
*/
public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyResourceConfigurer
implements BeanNameAware, BeanFactoryAware {
/** Default placeholder prefix: "${" */
/** Default placeholder prefix: {@value} */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
/** Default placeholder suffix: "}" */
/** Default placeholder suffix: {@value} */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
/** Default value separator: ":" */
/** Default value separator: {@value} */
public static final String DEFAULT_VALUE_SEPARATOR = ":";
/** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
/** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
/** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
protected boolean ignoreUnresolvablePlaceholders = false;
@@ -60,12 +121,14 @@ public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyReso
private BeanFactory beanFactory;
/**
* Return the {@code PlaceholderResolver} for this configurer.
*/
protected abstract PlaceholderResolver getPlaceholderResolver(Properties props);
/**
* Set the prefix that a placeholder string starts with.
* The default is "${".
* @see #DEFAULT_PLACEHOLDER_PREFIX
* The default is {@value #DEFAULT_PLACEHOLDER_PREFIX}.
*/
public void setPlaceholderPrefix(String placeholderPrefix) {
this.placeholderPrefix = placeholderPrefix;
@@ -73,8 +136,7 @@ public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyReso
/**
* Set the suffix that a placeholder string ends with.
* The default is "}".
* @see #DEFAULT_PLACEHOLDER_SUFFIX
* The default is {@value #DEFAULT_PLACEHOLDER_SUFFIX}.
*/
public void setPlaceholderSuffix(String placeholderSuffix) {
this.placeholderSuffix = placeholderSuffix;
@@ -82,22 +144,22 @@ public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyReso
/**
* Specify the separating character between the placeholder variable
* and the associated default value, or <code>null</code> if no such
* and the associated default value, or {@code null} if no such
* special character should be processed as a value separator.
* The default is ":".
* The default is {@value #DEFAULT_VALUE_SEPARATOR}.
*/
public void setValueSeparator(String valueSeparator) {
this.valueSeparator = valueSeparator;
}
/**
* Set a value that should be treated as <code>null</code> when
* Set a value that should be treated as {@code null} when
* resolved as a placeholder value: e.g. "" (empty String) or "null".
* <p>Note that this will only apply to full property values,
* not to parts of concatenated values.
* <p>By default, no such null value is defined. This means that
* there is no way to express <code>null</code> as a property
* value unless you explictly map a corresponding value here.
* there is no way to express {@code null} as a property
* value unless you explicitly map a corresponding value here.
*/
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
@@ -139,6 +201,10 @@ public abstract class AbstractPropertyPlaceholderConfigurer extends PropertyReso
}
/**
* Visit each bean definition in the given bean factory and attempt to replace ${...} property
* placeholders with values from the given properties.
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@@ -25,69 +25,40 @@ import org.springframework.core.Constants;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
/**
* A property resource configurer that resolves placeholders in bean property values of
* context definitions. It <i>pulls</i> values from a properties file into bean definitions.
* {@link AbstractPropertyPlaceholderConfigurer} subclass that resolves ${...} placeholders
* against {@link #setLocation local} {@link #setProperties properties} and/or system properties
* and environment variables.
*
* <p>The default placeholder syntax follows the Ant / Log4J / JSP EL style:
* <p>As of Spring 3.1, {@link org.springframework.context.support.PropertySourcesPlaceholderConfigurer
* PropertySourcesPlaceholderConfigurer} should be used preferentially over this implementation; it is
* more flexible through taking advantage of the {@link org.springframework.core.env.Environment Environment} and
* {@link org.springframework.core.env.PropertySource PropertySource} mechanisms also made available in Spring 3.1.
*
* <pre class="code">${...}</pre>
* <p>{@link PropertyPlaceholderConfigurer} is still appropriate for use when:
* <ul>
* <li>the {@link org.springframework.context spring-context} module is not available (i.e., one is using
* Spring's {@code BeanFactory} API as opposed to {@code ApplicationContext}).
* <li>existing configuration makes use of the {@link #setSystemPropertiesMode(int) "systemPropertiesMode"} and/or
* {@link #setSystemPropertiesModeName(String) "systemPropertiesModeName"} properties. Users are encouraged to move
* away from using these settings, and rather configure property source search order through the container's
* {@code Environment}; however, exact preservation of functionality may be maintained by continuing to
* use {@code PropertyPlaceholderConfigurer}.
* </ul>
*
* Example XML context definition:
*
* <pre class="code">&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
* &lt;property name="driverClassName"&gt;&lt;value&gt;${driver}&lt;/value&gt;&lt;/property&gt;
* &lt;property name="url"&gt;&lt;value&gt;jdbc:${dbname}&lt;/value&gt;&lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* Example properties file:
*
* <pre class="code">driver=com.mysql.jdbc.Driver
* dbname=mysql:mydb</pre>
*
* PropertyPlaceholderConfigurer checks simple property values, lists, maps,
* props, and bean names in bean references. Furthermore, placeholder values can
* also cross-reference other placeholders, like:
*
* <pre class="code">rootPath=myrootdir
* subPath=${rootPath}/subdir</pre>
*
* In contrast to PropertyOverrideConfigurer, this configurer allows to fill in
* explicit placeholders in context definitions. Therefore, the original definition
* cannot specify any default values for such bean properties, and the placeholder
* properties file is supposed to contain an entry for each defined placeholder.
*
* <p>If a configurer cannot resolve a placeholder, a BeanDefinitionStoreException
* will be thrown. If you want to check against multiple properties files, specify
* multiple resources via the "locations" setting. You can also define multiple
* PropertyPlaceholderConfigurers, each with its <i>own</i> placeholder syntax.
*
* <p>Default property values can be defined via "properties", to make overriding
* definitions in properties files optional. A configurer will also check against
* system properties (e.g. "user.dir") if it cannot resolve a placeholder with any
* of the specified properties. This can be customized via "systemPropertiesMode".
*
* <p>Note that the context definition <i>is</i> aware of being incomplete;
* this is immediately obvious to users when looking at the XML definition file.
* Hence, placeholders have to be resolved; any desired defaults have to be
* defined as placeholder values as well (for example in a default properties file).
*
* <p>Property values can be converted after reading them in, through overriding
* the {@link #convertPropertyValue} method. For example, encrypted values can
* be detected and decrypted accordingly before processing them.
* <p>Prior to Spring 3.1, the {@code <context:property-placeholder/>} namespace element
* registered an instance of {@code PropertyPlaceholderConfigurer}. It will still do so if
* using the {@code spring-beans-3.0.xsd} definition of the namespace. That is, you can preserve
* registration of {@code PropertyPlaceholderConfigurer} through the namespace, even if using Spring 3.1;
* simply do not update your {@code xsi:schemaLocation} and continue using the 3.0 XSD.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 02.10.2003
* @see #setLocations
* @see #setProperties
* @see #setPlaceholderPrefix
* @see #setPlaceholderSuffix
* @see #setSystemPropertiesModeName
* @see System#getProperty(String)
* @see #convertPropertyValue
* @see AbstractPropertyPlaceholderConfigurer
* @see PropertyOverrideConfigurer
* @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
*/
public class PropertyPlaceholderConfigurer extends AbstractPropertyPlaceholderConfigurer
implements BeanNameAware, BeanFactoryAware {

View File

@@ -55,15 +55,24 @@ public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
/**
* Set the order value of this object for sorting purposes.
* @see PriorityOrdered
*/
public void setOrder(int order) {
this.order = order;
this.order = order;
}
public int getOrder() {
return this.order;
return this.order;
}
/**
* {@linkplain #mergeProperties Merge}, {@linkplain #convertProperties convert} and
* {@linkplain #processProperties process} properties against the given bean factory.
* @throws BeanInitializationException if any properties cannot be loaded
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
@@ -88,7 +97,7 @@ public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
* @see #processProperties
*/
protected void convertProperties(Properties props) {
Enumeration propertyNames = props.propertyNames();
Enumeration<?> propertyNames = props.propertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String) propertyNames.nextElement();
String propertyValue = props.getProperty(propertyName);

View File

@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
* and the class loader to use for loading bean classes.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 11.12.2003
* @see BeanDefinitionReaderUtils
*/
@@ -140,16 +141,14 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
}
/**
* TODO SPR-7508: document
* @param environment
* Set the Environment to use when reading bean definitions. Most often used
* for evaluating profile information to determine which bean definitions
* should be read and which should be omitted.
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* TODO SPR-7508: document
*/
public Environment getEnvironment() {
return this.environment;
}

View File

@@ -70,7 +70,6 @@ import org.springframework.core.NamedThreadLocal;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -170,8 +169,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
* Create a new AbstractBeanFactory.

View File

@@ -33,8 +33,6 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.DefaultEnvironment;
import org.springframework.util.StringUtils;
/**
@@ -61,9 +59,6 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
/** Map from bean name to bean instance */
private final Map<String, Object> beans = new HashMap<String, Object>();
/** TODO SPR-7508: document */
private ConfigurableEnvironment environment = new DefaultEnvironment();
/**
* Add a new singleton bean.

View File

@@ -16,9 +16,10 @@
package org.springframework.beans.factory.xml;
import org.w3c.dom.Document;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.core.env.Environment;
import org.w3c.dom.Document;
/**
* SPI for parsing an XML document that contains Spring bean definitions.
@@ -46,4 +47,11 @@ public interface BeanDefinitionDocumentReader {
void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
throws BeanDefinitionStoreException;
/**
* Set the Environment to use when reading bean definitions. Used for evaluating
* profile information to determine whether a {@code <beans/>} document/element should
* be included or omitted.
*/
void setEnvironment(Environment environment);
}

View File

@@ -1476,7 +1476,7 @@ public class BeanDefinitionParserDelegate {
/**
* Determine whether the name of the supplied node is equal to the supplied name.
* <p>The default implementation checks the supplied desired name against both
* {@link Node#getNodeName()) and {@link Node#getLocalName()}.
* {@link Node#getNodeName()} and {@link Node#getLocalName()}.
* <p>Subclasses may override the default implementation to provide a different
* mechanism for comparing node names.
* @param node the node to compare

View File

@@ -38,6 +38,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
@@ -88,18 +89,21 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
/**
* TODO SPR-7508: document
* @param environment
* {@inheritDoc}
* <p>Default value is {@code null}; property is required for parsing any
* {@code <beans/>} element with a {@code profile} attribute present.
* @see #doRegisterBeanDefinitions
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Parses bean definitions according to the "spring-beans" DTD. TODO SPR-7508 XSD
* {@inheritDoc}
* <p>This implementation parses bean definitions according to the "spring-beans" XSD
* (or DTD, historically).
* <p>Opens a DOM Document; then initializes the default settings
* specified at <code>&lt;beans&gt;</code> level; then parses
* the contained bean definitions.
* specified at the {@code <beans/>} level; then parses the contained bean definitions.
*/
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
@@ -110,17 +114,24 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
doRegisterBeanDefinitions(root);
}
/**
* Register each bean definition within the given root {@code <beans/>} element.
* @throws IllegalStateException if {@code <beans profile="..."} attribute is present
* and Environment property has not been set
* @see #setEnvironment
*/
protected void doRegisterBeanDefinitions(Element root) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
Assert.state(this.environment != null, "environment property must not be null");
String[] specifiedProfiles = commaDelimitedListToStringArray(trimAllWhitespace(profileSpec));
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
// TODO SPR-7508: log that this bean is being rejected on profile mismatch
return;
}
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
// TODO SPR-7508: log that this bean is being rejected on profile mismatch
return;
}
}
// any nested <beans> elements will cause recursion in this method. in
// any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
@@ -212,7 +223,7 @@ public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocume
}
// Resolve system properties: e.g. "${user.dir}"
location = environment.resolveRequiredPlaceholders(location);
location = environment.getPropertyResolver().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

View File

@@ -487,12 +487,8 @@ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
* @see BeanDefinitionDocumentReader#registerBeanDefinitions
*/
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// Read document based on new BeanDefinitionDocumentReader SPI. // TODO SPR-7508: polish - remove comment
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// TODO SPR-7508: remove ugly cast
if (documentReader instanceof DefaultBeanDefinitionDocumentReader) {
((DefaultBeanDefinitionDocumentReader)documentReader).setEnvironment(this.getEnvironment());
}
documentReader.setEnvironment(this.getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2011 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.
@@ -19,7 +19,6 @@ package org.springframework.beans.factory.xml;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.Resource;
/**
@@ -35,7 +34,8 @@ import org.springframework.core.io.Resource;
* <p>This class registers each bean definition with the {@link DefaultListableBeanFactory}
* superclass, and relies on the latter's implementation of the {@link BeanFactory} interface.
* It supports singletons, prototypes, and references to either of these kinds of bean.
* See "spring-beans-2.0.dtd" for details on options and configuration style. // TODO SPR-7508 polish - s/dtd/xsd/
* See {@code "spring-beans-3.x.xsd"} (or historically, {@code "spring-beans-2.0.dtd"}) for
* details on options and configuration style.
*
* <p><b>For advanced needs, consider using a {@link DefaultListableBeanFactory} with
* an {@link XmlBeanDefinitionReader}.</b> The latter allows for reading from multiple XML
@@ -63,7 +63,7 @@ public class XmlBeanFactory extends DefaultListableBeanFactory {
* @throws BeansException in case of loading or parsing errors
*/
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, (BeanFactory)null);
this(resource, null);
}
/**

View File

@@ -36,8 +36,6 @@
There is also support for lists, sets, maps, and java.util.Properties
as bean property types or constructor argument types.
TODO:SPR-7508: Document use of nested beans elements.
]]></xsd:documentation>
</xsd:annotation>
@@ -63,8 +61,11 @@
<xsd:element name="beans">
<xsd:annotation>
<xsd:documentation><![CDATA[
The top level (typically root) element. Allows the definition
of default values for all nested bean definitions.
Container for <bean> and other elements, typically the root element in the document.
Allows the definition of default values for all nested bean definitions. May itself
be nested for the purpose of defining a subset of beans with certain default values or
to be registered only when certain profile(s) are active. Any such nested <beans> element
must be declared as the last element in the document.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
@@ -81,16 +82,20 @@
<xsd:attribute name="profile" use="optional" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
TODO:SPR-7508: Document profile annotation:
* may be comma-delimited
* empty profile means beans will always be registered
* ConfigurableEnvironment.setActiveProfiles(String...) sets which profiles are active
* 'spring.profile.active' sets which profiles are active (typically as a -D system property)
servlet context/init param)
* ConfigurableEnvironment.setDefaultProfiles(String...) or 'spring.profile.default' property specifies one
or more default profiles, e.g., 'default'
* if 'default' is specified as a default profile, `profile="xyz,default"` means that beans will be
registered if 'xyz' is active or if no profile is active
The set of profiles for which this <beans> element may be parsed. May be a comma-delimited
list in the case of multiple profiles. If one or more of the specified profiles are active at time
of parsing, the <beans> element will be parsed, and all of its <bean> elements registered,
&lt;import&gt; elements followed, etc. If none of the specified profiles are active at time of parsing,
then the entire element and its contents will be ignored.
Profiles are activated in one of two ways:
Programmatic:
ConfigurableEnvironment#setActiveProfiles(String...)
ConfigurableEnvironment#setDefaultProfiles(String...)
Properties (typically through -D system properties, environment variables, or servlet context init params):
spring.profile.active=p1,p2
spring.profile.default=p1,p2
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -115,7 +120,7 @@
<xsd:annotation>
<xsd:documentation><![CDATA[
The default 'autowire' value; see the documentation for the
'autowire' attribute of the 'bean' element. The default is 'no'.
'autowire' attribute of the 'bean' element. The default is 'default'.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>

View File

@@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
@@ -33,13 +34,16 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import test.beans.TestBean;
/**
* Unit tests for {@link EnvironmentAwarePropertyPlaceholderConfigurer}.
* Unit tests for {@link PropertyPlaceholderConfigurer}.
*
* @see PropertySourcesPlaceholderConfigurerTests
* @see PropertyResourceConfigurerTests
* @author Chris Beams
*/
@@ -50,7 +54,7 @@ public class PropertyPlaceholderConfigurerTests {
private static final String P1_SYSTEM_ENV_VAL = "p1SystemEnvVal";
private DefaultListableBeanFactory bf;
private AbstractPropertyPlaceholderConfigurer ppc;
private PropertyPlaceholderConfigurer ppc;
private Properties ppcProperties;
private AbstractBeanDefinition p1BeanDef;
@@ -79,9 +83,19 @@ public class PropertyPlaceholderConfigurerTests {
}
// -------------------------------------------------------------------------
// Tests to ensure backward-compatibility for Environment refactoring
// -------------------------------------------------------------------------
@Test
public void localPropertiesViaResource() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean",
genericBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
PropertyPlaceholderConfigurer pc = new PropertyPlaceholderConfigurer();
Resource resource = new ClassPathResource("PropertyPlaceholderConfigurerTests.properties", this.getClass());
pc.setLocation(resource);
pc.postProcessBeanFactory(bf);
}
@Test
public void resolveFromSystemProperties() {
@@ -115,7 +129,6 @@ public class PropertyPlaceholderConfigurerTests {
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
}
/*
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemProperties() {
registerWithGeneratedName(p1BeanDef, bf);
@@ -145,7 +158,6 @@ public class PropertyPlaceholderConfigurerTests {
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL)); // has to resort to local props
}
*/
/**
* Creates a scenario in which two PPCs are configured, each with different
@@ -231,34 +243,6 @@ public class PropertyPlaceholderConfigurerTests {
}
// -------------------------------------------------------------------------
// Tests for functionality not possible prior to Environment refactoring
// -------------------------------------------------------------------------
/**
* Tests that properties against a BeanFactory's Environment are used by
* PropertyPlaceholderConfigurer during placeholder resolution.
@Test @SuppressWarnings({ "unchecked", "rawtypes", "serial" })
public void replacePlaceholdersFromBeanFactoryEnvironmentPropertySources() {
System.setProperty("key1", "systemValue");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.getEnvironment().addPropertySource("psCustom", new HashMap() {{ put("key1", "customValue"); }});
bf.registerBeanDefinition("testBean",
rootBeanDefinition(TestBean.class).addPropertyValue("name", "${key1}").getBeanDefinition());
new PropertyPlaceholderConfigurer().postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), is("customValue"));
System.clearProperty("key1");
}
*/
// -------------------------------------------------------------------------
// Utilities
// -------------------------------------------------------------------------
// TODO SPR-7508: duplicated from EnvironmentPropertyResolutionSearchTests
@SuppressWarnings("unchecked")
private static Map<String, String> getModifiableSystemEnvironment() {

View File

@@ -800,7 +800,7 @@ public final class PropertyResourceConfigurerTests {
Preferences.systemRoot().node("mySystemPath/mypath").remove("myName");
}
/* TODO SPR-7508: uncomment after EnvironmentAwarePropertyPlaceholderConfigurer implementation
/* TODO SPR-7508: uncomment after PropertySourcesPlaceholderConfigurer implementation
@Test
public void testPreferencesPlaceholderConfigurerWithCustomPropertiesInEnvironment() {
factory.registerBeanDefinition("tb",