In the first II posts of this series, I described the bean definition Profiles feature, and what it relates to th E Environment
abstraction New in Spring 3.1 M1. Today We ll take a look at a second aspect of the Environment
–how it helps simplify the concern of the configuration property mana Gement.
Understanding Property Sources
Spring ' s Environment
abstraction provides search operations over a configurable hierarchy of property sources. To explain fully, consider the following:
ApplicationContextAt= New Genericapplicationcontext (); environment env = ctx< Span class= "pun". getenvironment (); boolean Containsfoo = env containsproperty ( "foo" system.. Println ( "Does my environment contain the ' Foo ' property?" + Containsfoo
In the snippet above, we see a high-level to asking Spring whether the ' Foo ' property was defined for the current EN Vironment. To answer the question, the Environment
object performs a search over a set of Pro Pertysource
objects. a Propertysource
is A simple abstraction over any source of key-value pairs, and Spring ' S defaultenvironment is configured with two Propertysource
objects–one Representing the set of JVM system Properties (a la system.getproperties ()
) and one representing the set of system environment variables (a la system.getenv ()
) [1]. This means. If a ' Foo ' system property or ' foo ' environment variable was present at runtime, the call to env . Containsproperty ("foo")
would return true
.
The search performed is hierarchical. By default, System properties has precedence over environment variables, so if the ' Foo ' property happens to is set in Bo Th places during a call env.getProperty(“foo”)
to, the system property value would ' win ' and be returned preferentially over the environment Variable.
Most importantly, the entire mechanism is configurable. Perhaps you has a custom source of properties that is you ' d as to integrate into this search. No problem–simply implement and instantiate your own and add it to the set of the current PropertySource
PropertySources
Environment
:
configurableapplicationcontext= new Genericapplicationcontextmutablepropertysources sources = Ctxgetenvironment (). . Addfirst (new mypropertysource
In the code above, have MyPropertySource
been added with highest precedence in the search. If it contains a ' Foo ' property, it'll be detected and returned ahead of any of the ' Foo ' property in any other PropertySource
. The API exposes a number of methods that allow for precise manipulation of the set of property MutablePropertySources
sources. Explore the Javadoc for full details.
Putting property sources to use
Now so you understand the basics's property sources and their relationship Environment
to the, you might is wondering how all Of this was relevant to you as a developer of Spring applications. Let's consider a couple of scenarios and see how it's all comes together.
Scenario 1: ${placeholder}
resolution in
statements
You had a set of Spring configuration files that configure beans specific to certain customers of your application, and Y ou conditionally load those files using
statements containing a placeholder resolving to the value of a ' customer ' PR Operty:
<beans><import resource="com/bank/service/${customer}-config.xml"/></beans>
Prior to Spring 3.1, the value of placeholders in
elements could is resolved only against JVM system properties or en Vironment variables[2]. No longer is the case. Because Environment
The abstraction is integrated throughout the container, it's easy to route resolution of placeholders through It. This means, configure the resolution process in any of the like:change the precedence of searching s Ystem Properties and environment variables, or remove them entirely; Add your own property sources to the mix as appropriate.
Scenario 2: ${placeholder}
resolution in bean definitions
Most Spring users would be familiar with the use of PropertyPlaceholderConfigurer
or to <context:property-placeholder/>
replace ${…}
placeholders in Spring bean definitions. Here is a typical configuration:
<context:property-placeholder Location="Com/bank/config/datasource.properties"/><bean Id="DataSource" Class="Org.apache.commons.dbcp.BasicDataSource" Destroy-method="Close"><property Name="Driverclass" Value="${database.driver}"/><property name= "Jdbcurl" value< Span class= "pun" >= "${database.url}" /><property name= " Username " value=" ${database.username} " span class= "tag" >/><property name< Span class= "pun" >= "password" value= "${database.password}" /></bean>
As of Spring 3.1, the <context:property-placeholder/>
no longer registers a PropertyPlaceholderConfigurer
, but rather a PropertySourcesPlaceholderConfigurer
[3]. This component still looks datasource.properties
to the file to Reslove ${database.*}
the placeholders above, but would fall back to the set of for the current if the properties is not a found in the Environment
file. Again This gives your more control; Prior to this change, the only fallback options were system properties and environment variables.
Manipulating property sources in a Web application
So far we ' ve seen what to access and manipulate property sources in a standalone application where we have programmatic ACC ESS to an ApplicationContext
. In reality, however, many spring applications be webapps in which the was managed for your by ApplicationContext
Spring ' s ContextLoaderListener
. For this reason we ' ve introduced ApplicationContextInitializer
the interface and its companion, the servlet context param. T contextInitializerClasses
Ake a look:
web.xml
<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.bank.MyInitializer</param-value></context-param>
Public Class Myinitializer Implements Applicationcontextinitializer<Configurablewebapplicationcontext> {Public voidInitialize (configurablewebapplicationcontext Ctx) {propertysource PS Span class= "pun" >= new mypropertysource< Span class= "pun" > (); ctx. (). Getpropertysources (). Addfirstps//perform any other initialization of the context ... }} /span>
Implementing and registering an provides a simple-to- ApplicationContextInitializer
interact with your application context before it's ref Reshed. This was a perfect place-to-manipulate property sources, but you could also call or any other setConfigLocations(…)
method designed to be C alled prior to refresh()
.
Summary
Spring ' s Environment
abstraction provides a single location to configure both profiles andproperties. Profiles, as described in earlier posts, determine which bean definitions should is registered for a given deployment cont Ext The property is described in this post provides a consistent abstraction over any source of properties, resulting in More flexible property access and placeholder resolution throughout your application configuration.
In the next post in this series we'll take a look at how Spring 3.1 makes 100% java-based (read:xml-free) application con Figuration a reality FeatureSpecification
with Support–an natural evolution out of the @Configuration
class support introduced in Sprin G 3.0.
Footnotes
[1]: These default property sources DefaultEnvironment
was present for, a for use in standalone applications. was DefaultWebEnvironment
populated with add Itional default property sources including Servlet config and servlet context parameters. DefaultPortletEnvironment
similarly have access to Portlet Config and portlet context parameters as property sources. Both can optionally enable a JndiPropertySource
. See Javadoc for details.
[2]: Because processing of elements necessarily occurs before beanfactorypostprocessors
is Invoked, meaning that even propertyplaceholderconfigurer
could don't help here. Because the Environment
and its set of propertysources
are configured Before container refresh, placeholders in elements can be resolved against the Environment
Without any lifecycle issues.
[3]: In certain cases, would <context:property-placeholder/>
still register a PropertyPlaceholderConfigurer
. spring-context
in the 3.1 version of the schema, the system-properties-mode
attribute have been removed from the property-placeholder
element. This is because the attribute no longer makes sense in a PropertySources
-/ Environment
-aware world. However, if you build against Spring 3.1 but still use spring-context-3.0.xsd
the schema and set system-properties-mode
the attribute, would <context:property-placeholder>
revert to re Gistering A in PropertyPlaceholderConfigurer
order to honor the exact semantics of this setting. This approach preserves backward compatibility in any case.
Spring 3.1 m1:unified Property Management (EXT)