Your typical enterprise application is not made up of a single object (or bean in the Spring parlance). Even the simplest of applications will no doubt have at least a handful of objects that work together to present what the end-user sees as a coherent application. This next section explains how you go from defining a number of bean definitions that stand-alone, each to themselves, to a fully realized application where objects work (or collaborate) together to achieve some goal (usually an application that does what the end-user wants).
The basic principle behind Dependency Injection (DI) is that objects define their dependencies (that is to say the other objects they work with) only through constructor arguments, arguments to a factory method, or properties which are set on the object instance after it has been constructed or returned from a factory method. Then, it is the job of the container to actually inject those dependencies when it creates the bean. This is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself being in control of instantiating or locating its dependencies on its own using direct construction of classes, or something like the Service Locator pattern.
It becomes evident upon usage that code gets much cleaner when the DI principle is applied, and reaching a higher grade of decoupling is much easier when objects do not look up their dependencies, but are provided with them (and additionally do not even know where the dependencies are located and of what concrete class they are). DI exists in two major variants, namely Constructor Injection and Setter Injection.
Constructor-based DI is effected by
invoking a constructor with a number of arguments, each representing a
dependency. Additionally, calling a static factory
method with specific arguments to construct the bean, can be
considered almost equivalent, and the rest of this text will consider
arguments to a constructor and arguments to a
static factory method similarly. Find below an
example of a class that could only be dependency injected using
constructor injection. Notice that there is nothing
special about this class.
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on a MovieFinder private MovieFinder movieFinder; // a constructor so that the Spring container can 'inject' a MovieFinder public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually 'uses' the injected MovieFinder is omitted... }
Constructor argument resolution matching occurs using the argument's type. If there is no potential for ambiguity in the constructor arguments of a bean definition, then the order in which the constructor arguments are defined in a bean definition is the order in which those arguments will be supplied to the appropriate constructor when it is being instantiated. Consider the following class:
package x.y; public class Foo { public Foo(Bar bar, Baz baz) { // ... } }
There is no potential for ambiguity here (assuming of course
that Bar and Baz
classes are not related in an inheritance hierarchy). Thus the
following configuration will work just fine, and you do not need to
specify the constructor argument indexes and / or types
explicitly.
<beans> <bean name="foo" class="x.y.Foo"> <constructor-arg> <bean class="x.y.Bar"/> </constructor-arg> <constructor-arg> <bean class="x.y.Baz"/> </constructor-arg> </bean> </beans>
When another bean is referenced, the type is known, and
matching can occur (as was the case with the preceding example).
When a simple type is used, such as
<value>true<value>, Spring cannot
determine the type of the value, and so cannot match by type without
help. Consider the following class:
package examples; public class ExampleBean { // No. of years to the calculate the Ultimate Answer private int years; // The Answer to Life, the Universe, and Everything private String ultimateAnswer; public ExampleBean(int years, String ultimateAnswer) { this.years = years; this.ultimateAnswer = ultimateAnswer; } }
The above scenario can use type
matching with simple types by explicitly specifying the type of
the constructor argument using the 'type'
attribute. For example:
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
Constructor arguments can have their index specified
explicitly by use of the index attribute. For
example:
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
As well as solving the ambiguity problem of multiple simple values, specifying an index also solves the problem of ambiguity where a constructor may have two arguments of the same type. Note that the index is 0 based.
Setter-based DI is realized by calling
setter methods on your beans after invoking a no-argument constructor
or no-argument static factory method to instantiate
your bean.
Find below an example of a class that can only be dependency injected using pure setter injection. Note that there is nothing special about this class... it is plain old Java.
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on the MovieFinder private MovieFinder movieFinder; // a setter method so that the Spring container can 'inject' a MovieFinder public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually 'uses' the injected MovieFinder is omitted... }
The BeanFactory supports both of
these variants for injecting dependencies into beans it manages. (It
in fact also supports injecting setter-based dependencies after some
dependencies have already been supplied via the constructor approach.)
The configuration for the dependencies comes in the form of a
BeanDefinition, which is used together
with PropertyEditor instances to know
how to convert properties from one format to another. However, most
users of Spring will not be dealing with these classes directly (that
is programmatically), but rather with an XML definition file which
will be converted internally into instances of these classes, and used
to load an entire Spring IoC container instance.
Bean dependency resolution generally happens as follows:
The BeanFactory is created
and initialized with a configuration which describes all the
beans. (Most Spring users use a
BeanFactory or
ApplicationContext implementation
that supports XML format configuration files.)
Each bean has dependencies expressed in the form of properties, constructor arguments, or arguments to the static-factory method when that is used instead of a normal constructor. These dependencies will be provided to the bean, when the bean is actually created.
Each property or constructor argument is either an actual definition of the value to set, or a reference to another bean in the container.
Each property or constructor argument which is a value must be
able to be converted from whatever format it was specified in, to
the actual type of that property or constructor argument. By
default Spring can convert a value supplied in string format to
all built-in types, such as int,
long, String,
boolean, etc.
The Spring container validates the configuration of each bean as
the container is created, including the validation that properties
which are bean references are actually referring to valid beans.
However, the bean properties themselves are not set until the bean
is actually created. For those beans that are
singleton-scoped and set to be pre-instantiated (such as singleton
beans in an ApplicationContext),
creation happens at the time that the container is created, but
otherwise this is only when the bean is requested. When a bean
actually has to be created, this will potentially cause a graph of
other beans to be created, as its dependencies and its dependencies'
dependencies (and so on) are created and assigned.
You can generally trust Spring to do the right thing. It will
detect misconfiguration issues, such as references to non-existent
beans and circular dependencies, at container load-time. It will
actually set properties and resolve dependencies as late as possible,
which is when the bean is actually created. This means that a Spring
container which has loaded correctly can later generate an exception
when you request a bean if there is a problem creating that bean or
one of its dependencies. This could happen if the bean throws an
exception as a result of a missing or invalid property, for example.
This potentially delayed visibility of some configuration issues is
why ApplicationContext implementations
by default pre-instantiate singleton beans. At the cost of some
upfront time and memory to create these beans before they are actually
needed, you find out about configuration issues when the
ApplicationContext is created, not
later. If you wish, you can still override this default behavior and
set any of these singleton beans to lazy-initialize (that is not be
pre-instantiated).
If no circular dependencies are involved (see sidebar for a discussion of circular dependencies), when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being passed (via one of the DI flavors) to the dependent bean. This means that if bean A has a dependency on bean B, the Spring IoC container will totally configure bean B prior to invoking the setter method on bean A; you can read 'totally configure' to mean that the bean will be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevant lifecycle methods (such as a configured init method or the IntializingBean callback method) will all be invoked.
First, an example of using XML-based configuration metadata for setter-based DI. Find below a small part of a Spring XML configuration file specifying some bean definitions.
<bean id="exampleBean" class="examples.ExampleBean"> <!-- setter injection using the nested <ref/> element --> <property name="beanOne"><ref bean="anotherExampleBean"/></property> <!-- setter injection using the neater 'ref' attribute --> <property name="beanTwo" ref="yetAnotherBean"/> <property name="integerProperty" value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public void setBeanOne(AnotherBean beanOne) { this.beanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) { this.beanTwo = beanTwo; } public void setIntegerProperty(int i) { this.i = i; } }
As you can see, setters have been declared to match against the properties specified in the XML file. Find below an example of using constructor-based DI.
<bean id="exampleBean" class="examples.ExampleBean"> <!-- constructor injection using the nested <ref/> element --> <constructor-arg> <ref bean="anotherExampleBean"/> </constructor-arg> <!-- constructor injection using the neater 'ref' attribute --> <constructor-arg ref="yetAnotherBean"/> <constructor-arg type="int" value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public ExampleBean( AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { this.beanOne = anotherBean; this.beanTwo = yetAnotherBean; this.i = i; } }
As you can see, the constructor arguments specified in the bean
definition will be used to pass in as arguments to the constructor of
the ExampleBean.
Now consider a variant of this where instead of using a
constructor, Spring is told to call a static
factory method to return an instance of the object:
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance"> <constructor-arg ref="anotherExampleBean"/> <constructor-arg ref="yetAnotherBean"/> <constructor-arg value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean { // a private constructor private ExampleBean(...) { ... } // a static factory method; the arguments to this method can be // considered the dependencies of the bean that is returned, // regardless of how those arguments are actually used. public static ExampleBean createInstance ( AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { ExampleBean eb = new ExampleBean (...); // some other operations... return eb; } }
Note that arguments to the static factory
method are supplied via <constructor-arg/>
elements, exactly the same as if a constructor had actually been used.
Also, it is important to realize that the type of the class being
returned by the factory method does not have to be of the same type as
the class which contains the static factory method,
although in this example it is. An instance (non-static) factory
method would be used in an essentially identical fashion (aside from
the use of the factory-bean attribute instead of
the class attribute), so details will not be
discussed here.
As mentioned in the previous section, bean properties and
constructor arguments can be defined as either references to other
managed beans (collaborators), or values defined inline. Spring's
XML-based configuration metadata supports a number of sub-element types
within its <property/> and
<constructor-arg/> elements for just this
purpose.
The <value/> element specifies a
property or constructor argument as a human-readable string
representation. As mentioned
previously, JavaBeans PropertyEditors are
used to convert these string values from a
String to the actual type of the property or
argument.
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- results in a setDriverClassName(String) call --> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/mydb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>masterkaoli</value> </property> </bean>
The <property/> and
<constructor-arg/> elements also support the
use of the 'value' attribute, which can lead to
much more succinct configuration. When using the
'value' attribute, the above bean definition reads
like so:
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- results in a setDriverClassName(String) call --> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mydb"/> <property name="username" value="root"/> <property name="password" value="masterkaoli"/> </bean>
The Spring team generally prefer the attribute style over the
use of nested <value/> elements. If you are
reading this reference manual straight through from top to bottom
(wow!) then we are getting slightly ahead of ourselves here, but you
can also configure a java.util.Properties
instance like so:
<bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <!-- typed as a java.util.Properties --> <property name="properties"> <value> jdbc.driver.className=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mydb </value> </property> </bean>
Can you see what is happening? The Spring container is
converting the text inside the <value/>
element into a java.util.Properties instance
using the JavaBeans PropertyEditor
mechanism. This is a nice shortcut, and is one of a few places where
the Spring team do favor the use of the nested
<value/> element over the
'value' attribute style.
The idref element is simply an error-proof
way to pass the id of another bean in the
container (to a <constructor-arg/> or
<property/> element).
<bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean" /> </property> </bean>
The above bean definition snippet is exactly equivalent (at runtime) to the following snippet:
<bean id="theTargetBean" class="..." /> <bean id="client" class="..."> <property name="targetName" value="theTargetBean" /> </bean>
The main reason the first form is preferable to the second is
that using the idref tag allows the container to
validate at deployment time that the
referenced, named bean actually exists. In the second variation, no
validation is performed on the value that is passed to the
'targetName' property of the
'client' bean. Any typo will only be discovered
(with most likely fatal results) when the
'client' bean is actually instantiated. If the
'client' bean is a prototype bean, this typo (and
the resulting exception) may only be discovered long after the
container is actually deployed.
Additionally, if the bean being referred to is in the same XML
unit, and the bean name is the bean id, the
'local' attribute may be used, which allows the
XML parser itself to validate the bean id even earlier, at XML
document parse time.
<property name="targetName"> <!-- a bean with an id of 'theTargetBean' must exist; otherwise an XML exception will be thrown --> <idref local="theTargetBean"/> </property>
By way of an example, one common place (at least in pre-Spring
2.0 configuration) where the <idref/> element brings value is
in the configuration of AOP
interceptors in a ProxyFactoryBean
bean definition. If you use <idref/> elements when specifying
the interceptor names, there is no chance of inadvertently
misspelling an interceptor id.
The ref element is the final element allowed
inside a <constructor-arg/> or
<property/> definition element. It is used to
set the value of the specified property to be a reference to another
bean managed by the container (a collaborator). As mentioned in a
previous section, the referred-to bean is considered to be a
dependency of the bean who's property is being set, and will be
initialized on demand as needed (if it is a singleton bean it may have
already been initialized by the container) before the property is set.
All references are ultimately just a reference to another object, but
there are 3 variations on how the id/name of the other object may be
specified, which determines how scoping and validation is
handled.
Specifying the target bean by using the bean
attribute of the <ref/> tag is the most
general form, and will allow creating a reference to any bean in the
same container (whether or not in the same XML file), or parent
container. The value of the 'bean' attribute may be
the same as either the 'id' attribute of the target
bean, or one of the values in the 'name' attribute
of the target bean.
<ref bean="someBean"/>
Specifying the target bean by using the local
attribute leverages the ability of the XML parser to validate XML id
references within the same file. The value of the
local attribute must be the same as the
id attribute of the target bean. The XML parser
will issue an error if no matching element is found in the same file.
As such, using the local variant is the best choice (in order to know
about errors as early as possible) if the target bean is in the same
XML file.
<ref local="someBean"/>
Specifying the target bean by using the
'parent' attribute allows a reference to be created
to a bean which is in a parent container of the current container. The
value of the 'parent' attribute may be the same as
either the 'id' attribute of the target bean, or
one of the values in the 'name' attribute of the
target bean, and the target bean must be in a parent container to the
current one. The main use of this bean reference variant is when you
have a hierarchy of containers and you want to wrap an existing bean
in a parent container with some sort of proxy which will have the same
name as the parent bean.
<!-- in the parent context --> <bean id="accountService" class="com.foo.SimpleAccountService"> <!-- insert dependencies as required as here --> </bean>
<!-- in the child (descendant) context --> <bean id="accountService" <-- notice that the name of this bean is the same as the name of the 'parent' bean class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target"> <ref parent="accountService"/> <-- notice how we refer to the parent bean </property> <!-- insert other configuration and dependencies as required as here --> </bean>
A <bean/> element inside the
<property/> or
<constructor-arg/> elements is used to define
a so-called inner bean. An inner bean
definition does not need to have any id or name defined, and it is
best not to even specify any id or name value because the id or name
value simply will be ignored by the container.
<bean id="outer" class="..."> <!-- instead of using a reference to a target bean, simply define the target bean inline --> <property name="target"> <bean class="com.example.Person"> <!-- this is the inner bean --> <property name="name" value="Fiona Apple"/> <property name="age" value="25"/> </bean> </property> </bean>
Note that in the specific case of inner beans, the
'scope' flag and any 'id' or
'name' attribute are effectively ignored. Inner
beans are always anonymous and they are
always scoped as prototypes. Please
also note that it is not possible to inject inner
beans into collaborating beans other than the enclosing bean.
The <list/>,
<set/>, <map/>, and
<props/> elements allow properties and
arguments of the Java Collection type
List,
Set,
Map, and
Properties, respectively, to be defined
and set.
<bean id="moreComplexObject" class="example.ComplexObject"> <!-- results in a setAdminEmails(java.util.Properties) call --> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.org</prop> <prop key="support">support@example.org</prop> <prop key="development">development@example.org</prop> </props> </property> <!-- results in a setSomeList(java.util.List) call --> <property name="someList"> <list> <value>a list element followed by a reference</value> <ref bean="myDataSource" /> </list> </property> <!-- results in a setSomeMap(java.util.Map) call --> <property name="someMap"> <map> <entry> <key> <value>an entry</value> </key> <value>just some string</value> </entry> <entry> <key> <value>a ref</value> </key> <ref bean="myDataSource" /> </entry> </map> </property> <!-- results in a setSomeSet(java.util.Set) call --> <property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource" /> </set> </property> </bean>
![]() | Note |
|---|---|
The nested element style used this initial example tends to become quite verbose. Fortunately, there are attribute shortcuts for most elements, which you can read about in Section 4.3.2.6, “Shortcuts and other convenience options for XML-based configuration metadata”. |
Note that the value of a map key or value, or a set value, can also again be any of the following elements:
bean | ref | idref | list | set | map | props | value | null
As of Spring 2.0, the container also supports the
merging of collections. This allows an
application developer to define a parent-style
<list/>, <map/>,
<set/> or <props/>
element, and have child-style <list/>,
<map/>, <set/> or
<props/> elements inherit and override
values from the parent collection; that is to say the child
collection's values will be the result obtained from the merging of
the elements of the parent and child collections, with the child's
collection elements overriding values specified in the parent
collection.
Please note that this section on merging makes use of the parent-child bean mechanism. This concept has not yet been introduced, so readers unfamiliar with the concept of parent and child bean definitions may wish to read the relevant section before continuing.
Find below an example of the collection merging feature:
<beans> <bean id="parent" abstract="true" class="example.ComplexObject"> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.com</prop> <prop key="support">support@example.com</prop> </props> </property> </bean> <bean id="child" parent="parent"> <property name="adminEmails"> <!-- the merge is specified on the *child* collection definition --> <props merge="true"> <prop key="sales">sales@example.com</prop> <prop key="support">support@example.co.uk</prop> </props> </property> </bean> <beans>
Notice the use of the merge=true attribute
on the <props/> element of the
adminEmails property of the
child bean definition. When the
child bean is actually resolved and instantiated
by the container, the resulting instance will have an
adminEmails Properties
collection that contains the result of the merging of the child's
adminEmails collection with the parent's
adminEmails collection.
administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk
Notice how the child Properties
collection's value set will have inherited all the property elements
from the parent <props/>. Notice also how
the child's value for the support value overrides
the value in the parent collection.
This merging behavior applies similarly to the
<list/>, <map/>,
and <set/> collection types. In the
specific case of the <list/> element, the
semantics associated with the List collection
type, that is the notion of an ordered collection
of values, is maintained; the parent's values will precede all of
the child list's values. In the case of the
Map,
Set, and
Properties collection types, there is
no notion of ordering and hence no ordering semantics are in effect
for the collection types that underlie the associated
Map,
Set and
Properties implementation types used
internally by the container.
Finally, some minor notes about the merging support are in
order; you cannot merge different collection types (e.g. a
Map and a
List), and if you do attempt to do so
an appropriate Exception will be thrown; and
in case it is not immediately obvious, the
'merge' attribute must be specified on the lower
level, inherited, child definition; specifying the
'merge' attribute on a parent collection
definition is redundant and will not result in the desired merging;
and (lastly), please note that this merging feature is only
available in Spring 2.0 (and later versions).
If you are using Java 5 or Java 6, you will be aware that it
is possible to have strongly typed collections (using generic
types). That is, it is possible to declare a
Collection type such that it can only
contain String elements (for example). If you
are using Spring to dependency inject a strongly-typed
Collection into a bean, you can take
advantage of Spring's type-conversion support such that the elements
of your strongly-typed Collection
instances will be converted to the appropriate type prior to being
added to the Collection.
public class Foo { private Map<String, Float> accounts; public void setAccounts(Map<String, Float> accounts) { this.accounts = accounts; } }
<beans> <bean id="foo" class="x.y.Foo"> <property name="accounts"> <map> <entry key="one" value="9.99"/> <entry key="two" value="2.75"/> <entry key="six" value="3.99"/> </map> </property> </bean> </beans>
When the 'accounts' property of the
'foo' bean is being prepared for injection, the
generics information about the element type of the strongly-typed
Map<String, Float> is actually
available via reflection, and so Spring's type conversion
infrastructure will actually recognize the various value elements as
being of type Float and so the string values
'9.99', '2.75', and '3.99'
will be converted into an actual Float
type.
The <null/> element is used to handle
null values. Spring treats empty arguments for
properties and the like as empty Strings. The
following XML-based configuration metadata snippet results in the
email property being set to the empty String
value ("")
<bean class="ExampleBean"> <property name="email"><value/></property> </bean>
This is equivalent to the following Java code:
exampleBean.setEmail(""). The special
<null> element may be used to indicate a
null value. For example:
<bean class="ExampleBean"> <property name="email"><null/></property> </bean>
The above configuration is equivalent to the following Java
code: exampleBean.setEmail(null).
The configuration metadata shown so far is a tad verbose. That
is why there are several options available for you to limit the amount
of XML you have to write to configure your components. The first is a
shortcut to define values and references to other beans as part of a
<property/> definition. The second is
slightly different format of specifying properties altogether.
The <property/>,
<constructor-arg/>, and
<entry/> elements all support a
'value' attribute which may be used instead of
embedding a full <value/> element.
Therefore, the following:
<property name="myProperty"> <value>hello</value> </property>
<constructor-arg> <value>hello</value> </constructor-arg>
<entry key="myKey"> <value>hello</value> </entry>
are equivalent to:
<property name="myProperty" value="hello"/>
<constructor-arg value="hello"/>
<entry key="myKey" value="hello"/>
The <property/> and
<constructor-arg/> elements support a
similar shortcut 'ref' attribute which may be
used instead of a full nested <ref/>
element. Therefore, the following:
<property name="myProperty"> <ref bean="myBean"> </property>
<constructor-arg> <ref bean="myBean"> </constructor-arg>
... are equivalent to:
<property name="myProperty" ref="myBean"/>
<constructor-arg ref="myBean"/>
Note however that the shortcut form is equivalent to a
<ref bean="xxx"> element; there is no
shortcut for <ref local="xxx">. To enforce
a strict local reference, you must use the long form.
Finally, the entry element allows a shortcut form to specify
the key and/or value of the map, in the form of the
'key' / 'key-ref' and
'value' / 'value-ref'
attributes. Therefore, the following:
<entry> <key> <ref bean="myKeyBean" /> </key> <ref bean="myValueBean" /> </entry>
is equivalent to:
<entry key-ref="myKeyBean" value-ref="myValueBean"/>
Again, the shortcut form is equivalent to a <ref
bean="xxx"> element; there is no shortcut for
<ref local="xxx">.
The second option you have to limit the amount of XML you have
to write to configure your components is to use the special
"p-namespace". Spring 2.0 and later features support for extensible
configuration formats using
namespaces. Those namespaces are all based on an XML Schema
definition. In fact, the beans configuration
format that you've been reading about is defined in an XML Schema
document.
One special namespace is not defined in an XSD file, and only
exists in the core of Spring itself. The so-called p-namespace
doesn't need a schema definition and is an alternative way of
configuring your properties differently than the way you have seen
so far. Instead of using nested <property/>
elements, using the p-namespace you can use attributes as part of
the bean element that describe your property
values. The values of the attributes will be taken as the values for
your properties.
The following two XML snippets boil down to the same thing in the end: the first is using the standard XML format whereas the second example is using the p-namespace.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean name="classic" class="com.example.ExampleBean"> <property name="email" value="foo@bar.com/> </bean> <bean name="p-namespace" class="com.example.ExampleBean" p:email="foo@bar.com"/> </beans>
As you can see, we are including an attribute in the p-namespace called email in the bean definition - this is telling Spring that it should include a property declaration. As previously mentioned, the p-namespace doesn't have a schema definition, so the name of the attribute can be set to whatever name your property has.
This next example includes two more bean definitions that both have a reference to another bean:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean name="john-classic" class="com.example.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="john-modern" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/> <bean name="jane" class="com.example.Person"> <property name="name" value="Jane Doe"/> </bean> </beans>
As you can see, this example doesn't only include a property
value using the p-namespace, but also uses a special format to
declare property references. Whereas the first bean definition uses
<property name="spouse" ref="jane"/> to
create a reference from bean john to bean
jane, the second bean definition uses
p:spouse-ref="jane" as an attribute to do the
exact same thing. In this case 'spouse' is the
property name whereas the '-ref' part indicates
that this is not a straight value but rather a reference to another
bean.
![]() | Note |
|---|---|
Please note that the p-namespace is not quite as flexible as
the standard XML format - for example particular, the 'special'
format used to declare property references will clash with
properties that end in ' |
Compound or nested property names are perfectly legal when
setting bean properties, as long as all components of the path except
the final property name are not null. Consider the
following bean definition...
<bean id="foo" class="foo.Bar"> <property name="fred.bob.sammy" value="123" /> </bean>
The foo bean has a fred
property which has a bob property, which has a
sammy property, and that final
sammy property is being set to the value
123. In order for this to work, the
fred property of foo, and the
bob property of fred must not be
null be non-null after the bean is constructed, or
a NullPointerException will be
thrown.
For most situations, the fact that a bean is a dependency of
another is expressed by the fact that one bean is set as a property of
another. This is typically accomplished with the <ref/>
element in XML-based configuration metadata. For the relatively
infrequent situations where dependencies between beans are less direct
(for example, when a static initializer in a class needs to be
triggered, such as database driver registration), the
'depends-on' attribute may be used to explicitly
force one or more beans to be initialized before the bean using this
element is initialized. Find below an example of using the
'depends-on' attribute to express a dependency on a
single bean.
<bean id="beanOne" class="ExampleBean" depends-on="manager"/> <bean id="manager" class="ManagerBean" />
If you need to express a dependency on multiple beans, you can
supply a list of bean names as the value of the
'depends-on' attribute, with commas, whitespace and
semicolons all valid delimiters, like so:
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> <property name="manager" ref="manager" /> </bean> <bean id="manager" class="ManagerBean" /> <bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
![]() | Note |
|---|---|
The ' |
The default behavior for
ApplicationContext implementations is to
eagerly pre-instantiate all singleton beans at
startup. Pre-instantiation means that an
ApplicationContext will eagerly create
and configure all of its singleton beans as part
of its initialization process. Generally this is a good
thing, because it means that any errors in the configuration
or in the surrounding environment will be discovered immediately (as
opposed to possibly hours or even days down the line).
However, there are times when this behavior is
not what is wanted. If you do not want a singleton
bean to be pre-instantiated when using an
ApplicationContext, you can selectively
control this by marking a bean definition as lazy-initialized. A
lazily-initialized bean indicates to the IoC container whether or not a
bean instance should be created at startup or when it is first
requested.
When configuring beans via XML, this lazy loading is controlled by
the 'lazy-init' attribute on the
<bean/> element; for example:
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/> <bean name="not.lazy" class="com.foo.AnotherBean"/>
When the above configuration is consumed by an
ApplicationContext, the bean named
'lazy' will not be eagerly
pre-instantiated when the
ApplicationContext is starting up,
whereas the 'not.lazy' bean will be eagerly
pre-instantiated.
One thing to understand about lazy-initialization is that even
though a bean definition may be marked up as being lazy-initialized, if
the lazy-initialized bean is the dependency of a singleton bean that is
not lazy-initialized, when the
ApplicationContext is eagerly
pre-instantiating the singleton, it will have to satisfy all of the
singletons dependencies, one of which will be the lazy-initialized bean!
So don't be confused if the IoC container creates one of the beans that
you have explicitly configured as lazy-initialized at startup; all that
means is that the lazy-initialized bean is being injected into a
non-lazy-initialized singleton bean elsewhere.
It is also possible to control lazy-initialization at the
container level by using the 'default-lazy-init'
attribute on the <beans/> element; for
example:
<beans default-lazy-init="true"> <!-- no beans will be pre-instantiated... --> </beans>
The Spring container is able to autowire
relationships between collaborating beans. This means that it is
possible to automatically let Spring resolve collaborators (other beans)
for your bean by inspecting the contents of the
BeanFactory. The autowiring functionality
has five modes. Autowiring is specified per bean
and can thus be enabled for some beans, while other beans will not be
autowired. Using autowiring, it is possible to reduce or eliminate the
need to specify properties or constructor arguments, thus saving a
significant amount of typing. [2] When using XML-based configuration metadata, the autowire
mode for a bean definition is specified by using the
autowire attribute of the
<bean/> element. The following values are
allowed:
Table 4.2. Autowiring modes
| Mode | Explanation |
|---|---|
| no | No autowiring at all. Bean references must be
defined via a |
| byName | Autowiring by property name. This option will
inspect the container and look for a bean named exactly the same
as the property which needs to be autowired. For example, if you
have a bean definition which is set to autowire by name, and it
contains a master property (that is, it has
a setMaster(..) method), Spring will look
for a bean definition named |
| byType | Allows a property to be autowired if there is
exactly one bean of the property type in the container. If there
is more than one, a fatal exception is thrown, and this
indicates that you may not use byType
autowiring for that bean. If there are no matching beans,
nothing happens; the property is not set. If this is not
desirable, setting the
|
| constructor | This is analogous to byType, but applies to constructor arguments. If there isn't exactly one bean of the constructor argument type in the container, a fatal error is raised. |
| autodetect | Chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode will be applied. |
Note that explicit dependencies in property and
constructor-arg settings
always override autowiring. Please also
note that it is not currently possible to autowire so-called
simple properties such as primitives,
Strings, and Classes (and
arrays of such simple properties). (This is by-design and should be
considered a feature.) When using either the
byType or constructor
autowiring mode, it is possible to wire arrays and typed-collections. In
such cases all autowire candidates within the
container that match the expected type will be provided to satisfy the
dependency. Strongly-typed Maps can even be autowired if the expected
key type is String. An autowired Map's values
will consist of all bean instances that match the expected type, and the
Map's keys will contain the corresponding bean names.
Autowire behavior can be combined with dependency checking, which will be performed after all autowiring has been completed.
It is important to understand the various advantages and disadvantages of autowiring. Some advantages of autowiring include:
Autowiring can significantly reduce the volume of configuration required. However, mechanisms such as the use of a bean template (discussed elsewhere in this chapter) are also valuable in this regard.
Autowiring can cause configuration to keep itself up to date as your objects evolve. For example, if you need to add an additional dependency to a class, that dependency can be satisfied automatically without the need to modify configuration. Thus there may be a strong case for autowiring during development, without ruling out the option of switching to explicit wiring when the code base becomes more stable.
Some disadvantages of autowiring:
Autowiring is more magical than explicit wiring. Although, as noted in the above table, Spring is careful to avoid guessing in case of ambiguity which might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
Wiring information may not be available to tools that may generate documentation from a Spring container.
Another issue to consider when autowiring by type is that multiple
bean definitions within the container may match the type specified by
the setter method or constructor argument to be autowired. For arrays,
collections, or Maps, this is not necessarily a problem. However for
dependencies that expect a single value, this ambiguity will not be
arbitrarily resolved. Instead, if no unique bean definition is
available, an Exception will be thrown. You do have several options when
confronted with this scenario. First, you may abandon autowiring in
favor of explicit wiring. Second, you may designate that certain bean
definitions are never to be considered as candidates by setting their
'autowire-candidate' attributes to
'false' as described in the next section. Third, you
may designate a single bean definition as the
primary candidate by setting the
'primary' attribute of its
<bean/> element to 'true'.
Finally, if you are using at least Java 5, you may be interested in
exploring the more fine-grained control available with annotation-based
configuration as described in the section entitled Section 4.11, “Annotation-based configuration”.
When deciding whether to use autowiring, there is no wrong or right answer in all cases. A degree of consistency across a project is best though; for example, if autowiring is not used in general, it might be confusing to developers to use it just to wire one or two bean definitions.
You can also (on a per-bean basis) totally exclude a bean from
being an autowire candidate. When configuring beans using Spring's XML
format, the 'autowire-candidate' attribute of the
<bean/> element can be set to
'false'; this has the effect of making the
container totally exclude that specific bean definition from being
available to the autowiring infrastructure.
Another option is to limit autowire candidates based on
pattern-matching against bean names. The top-level
<beans/> element accepts one or more patterns
within its 'default-autowire-candidates' attribute.
For example, to limit autowire candidate status to any bean whose name
ends with 'Repository', provide a value of
'*Repository'. To provide multiple patterns, define them in a
comma-separated list. Note that an explicit value of
'true' or 'false' for a bean
definition's 'autowire-candidate' attribute always
takes precedence, and for such beans, the pattern matching rules will
not apply.
These techniques can be useful when you have one or more beans that you absolutely never ever want to have injected into other beans via autowiring. It does not mean that an excluded bean cannot itself be configured using autowiring... it can, it is rather that it itself will not be considered as a candidate for autowiring other beans.
The Spring IoC container also has the ability to check for the existence of unresolved dependencies of a bean deployed into the container. These are JavaBeans properties of the bean, which do not have actual values set for them in the bean definition, or alternately provided automatically by the autowiring feature.
This feature is sometimes useful when you want to ensure that all
properties (or all properties of a certain type) are set on a bean. Of
course, in many cases a bean class will have default values for many
properties, or some properties do not apply to all usage scenarios, so
this feature is of limited use. Dependency checking can also be enabled
and disabled per bean, just as with the autowiring functionality. The
default is to not check dependencies. Dependency
checking can be handled in several different modes. When using XML-based
configuration metadata, this is specified via the
'dependency-check' attribute in a bean definition,
which may have the following values.
Table 4.3. Dependency checking modes
| Mode | Explanation |
|---|---|
| none | No dependency checking. Properties of the bean which have no value specified for them are simply not set. |
| simple | Dependency checking is performed for primitive types and collections (everything except collaborators). |
| object | Dependency checking is performed for collaborators only. |
| all | Dependency checking is done for collaborators, primitive types and collections. |
If you are using Java 5 and thus have access to source-level annotations, you may find the section entitled Section 29.3.1, “@Required” to be of interest.
For most application scenarios, the majority of the beans in the container will be singletons. When a singleton bean needs to collaborate with another singleton bean, or a non-singleton bean needs to collaborate with another non-singleton bean, the typical and common approach of handling this dependency by defining one bean to be a property of the other is quite adequate. There is a problem when the bean lifecycles are different. Consider a singleton bean A which needs to use a non-singleton (prototype) bean B, perhaps on each method invocation on A. The container will only create the singleton bean A once, and thus only get the opportunity to set the properties once. There is no opportunity for the container to provide bean A with a new instance of bean B every time one is needed.
One solution to this issue is to forego some inversion of control.
Bean A can be made
aware of the container by implementing the
BeanFactoryAware interface, and use programmatic means to ask the
container via a getBean("B") call for (a
typically new) bean B instance every time it needs it. Find below an
admittedly somewhat contrived example of this approach:
// a class that uses a stateful Command-style class to perform some processing package fiona.apple; // lots of Spring-API imports import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; public class CommandManager implements BeanFactoryAware { private BeanFactory beanFactory; public Object process(Map commandState) { // grab a new instance of the appropriate Command Command command = createCommand(); // set the state on the (hopefully brand new) Command instance command.setState(commandState); return command.execute(); } // the Command returned here could be an implementation that executes asynchronously, or whatever protected Command createCommand() { return (Command) this.beanFactory.getBean("command"); // notice the Spring API dependency } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
The above example is generally not a desirable solution since the business code is then aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, allows this use case to be handled in a clean fashion.
Lookup method injection refers to the ability of the container to override methods on container managed beans, to return the result of looking up another named bean in the container. The lookup will typically be of a prototype bean as in the scenario described above. The Spring Framework implements this method injection by dynamically generating a subclass overriding the method, using bytecode generation via the CGLIB library.
So if you look at the code from previous code snippet (the
CommandManager class), the Spring container is
going to dynamically override the implementation of the
createCommand() method. Your
CommandManager class is not going to have any
Spring dependencies, as can be seen in this reworked example
below:
package fiona.apple; // no more Spring imports! public abstract class CommandManager { public Object process(Object commandState) { // grab a new instance of the appropriate Command interface Command command = createCommand(); // set the state on the (hopefully brand new) Command instance command.setState(commandState); return command.execute(); } // okay... but where is the implementation of this method? protected abstract Command createCommand(); }
In the client class containing the method to be injected (the
CommandManager in this case), the method that
is to be 'injected' must have a signature of the following
form:
<public|protected> [abstract] <return-type> theMethodName(no-arguments);
If the method is abstract, the
dynamically-generated subclass will implement the method. Otherwise,
the dynamically-generated subclass will override the concrete method
defined in the original class. Let's look at an example:
<!-- a stateful bean deployed as a prototype (non-singleton) --> <bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> <!-- inject dependencies here as required --> </bean> <!-- commandProcessor uses statefulCommandHelper --> <bean id="commandManager" class="fiona.apple.CommandManager"> <lookup-method name="createCommand" bean="command"/> </bean>
The bean identified as commandManager will
call its own method createCommand() whenever
it needs a new instance of the command bean. It
is important to note that the person deploying the beans must be
careful to deploy the command bean as a prototype
(if that is actually what is needed). If it is deployed as a singleton, the same
instance of the command bean will be returned each
time!
Please be aware that in order for this dynamic subclassing to
work, you will need to have the CGLIB jar(s) on your classpath.
Additionally, the class that the Spring container is going to subclass
cannot be final, and the method that is being
overridden cannot be final either. Also, testing a
class that has an abstract method can be somewhat
odd in that you will have to subclass the class yourself and supply a
stub implementation of the abstract method.
Finally, objects that have been the target of method injection cannot
be serialized.
![]() | Tip |
|---|---|
The interested reader may also find the
|
A less commonly useful form of method injection than Lookup Method Injection is the ability to replace arbitrary methods in a managed bean with another method implementation. Users may safely skip the rest of this section (which describes this somewhat advanced feature), until this functionality is actually needed.
When using XML-based configuration metadata, the
replaced-method element may be used to replace an
existing method implementation with another, for a deployed bean.
Consider the following class, with a method computeValue, which we
want to override:
public class MyValueCalculator { public String computeValue(String input) { // some real code... } // some other methods... }
A class implementing the
org.springframework.beans.factory.support.MethodReplacer
interface provides the new method definition.
/** meant to be used to override the existing computeValue(String) implementation in MyValueCalculator */ public class ReplacementComputeValue implements MethodReplacer { public Object reimplement(Object o, Method m, Object[] args) throws Throwable { // get the input value, work with it, and return a computed result String input = (String) args[0]; ... return ...; } }
The bean definition to deploy the original class and specify the method override would look like this:
<bean id="myValueCalculator class="x.y.z.MyValueCalculator"> <!-- arbitrary method replacement --> <replaced-method name="computeValue" replacer="replacementComputeValue"> <arg-type>String</arg-type> </replaced-method> </bean> <bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
One or more contained <arg-type/>
elements within the <replaced-method/>
element may be used to indicate the method signature of the method
being overridden. Note that the signature for the arguments is
actually only needed in the case that the method is actually
overloaded and there are multiple variants within the class. For
convenience, the type string for an argument may be a substring of the
fully qualified type name. For example, all the following would match
java.lang.String.
java.lang.String
String
StrSince the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by allowing you to type just the shortest string that will match an argument type.