6855 lines
329 KiB
XML
6855 lines
329 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
|
<chapter id="beans">
|
|
<title>The IoC container</title>
|
|
|
|
<section id="beans-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<para>This chapter covers the Spring Framework's implementation of the
|
|
Inversion of Control (IoC) <footnote>
|
|
<para>See the section entitled <xref
|
|
linkend="background-ioc" /></para>
|
|
</footnote> principle.</para>
|
|
|
|
<para>The <literal>org.springframework.beans</literal> and
|
|
<literal>org.springframework.context</literal> packages provide the basis
|
|
for the Spring Framework's IoC container. The <interfacename><ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</ulink></interfacename>
|
|
interface provides an advanced configuration mechanism capable of managing
|
|
objects of any nature. The <literal><ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/ApplicationContext.html">ApplicationContext</ulink></literal>
|
|
interface builds on top of the <interfacename>BeanFactory</interfacename>
|
|
(it is a sub-interface) and adds other functionality such as easier
|
|
integration with Spring's AOP features, message resource handling (for use
|
|
in internationalization), event propagation, and application-layer
|
|
specific contexts such as the
|
|
<interfacename>WebApplicationContext</interfacename> for use in web
|
|
applications.</para>
|
|
|
|
<para>In short, the <interfacename>BeanFactory</interfacename> provides
|
|
the configuration framework and basic functionality, while the
|
|
<interfacename>ApplicationContext</interfacename> adds more
|
|
enterprise-centric functionality to it. The
|
|
<interfacename>ApplicationContext</interfacename> is a complete superset
|
|
of the <interfacename>BeanFactory</interfacename>, and any description of
|
|
<interfacename>BeanFactory</interfacename> capabilities and behavior is to
|
|
be considered to apply to the
|
|
<interfacename>ApplicationContext</interfacename> as well.</para>
|
|
|
|
<sidebar>
|
|
<title><interfacename>BeanFactory</interfacename> or
|
|
<interfacename>ApplicationContext</interfacename>?</title>
|
|
|
|
<para>Users are sometimes unsure whether a
|
|
<interfacename>BeanFactory</interfacename> or an
|
|
<interfacename>ApplicationContext</interfacename> is best suited for use
|
|
in a particular situation. A <interfacename>BeanFactory</interfacename>
|
|
pretty much just instantiates and configures beans. An
|
|
<interfacename>ApplicationContext</interfacename> also does that,
|
|
<emphasis>and</emphasis> it provides the supporting infrastructure to
|
|
enable <emphasis>lots</emphasis> of enterprise-specific features such as
|
|
transactions and AOP.</para>
|
|
|
|
<para><emphasis role="bold">In short, favor the use of an
|
|
<interfacename>ApplicationContext</interfacename>.</emphasis></para>
|
|
|
|
<para>(For the specific details behind this recommendation, see <link
|
|
linkend="context-introduction-ctx-vs-beanfactory">this
|
|
section</link>.)</para>
|
|
</sidebar>
|
|
|
|
<para>This chapter is divided into two parts, with the <link
|
|
linkend="beans-basics">first part</link> covering the basic principles
|
|
that apply to both the <interfacename>BeanFactory</interfacename> and
|
|
<interfacename>ApplicationContext</interfacename>, and with the <link
|
|
linkend="context-introduction">second part</link> covering those features
|
|
that apply only to the <interfacename>ApplicationContext</interfacename>
|
|
interface.</para>
|
|
</section>
|
|
|
|
<section id="beans-basics">
|
|
<title>Basics - containers and beans</title>
|
|
|
|
<para>In Spring, those objects that form the backbone of your application
|
|
and that are managed by the Spring IoC <firstterm>container</firstterm>
|
|
are referred to as <firstterm>beans</firstterm>. A bean is simply an
|
|
object that is instantiated, assembled and otherwise managed by a Spring
|
|
IoC container; other than that, there is nothing special about a bean (it
|
|
is in all other respects one of probably many objects in your
|
|
application). These beans, and the <firstterm>dependencies</firstterm>
|
|
between them, are reflected in the <firstterm>configuration
|
|
metadata</firstterm> used by a container.</para>
|
|
|
|
<sidebar>
|
|
<title>Why... <emphasis>bean</emphasis>?</title>
|
|
|
|
<para>The motivation for using the name <emphasis>'bean'</emphasis>, as
|
|
opposed to <emphasis>'component'</emphasis> or
|
|
<emphasis>'object'</emphasis> is rooted in the origins of the Spring
|
|
Framework itself (it arose partly as a response to the complexity of
|
|
Enterprise Java<emphasis>Beans</emphasis>).</para>
|
|
</sidebar>
|
|
|
|
<section id="beans-factory">
|
|
<title>The container</title>
|
|
|
|
<para>The
|
|
<interfacename>org.springframework.beans.factory.BeanFactory</interfacename>
|
|
is the actual representation of the Spring IoC
|
|
<emphasis>container</emphasis> that is responsible for containing and
|
|
otherwise managing the aforementioned beans.</para>
|
|
|
|
<para>The <interfacename>BeanFactory</interfacename> interface is the
|
|
central IoC container interface in Spring. Its responsibilities include
|
|
instantiating or sourcing application objects, configuring such objects,
|
|
and assembling the dependencies between these objects.</para>
|
|
|
|
<para>There are a number of implementations of the
|
|
<interfacename>BeanFactory</interfacename> interface that come supplied
|
|
straight out-of-the-box with Spring. The most commonly used
|
|
<interfacename>BeanFactory</interfacename> implementation is the
|
|
<classname>XmlBeanFactory</classname> class. This implementation allows
|
|
you to express the objects that compose your application, and the
|
|
doubtless rich interdependencies between such objects, in terms of XML.
|
|
The <classname>XmlBeanFactory</classname> takes this XML
|
|
<firstterm>configuration metadata</firstterm> and uses it to create a
|
|
fully configured system or application.</para>
|
|
|
|
<para><mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata align="center" fileref="images/container-magic.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
|
|
<imageobject role="html">
|
|
<imagedata align="center" fileref="images/container-magic.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
|
|
<caption><para>The Spring IoC container</para></caption>
|
|
</mediaobject></para>
|
|
|
|
<section id="beans-factory-metadata">
|
|
<title>Configuration metadata</title>
|
|
|
|
<para>As can be seen in the above image, the Spring IoC container
|
|
consumes some form of <emphasis>configuration metadata</emphasis>;
|
|
this configuration metadata is nothing more than how you (as an
|
|
application developer) inform the Spring container as to how to
|
|
<emphasis><quote>instantiate, configure, and assemble [the objects in
|
|
your application]</quote>.</emphasis> This configuration metadata is
|
|
typically supplied in a simple and intuitive XML format. When using
|
|
XML-based configuration metadata, you write <emphasis>bean
|
|
definitions</emphasis> for those beans that you want the Spring IoC
|
|
container to manage, and then let the container do its stuff.</para>
|
|
|
|
<note>
|
|
<para>XML-based metadata is by far the most commonly used form of
|
|
configuration metadata. It is <emphasis>not</emphasis> however the
|
|
only form of configuration metadata that is allowed. The Spring IoC
|
|
container itself is <emphasis>totally</emphasis> decoupled from the
|
|
format in which this configuration metadata is actually written. The
|
|
XML-based configuration metadata format really is simple though, and
|
|
so the majority of this chapter will use the XML format to convey
|
|
key concepts and features of the Spring IoC container.</para>
|
|
|
|
<para>You can find details of another form of metadata that the
|
|
Spring container can consume in the section entitled <xref
|
|
linkend="beans-annotation-config" /></para>
|
|
</note>
|
|
|
|
<sidebar>
|
|
<title>Resources</title>
|
|
|
|
<para>The location path or paths supplied to an
|
|
<interfacename>ApplicationContext</interfacename> constructor are
|
|
actually resource strings that allow the container to load
|
|
configuration metadata from a variety of external resources such as
|
|
the local file system, from the Java <literal>CLASSPATH</literal>,
|
|
etc.</para>
|
|
|
|
<para>Once you have learned about Spring's IoC container, you may
|
|
wish to learn a little more about Spring's
|
|
<interfacename>Resource</interfacename> abstraction, as described in
|
|
the chapter entitled <xref linkend="resources" />.</para>
|
|
</sidebar>
|
|
|
|
<para>In the vast majority of application scenarios, explicit user
|
|
code is not required to instantiate one or more instances of a Spring
|
|
IoC container. For example, in a web application scenario, a simple
|
|
eight (or so) lines of boilerplate J2EE web descriptor XML in the
|
|
<literal>web.xml</literal> file of the application will typically
|
|
suffice (see <xref linkend="context-create" />).</para>
|
|
|
|
<para>Spring configuration consists of at least one bean definition
|
|
that the container must manage, but typically there will be more than
|
|
one bean definition. When using XML-based configuration metadata,
|
|
these beans are configured as <literal><bean/></literal>
|
|
elements inside a top-level <literal><beans/></literal>
|
|
element.</para>
|
|
|
|
<para>These bean definitions correspond to the actual objects that
|
|
make up your application. Typically you will have bean definitions for
|
|
your service layer objects, your data access objects (DAOs),
|
|
presentation objects such as Struts
|
|
<interfacename>Action</interfacename> instances, infrastructure
|
|
objects such as Hibernate
|
|
<interfacename>SessionFactories</interfacename>, JMS
|
|
<interfacename>Queues</interfacename>, and so forth. Typically one
|
|
does not configure fine-grained domain objects in the container,
|
|
because it is usually the responsibility of DAOs and business logic to
|
|
create/load domain objects.</para>
|
|
|
|
<para>Find below an example of the basic structure of XML-based
|
|
configuration metadata.</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
|
|
|
<bean id="..." class="...">
|
|
<!-- collaborators and configuration for this bean go here -->
|
|
</bean>
|
|
|
|
<bean id="..." class="...">
|
|
<!-- collaborators and configuration for this bean go here -->
|
|
</bean>
|
|
|
|
<!-- more bean definitions go here -->
|
|
|
|
</beans></programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-instantiation">
|
|
<title>Instantiating a container</title>
|
|
|
|
<para>Instantiating a Spring IoC container is straightforward.</para>
|
|
|
|
<programlisting language="java">ApplicationContext context = new ClassPathXmlApplicationContext(
|
|
new String[] {"services.xml", "daos.xml"});
|
|
|
|
<lineannotation>// an <interfacename>ApplicationContext</interfacename> is also a <interfacename>BeanFactory</interfacename> (via inheritance)</lineannotation>
|
|
BeanFactory factory = context;</programlisting>
|
|
|
|
<section id="beans-factory-xml-import">
|
|
<title>Composing XML-based configuration metadata</title>
|
|
|
|
<para>It can often be useful to split up container definitions into
|
|
multiple XML files. One way to then load an application context which
|
|
is configured from all these XML fragments is to use the application
|
|
context constructor which takes multiple
|
|
<interfacename>Resource</interfacename> locations. With a bean
|
|
factory, a bean definition reader can be used multiple times to read
|
|
definitions from each file in turn.</para>
|
|
|
|
<para>Generally, the Spring team prefers the above approach, since it
|
|
keeps container configuration files unaware of the fact that they are
|
|
being combined with others. An alternate approach is to use one or
|
|
more occurrences of the <literal><import/></literal> element to
|
|
load bean definitions from another file (or files). Let's look at a
|
|
sample:</para>
|
|
|
|
<programlisting language="xml"><beans>
|
|
|
|
<import resource="services.xml"/>
|
|
<import resource="resources/messageSource.xml"/>
|
|
<import resource="/resources/themeSource.xml"/>
|
|
|
|
<bean id="bean1" class="..."/>
|
|
<bean id="bean2" class="..."/>
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>In this example, external bean definitions are being loaded from
|
|
3 files, <literal>services.xml</literal>,
|
|
<literal>messageSource.xml</literal>, and
|
|
<literal>themeSource.xml</literal>. All location paths are considered
|
|
relative to the definition file doing the importing, so
|
|
<literal>services.xml</literal> in this case must be in the same
|
|
directory or classpath location as the file doing the importing, while
|
|
<literal>messageSource.xml</literal> and
|
|
<literal>themeSource.xml</literal> must be in a
|
|
<literal>resources</literal> location below the location of the
|
|
importing file. As you can see, a leading slash is actually ignored,
|
|
but given that these are considered relative paths, it is probably
|
|
better form not to use the slash at all. The contents of the files
|
|
being imported must be valid XML bean definition files according to
|
|
the Spring Schema or DTD, including the top level
|
|
<literal><beans/></literal> element.</para>
|
|
|
|
<note>
|
|
<para>It is possible to reference files in parent directories using
|
|
a relative "../" path. However, this is not recommended because it
|
|
creates a dependency on a file that is outside the current
|
|
application. This is in particular not recommended for "classpath:"
|
|
URLs (e.g. "classpath:../services.xml") where the runtime resolution
|
|
process will pick the "nearest" classpath root and then look into
|
|
its parent directory. This is fragile since classpath configuration
|
|
changes may lead to a different directory being picked.</para>
|
|
|
|
<para>Note that you can always use fully qualified resource
|
|
locations instead of relative paths: e.g.
|
|
"file:C:/config/services.xml" or "classpath:/config/services.xml".
|
|
However, be aware that you are coupling your application's
|
|
configuration to specific absolute locations then. It is generally
|
|
preferable to keep an indirection for such absolute locations, e.g.
|
|
through "${...}" placeholders that are resolved against JVM system
|
|
properties at runtime.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-definition">
|
|
<title>The beans</title>
|
|
|
|
<para>A Spring IoC container manages one or more
|
|
<emphasis>beans</emphasis>. These beans are created using the
|
|
configuration metadata that has been supplied to the container
|
|
(typically in the form of XML <literal><bean/></literal>
|
|
definitions).</para>
|
|
|
|
<para>Within the container itself, these bean definitions are
|
|
represented as <interfacename>BeanDefinition</interfacename> objects,
|
|
which contain (among other information) the following metadata:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis>a package-qualified class name:</emphasis> typically
|
|
this is the actual implementation class of the bean being
|
|
defined.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>bean behavioral configuration elements, which state how the
|
|
bean should behave in the container (scope, lifecycle callbacks, and
|
|
so forth).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>references to other beans which are needed for the bean to do
|
|
its work; these references are also called
|
|
<emphasis>collaborators</emphasis> or
|
|
<emphasis>dependencies</emphasis>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>other configuration settings to set in the newly created
|
|
object. An example would be the number of connections to use in a
|
|
bean that manages a connection pool, or the size limit of the
|
|
pool.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The concepts listed above directly translate to a set of
|
|
properties that each bean definition consists of. Some of these
|
|
properties are listed below, along with a link to further documentation
|
|
about each of them.</para>
|
|
|
|
<table id="beans-factory-bean-definition-tbl">
|
|
<title>The bean definition</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="2*" />
|
|
|
|
<colspec colname="c2" colwidth="4*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Feature</entry>
|
|
|
|
<entry>Explained in...</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>class</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-class" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>name</entry>
|
|
|
|
<entry><para> <xref linkend="beans-beanname" /> </para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>scope</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-scopes" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>constructor arguments</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-collaborators" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>properties</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-collaborators" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>autowiring mode</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-autowire" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>dependency checking mode</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-dependencies" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>lazy-initialization mode</entry>
|
|
|
|
<entry><para> <xref linkend="beans-factory-lazy-init" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>initialization method</entry>
|
|
|
|
<entry><para> <xref
|
|
linkend="beans-factory-lifecycle-initializingbean" />
|
|
</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>destruction method</entry>
|
|
|
|
<entry><para> <xref
|
|
linkend="beans-factory-lifecycle-disposablebean" />
|
|
</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>Besides bean definitions which contain information on how to
|
|
create a specific bean, certain
|
|
<interfacename>BeanFactory</interfacename> implementations also permit
|
|
the registration of existing objects that have been created outside the
|
|
factory (by user code). The
|
|
<classname>DefaultListableBeanFactory</classname> class supports this
|
|
through the <methodname>registerSingleton(..)</methodname> method.
|
|
(Typical applications solely work with beans defined through metadata
|
|
bean definitions though.)</para>
|
|
|
|
<section id="beans-beanname">
|
|
<title>Naming beans</title>
|
|
|
|
<sidebar>
|
|
<title>Bean naming conventions</title>
|
|
|
|
<para>The convention (at least amongst the Spring development team)
|
|
is to use the standard Java convention for instance field names when
|
|
naming beans. That is, bean names start with a lowercase letter, and
|
|
are camel-cased from then on. Examples of such names would be
|
|
(without quotes) <literal>'accountManager'</literal>,
|
|
<literal>'accountService'</literal>, <literal>'userDao'</literal>,
|
|
<literal>'loginController'</literal>, and so forth.</para>
|
|
|
|
<para>Adopting a consistent way of naming your beans will go a long
|
|
way towards making your configuration easier to read and understand;
|
|
adopting such naming standards is not hard to do, and if you are
|
|
using Spring AOP it can pay off handsomely when it comes to applying
|
|
advice to a set of beans related by name.</para>
|
|
</sidebar>
|
|
|
|
<para>Every bean has one or more <literal>id</literal>s (also called
|
|
identifiers, or names; these terms refer to the same thing). These
|
|
<literal>id</literal>s must be unique within the container the bean is
|
|
hosted in. A bean will almost always have only one id, but if a bean
|
|
has more than one id, the extra ones can essentially be considered
|
|
aliases.</para>
|
|
|
|
<para>When using XML-based configuration metadata, you use the
|
|
<literal>'id'</literal> or <literal>'name'</literal> attributes to
|
|
specify the bean identifier(s). The <literal>'id'</literal> attribute
|
|
allows you to specify exactly one id, and as it is a real XML element
|
|
ID attribute, the XML parser is able to do some extra validation when
|
|
other elements reference the id; as such, it is the preferred way to
|
|
specify a bean id. However, the XML specification does limit the
|
|
characters which are legal in XML IDs. This is usually not a
|
|
constraint, but if you have a need to use one of these special XML
|
|
characters, or want to introduce other aliases to the bean, you may
|
|
also or instead specify one or more bean <literal>id</literal>s,
|
|
separated by a comma (<literal>,</literal>), semicolon
|
|
(<literal>;</literal>), or whitespace in the <literal>'name'</literal>
|
|
attribute.</para>
|
|
|
|
<para>Please note that you are not required to supply a name for a
|
|
bean. If no name is supplied explicitly, the container will generate a
|
|
unique name for that bean. The motivations for not supplying a name
|
|
for a bean will be discussed later (one use case is <link
|
|
linkend="beans-inner-beans">inner beans</link>).</para>
|
|
|
|
<section id="beans-beanname-alias">
|
|
<title>Aliasing beans</title>
|
|
|
|
<para>In a bean definition itself, you may supply more than one name
|
|
for the bean, by using a combination of up to one name specified via
|
|
the <literal>id</literal> attribute, and any number of other names
|
|
via the <literal>name</literal> attribute. All these names can be
|
|
considered equivalent aliases to the same bean, and are useful for
|
|
some situations, such as allowing each component used in an
|
|
application to refer to a common dependency using a bean name that
|
|
is specific to that component itself.</para>
|
|
|
|
<para>Having to specify all aliases when the bean is actually
|
|
defined is not always adequate however. It is sometimes desirable to
|
|
introduce an alias for a bean which is defined elsewhere. In
|
|
XML-based configuration metadata this may be accomplished via the
|
|
use of the <literal><alias/></literal> element.</para>
|
|
|
|
<programlisting language="xml"><alias name="fromName" alias="toName"/></programlisting>
|
|
|
|
<para>In this case, a bean in the same container which is named
|
|
<literal>'fromName'</literal>, may also after the use of this alias
|
|
definition, be referred to as <literal>'toName'</literal>.</para>
|
|
|
|
<para>As a concrete example, consider the case where component A
|
|
defines a DataSource bean called componentA-dataSource, in its XML
|
|
fragment. Component B would however like to refer to the DataSource
|
|
as componentB-dataSource in its XML fragment. And the main
|
|
application, MyApp, defines its own XML fragment and assembles the
|
|
final application context from all three fragments, and would like
|
|
to refer to the DataSource as myApp-dataSource. This scenario can be
|
|
easily handled by adding to the MyApp XML fragment the following
|
|
standalone aliases:</para>
|
|
|
|
<programlisting language="xml"><alias name="componentA-dataSource" alias="componentB-dataSource"/>
|
|
<alias name="componentA-dataSource" alias="myApp-dataSource" /></programlisting>
|
|
|
|
<para>Now each component and the main application can refer to the
|
|
dataSource via a name that is unique and guaranteed not to clash
|
|
with any other definition (effectively there is a namespace), yet
|
|
they refer to the same bean.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-class">
|
|
<title>Instantiating beans</title>
|
|
|
|
<sidebar>
|
|
<title>Inner class names</title>
|
|
|
|
<para>If for whatever reason you want to configure a bean definition
|
|
for a <literal>static</literal> inner class, you have to use the
|
|
<emphasis>binary</emphasis> name of the inner class.</para>
|
|
|
|
<para>For example, if you have a class called
|
|
<classname>Foo</classname> in the <literal>com.example</literal>
|
|
package, and this <classname>Foo</classname> class has a
|
|
<literal>static</literal> inner class called
|
|
<classname>Bar</classname>, the value of the
|
|
<literal>'class'</literal> attribute on a bean definition would
|
|
be...</para>
|
|
|
|
<para><classname>com.example.Foo$Bar</classname></para>
|
|
|
|
<para>Notice the use of the <literal>$</literal> character in the
|
|
name to separate the inner class name from the outer class
|
|
name.</para>
|
|
</sidebar>
|
|
|
|
<para>A bean definition essentially is a recipe for creating one or
|
|
more objects. The container looks at the recipe for a named bean when
|
|
asked, and uses the configuration metadata encapsulated by that bean
|
|
definition to create (or acquire) an actual object.</para>
|
|
|
|
<para>If you are using XML-based configuration metadata, you can
|
|
specify the type (or class) of object that is to be instantiated using
|
|
the <literal>'class'</literal> attribute of the
|
|
<literal><bean/></literal> element. This
|
|
<literal>'class'</literal> attribute (which internally eventually
|
|
boils down to being a <classname>Class</classname> property on a
|
|
<interfacename>BeanDefinition</interfacename> instance) is normally
|
|
mandatory (see <xref
|
|
linkend="beans-factory-class-instance-factory-method" /> and <xref
|
|
linkend="beans-child-bean-definitions" /> for the two exceptions) and
|
|
is used for one of two purposes. The class property specifies the
|
|
class of the bean to be constructed in the common case where the
|
|
container itself directly creates the bean by calling its constructor
|
|
reflectively (somewhat equivalent to Java code using the
|
|
<emphasis>'new'</emphasis> operator). In the less common case where
|
|
the container invokes a <literal>static</literal>,
|
|
<emphasis>factory</emphasis> method on a class to create the bean, the
|
|
class property specifies the actual class containing the
|
|
<literal>static</literal> factory method that is to be invoked to
|
|
create the object (the type of the object returned from the invocation
|
|
of the <literal>static</literal> factory method may be the same class
|
|
or another class entirely, it doesn't matter).</para>
|
|
|
|
<section id="beans-factory-class-ctor">
|
|
<title>Instantiation using a constructor</title>
|
|
|
|
<para>When creating a bean using the constructor approach, all
|
|
normal classes are usable by and compatible with Spring. That is,
|
|
the class being created does not need to implement any specific
|
|
interfaces or be coded in a specific fashion. Just specifying the
|
|
bean class should be enough. However, depending on what type of IoC
|
|
you are going to use for that specific bean, you may need a default
|
|
(empty) constructor.</para>
|
|
|
|
<para>Additionally, the Spring IoC container isn't limited to just
|
|
managing true JavaBeans, it is also able to manage virtually
|
|
<emphasis>any</emphasis> class you want it to manage. Most people
|
|
using Spring prefer to have actual JavaBeans (having just a default
|
|
(no-argument) constructor and appropriate setters and getters
|
|
modeled after the properties) in the container, but it is also
|
|
possible to have more exotic non-bean-style classes in your
|
|
container. If, for example, you need to use a legacy connection pool
|
|
that absolutely does not adhere to the JavaBean specification,
|
|
Spring can manage it as well.</para>
|
|
|
|
<para>When using XML-based configuration metadata you can specify
|
|
your bean class like so:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"/>
|
|
|
|
<bean name="anotherExample" class="examples.ExampleBeanTwo"/></programlisting>
|
|
|
|
<para>The mechanism for supplying arguments to the constructor (if
|
|
required), or setting properties of the object instance after it has
|
|
been constructed, <link linkend="beans-factory-collaborators">is
|
|
described shortly</link>.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-class-static-factory-method">
|
|
<title>Instantiation using a static factory method</title>
|
|
|
|
<para>When defining a bean which is to be created using a static
|
|
factory method, along with the <literal>class</literal> attribute
|
|
which specifies the class containing the <literal>static</literal>
|
|
factory method, another attribute named
|
|
<literal>factory-method</literal> is needed to specify the name of
|
|
the factory method itself. Spring expects to be able to call this
|
|
method (with an optional list of arguments as described later) and
|
|
get back a live object, which from that point on is treated as if it
|
|
had been created normally via a constructor. One use for such a bean
|
|
definition is to call <literal>static</literal> factories in legacy
|
|
code.</para>
|
|
|
|
<para>The following example shows a bean definition which specifies
|
|
that the bean is to be created by calling a factory-method. Note
|
|
that the definition does not specify the type (class) of the
|
|
returned object, only the class containing the factory method. In
|
|
this example, the <methodname>createInstance()</methodname> method
|
|
must be a <emphasis>static</emphasis> method.</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean"
|
|
class="examples.ExampleBean2"
|
|
factory-method="createInstance"/></programlisting>
|
|
|
|
<para>The mechanism for supplying (optional) arguments to the
|
|
factory method, or setting properties of the object instance after
|
|
it has been returned from the factory, will be <link
|
|
linkend="beans-factory-properties-detailed">described
|
|
shortly</link>.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-class-instance-factory-method">
|
|
<title>Instantiation using an instance factory method</title>
|
|
|
|
<para>In a fashion similar to instantiation via a <link
|
|
linkend="beans-factory-class-static-factory-method">static factory
|
|
method</link>, instantiation using an instance factory method is
|
|
where a non-static method of an existing bean from the container is
|
|
invoked to create a new bean. To use this mechanism, the
|
|
<literal>'class'</literal> attribute must be left empty, and the
|
|
<literal>'factory-bean'</literal> attribute must specify the name of
|
|
a bean in the current (or parent/ancestor) container that contains
|
|
the instance method that is to be invoked to create the object. The
|
|
name of the factory method itself must be set using the
|
|
<literal>'factory-method'</literal> attribute.</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- the factory bean, which contains a method called <methodname>createInstance()</methodname> --></lineannotation>
|
|
<bean id="serviceLocator" class="com.foo.DefaultServiceLocator">
|
|
<lineannotation><!-- inject any dependencies required by this locator bean --></lineannotation>
|
|
</bean>
|
|
|
|
<lineannotation><!-- the bean to be created via the factory bean --></lineannotation>
|
|
<bean id="exampleBean"
|
|
factory-bean="serviceLocator"
|
|
factory-method="createInstance"/></programlisting>
|
|
|
|
<para>Although the mechanisms for <link
|
|
linkend="beans-factory-properties-detailed">setting bean
|
|
properties</link> are still to be discussed, one implication of this
|
|
approach is that the factory bean itself can be managed and
|
|
configured via DI.</para>
|
|
|
|
<note>
|
|
<para>When the Spring documentation makes mention of a 'factory
|
|
bean', this will be a reference to a bean that is configured in
|
|
the Spring container that will create objects via an <link
|
|
linkend="beans-factory-class-instance-factory-method">instance</link>
|
|
or <link
|
|
linkend="beans-factory-class-static-factory-method">static</link>
|
|
factory method. When the documentation mentions a
|
|
<interfacename>FactoryBean</interfacename> (notice the
|
|
capitalization) this is a reference to a Spring-specific <link
|
|
linkend="beans-factory-extension-factorybean">
|
|
<interfacename>FactoryBean</interfacename> </link>.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-client">
|
|
<title>Using the container</title>
|
|
|
|
<para>A <interfacename>BeanFactory</interfacename> is essentially
|
|
nothing more than the interface for an advanced factory capable of
|
|
maintaining a registry of different beans and their dependencies. The
|
|
<interfacename>BeanFactory</interfacename> enables you to read bean
|
|
definitions and access them using the bean factory. When using just the
|
|
<interfacename>BeanFactory</interfacename> you would create one and read
|
|
in some bean definitions in the XML format as follows:</para>
|
|
|
|
<programlisting language="java">Resource res = new FileSystemResource("beans.xml");
|
|
BeanFactory factory = new XmlBeanFactory(res);</programlisting>
|
|
|
|
<para>Basically that is all there is to it. Using
|
|
<methodname>getBean(String)</methodname> you can retrieve instances of
|
|
your beans; the client-side view of the
|
|
<interfacename>BeanFactory</interfacename> is simple. The
|
|
<interfacename>BeanFactory</interfacename> interface has just a few
|
|
other methods, but ideally your application code should never use
|
|
them... indeed, your application code should have no calls to the
|
|
<methodname>getBean(String)</methodname> method at all, and thus no
|
|
dependency on Spring APIs at all.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-dependencies">
|
|
<title>Dependencies</title>
|
|
|
|
<para>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).</para>
|
|
|
|
<section id="beans-factory-collaborators">
|
|
<title>Injecting dependencies</title>
|
|
|
|
<para>The basic principle behind <emphasis>Dependency
|
|
Injection</emphasis> (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 <emphasis>inject</emphasis> those dependencies when it creates
|
|
the bean. This is fundamentally the inverse, hence the name
|
|
<emphasis>Inversion of Control</emphasis> (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
|
|
<emphasis>Service Locator</emphasis> pattern.</para>
|
|
|
|
<para>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 <link
|
|
linkend="beans-constructor-injection">Constructor Injection</link> and
|
|
<link linkend="beans-setter-injection">Setter Injection</link>.</para>
|
|
|
|
<section id="beans-constructor-injection">
|
|
<title>Constructor Injection</title>
|
|
|
|
<para><emphasis>Constructor-based</emphasis> DI is effected by
|
|
invoking a constructor with a number of arguments, each representing a
|
|
dependency. Additionally, calling a <literal>static</literal> 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
|
|
<literal>static</literal> factory method similarly. Find below an
|
|
example of a class that could only be dependency injected using
|
|
constructor injection. Notice that there is nothing
|
|
<emphasis>special</emphasis> about this class.</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on a <interfacename>MovieFinder</interfacename></lineannotation>
|
|
private MovieFinder movieFinder;
|
|
|
|
<lineannotation>// a constructor so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation>
|
|
public SimpleMovieLister(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<section id="beans-factory-ctor-arguments-resolution">
|
|
<title>Constructor Argument Resolution</title>
|
|
|
|
<para>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:</para>
|
|
|
|
<programlisting language="java">package x.y;
|
|
|
|
public class Foo {
|
|
|
|
public Foo(Bar bar, Baz baz) {
|
|
<lineannotation>// ...</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>There is no potential for ambiguity here (assuming of course
|
|
that <classname>Bar</classname> and <classname>Baz</classname>
|
|
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.</para>
|
|
|
|
<programlisting language="xml"><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></programlisting>
|
|
|
|
<para>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
|
|
<literal><value>true<value></literal>, Spring cannot
|
|
determine the type of the value, and so cannot match by type without
|
|
help. Consider the following class:</para>
|
|
|
|
<programlisting language="java">package examples;
|
|
|
|
public class ExampleBean {
|
|
|
|
<lineannotation>// No. of years to the calculate the Ultimate Answer</lineannotation>
|
|
private int years;
|
|
|
|
<lineannotation>// The Answer to Life, the Universe, and Everything</lineannotation>
|
|
private String ultimateAnswer;
|
|
|
|
public ExampleBean(int years, String ultimateAnswer) {
|
|
this.years = years;
|
|
this.ultimateAnswer = ultimateAnswer;
|
|
}
|
|
}</programlisting>
|
|
|
|
<section id="beans-factory-ctor-arguments-type">
|
|
<title>Constructor Argument Type Matching</title>
|
|
|
|
<para>The above scenario <emphasis>can</emphasis> use type
|
|
matching with simple types by explicitly specifying the type of
|
|
the constructor argument using the <literal>'type'</literal>
|
|
attribute. For example:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean">
|
|
<constructor-arg type="int" value="7500000"/>
|
|
<constructor-arg type="java.lang.String" value="42"/>
|
|
</bean></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-factory-ctor-arguments-index">
|
|
<title>Constructor Argument Index</title>
|
|
|
|
<para>Constructor arguments can have their index specified
|
|
explicitly by use of the <literal>index</literal> attribute. For
|
|
example:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean">
|
|
<constructor-arg index="0" value="7500000"/>
|
|
<constructor-arg index="1" value="42"/>
|
|
</bean></programlisting>
|
|
|
|
<para>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 <emphasis>index is 0 based</emphasis>.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-setter-injection">
|
|
<title>Setter Injection</title>
|
|
|
|
<para><emphasis>Setter-based</emphasis> DI is realized by calling
|
|
setter methods on your beans after invoking a no-argument constructor
|
|
or no-argument <literal>static</literal> factory method to instantiate
|
|
your bean.</para>
|
|
|
|
<para>Find below an example of a class that can only be dependency
|
|
injected using pure setter injection. Note that there is nothing
|
|
<emphasis>special</emphasis> about this class... it is plain old
|
|
Java.</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on the <interfacename>MovieFinder</interfacename></lineannotation>
|
|
private MovieFinder movieFinder;
|
|
|
|
<lineannotation>// a setter method so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation>
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<sidebar>
|
|
<title>Constructor- or Setter-based DI?</title>
|
|
|
|
<para>The Spring team generally advocates the usage of setter
|
|
injection, since a large number of constructor arguments can get
|
|
unwieldy, especially when some properties are optional. The presence
|
|
of setter methods also makes objects of that class amenable to being
|
|
re-configured (or re-injected) at some later time (for management
|
|
via <link linkend="jmx">JMX MBeans</link> is a particularly
|
|
compelling use case).</para>
|
|
|
|
<para>Constructor-injection is favored by some purists though (and
|
|
with good reason). Supplying all of an object's dependencies means
|
|
that that object is never returned to client (calling) code in a
|
|
less than totally initialized state. The flip side is that the
|
|
object becomes less amenable to re-configuration (or
|
|
re-injection).</para>
|
|
|
|
<para>There is no hard and fast rule here. Use whatever type of DI
|
|
makes the most sense for a particular class; sometimes, when dealing
|
|
with third party classes to which you do not have the source, the
|
|
choice will already have been made for you - a legacy class may not
|
|
expose any setter methods, and so constructor injection will be the
|
|
only type of DI available to you.</para>
|
|
</sidebar>
|
|
|
|
<para>The <interfacename>BeanFactory</interfacename> 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
|
|
<interfacename>BeanDefinition</interfacename>, which is used together
|
|
with <interfacename>PropertyEditor</interfacename> 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.</para>
|
|
|
|
<para>Bean dependency resolution generally happens as follows:</para>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>The <interfacename>BeanFactory</interfacename> is created
|
|
and initialized with a configuration which describes all the
|
|
beans. (Most Spring users use a
|
|
<interfacename>BeanFactory</interfacename> or
|
|
<interfacename>ApplicationContext</interfacename> implementation
|
|
that supports XML format configuration files.)</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>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,
|
|
<emphasis>when the bean is actually created</emphasis>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each property or constructor argument is either an actual
|
|
definition of the value to set, or a reference to another bean in
|
|
the container.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><anchor id="beans-factory-collaborators-propertyeditor" />
|
|
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 <literal>int</literal>,
|
|
<literal>long</literal>, <literal>String</literal>,
|
|
<literal>boolean</literal>, etc.</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<para>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
|
|
<emphasis>is actually created</emphasis>. For those beans that are
|
|
singleton-scoped and set to be pre-instantiated (such as singleton
|
|
beans in an <interfacename>ApplicationContext</interfacename>),
|
|
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.</para>
|
|
|
|
<sidebar>
|
|
<title>Circular dependencies</title>
|
|
|
|
<para>If you are using predominantly constructor injection it is
|
|
possible to write and configure your classes and beans such that an
|
|
unresolvable circular dependency scenario is created.</para>
|
|
|
|
<para>Consider the scenario where you have class A, which requires
|
|
an instance of class B to be provided via constructor injection, and
|
|
class B, which requires an instance of class A to be provided via
|
|
constructor injection. If you configure beans for classes A and B to
|
|
be injected into each other, the Spring IoC container will detect
|
|
this circular reference at runtime, and throw a
|
|
<classname>BeanCurrentlyInCreationException</classname>.</para>
|
|
|
|
<para>One possible solution to this issue is to edit the source code
|
|
of some of your classes to be configured via setters instead of via
|
|
constructors. Another solution is not to use constructor injection
|
|
and stick to setter injection only. In other words, while it should
|
|
generally be avoided in all but the rarest of circumstances, it is
|
|
possible to configure circular dependencies with setter
|
|
injection.</para>
|
|
|
|
<para>Unlike the <emphasis>typical</emphasis> case (with no circular
|
|
dependencies), a circular dependency between bean A and bean B will
|
|
force one of the beans to be injected into the other prior to being
|
|
fully initialized itself (a classic chicken/egg scenario).</para>
|
|
</sidebar>
|
|
|
|
<para>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 <interfacename>ApplicationContext</interfacename> 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
|
|
<interfacename>ApplicationContext</interfacename> 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).</para>
|
|
|
|
<para>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 <emphasis>totally</emphasis> 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
|
|
<emphasis>totally</emphasis> configure bean B prior to invoking the
|
|
setter method on bean A; you can read '<emphasis>totally
|
|
configure</emphasis>' 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 <link
|
|
linkend="beans-factory-lifecycle-initializingbean">configured init
|
|
method</link> or the <link
|
|
linkend="beans-factory-lifecycle-initializingbean">IntializingBean
|
|
callback method</link>) will all be invoked.</para>
|
|
</section>
|
|
|
|
<section id="beans-some-examples">
|
|
<title>Some examples</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean">
|
|
|
|
<lineannotation><!-- setter injection using the nested <literal><ref/></literal> element --></lineannotation>
|
|
<property name="beanOne"><ref bean="anotherExampleBean"/></property>
|
|
|
|
<lineannotation><!-- setter injection using the neater 'ref' attribute --></lineannotation>
|
|
<property name="beanTwo" ref="yetAnotherBean"/>
|
|
<property name="integerProperty" value="1"/>
|
|
</bean>
|
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
|
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting>
|
|
|
|
<programlisting language="java">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;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>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.</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean">
|
|
|
|
<lineannotation><!-- constructor injection using the nested <literal><ref/></literal> element --></lineannotation>
|
|
<constructor-arg>
|
|
<ref bean="anotherExampleBean"/>
|
|
</constructor-arg>
|
|
|
|
<lineannotation><!-- constructor injection using the neater 'ref' attribute --></lineannotation>
|
|
<constructor-arg ref="yetAnotherBean"/>
|
|
|
|
<constructor-arg type="int" value="1"/>
|
|
</bean>
|
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
|
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting>
|
|
|
|
<programlisting language="java">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;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>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 <classname>ExampleBean</classname>.</para>
|
|
|
|
<para>Now consider a variant of this where instead of using a
|
|
constructor, Spring is told to call a <literal>static</literal>
|
|
factory method to return an instance of the object:</para>
|
|
|
|
<programlisting language="xml"><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"/></programlisting>
|
|
|
|
<programlisting language="java">public class ExampleBean {
|
|
|
|
<lineannotation>// a private constructor</lineannotation>
|
|
private ExampleBean(...) {
|
|
...
|
|
}
|
|
<lineannotation>
|
|
// 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.</lineannotation>
|
|
public static ExampleBean createInstance (
|
|
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
|
|
|
|
ExampleBean eb = new ExampleBean (...);
|
|
<lineannotation>// some other operations...</lineannotation>
|
|
return eb;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Note that arguments to the <literal>static</literal> factory
|
|
method are supplied via <literal><constructor-arg/></literal>
|
|
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 <literal>static</literal> 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 <literal>factory-bean</literal> attribute instead of
|
|
the <literal>class</literal> attribute), so details will not be
|
|
discussed here.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-properties-detailed">
|
|
<title>Dependencies and configuration in detail</title>
|
|
|
|
<para>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 <literal><property/></literal> and
|
|
<literal><constructor-arg/></literal> elements for just this
|
|
purpose.</para>
|
|
|
|
<section id="beans-value-element">
|
|
<title>Straight values (primitives, <literal>Strings</literal>,
|
|
etc.)</title>
|
|
|
|
<para>The <literal><value/></literal> element specifies a
|
|
property or constructor argument as a human-readable string
|
|
representation. <link
|
|
linkend="beans-factory-collaborators-propertyeditor">As mentioned
|
|
previously</link>, JavaBeans <literal>PropertyEditors</literal> are
|
|
used to convert these string values from a
|
|
<classname>String</classname> to the actual type of the property or
|
|
argument.</para>
|
|
|
|
<programlisting language="xml"><bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
|
|
|
<lineannotation><!-- results in a <methodname>setDriverClassName(String)</methodname> call --></lineannotation>
|
|
<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></programlisting>
|
|
|
|
<para>The <literal><property/></literal> and
|
|
<literal><constructor-arg/></literal> elements also support the
|
|
use of the <literal>'value'</literal> attribute, which can lead to
|
|
much more succinct configuration. When using the
|
|
<literal>'value'</literal> attribute, the above bean definition reads
|
|
like so:</para>
|
|
|
|
<programlisting language="xml"><bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
|
|
|
<lineannotation><!-- results in a <methodname>setDriverClassName(String)</methodname> call --></lineannotation>
|
|
<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></programlisting>
|
|
|
|
<para>The Spring team generally prefer the attribute style over the
|
|
use of nested <literal><value/></literal> 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 <classname>java.util.Properties</classname>
|
|
instance like so:</para>
|
|
|
|
<programlisting language="xml"><bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
|
|
|
<lineannotation><!-- typed as a <classname>java.util.Properties</classname> --></lineannotation>
|
|
<property name="properties">
|
|
<value>
|
|
jdbc.driver.className=com.mysql.jdbc.Driver
|
|
jdbc.url=jdbc:mysql://localhost:3306/mydb
|
|
</value>
|
|
</property>
|
|
</bean></programlisting>
|
|
|
|
<para>Can you see what is happening? The Spring container is
|
|
converting the text inside the <literal><value/></literal>
|
|
element into a <classname>java.util.Properties</classname> instance
|
|
using the JavaBeans <interfacename>PropertyEditor</interfacename>
|
|
mechanism. This is a nice shortcut, and is one of a few places where
|
|
the Spring team do favor the use of the nested
|
|
<literal><value/></literal> element over the
|
|
<literal>'value'</literal> attribute style.</para>
|
|
|
|
<section id="beans-idref-element">
|
|
<title>The <literal>idref</literal> element</title>
|
|
|
|
<para>The <literal>idref</literal> element is simply an error-proof
|
|
way to pass the <emphasis>id</emphasis> of another bean in the
|
|
container (to a <literal><constructor-arg/></literal> or
|
|
<literal><property/></literal> element).</para>
|
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..."/>
|
|
|
|
<bean id="theClientBean" class="...">
|
|
<property name="targetName">
|
|
<idref bean="theTargetBean" />
|
|
</property>
|
|
</bean></programlisting>
|
|
|
|
<para>The above bean definition snippet is
|
|
<emphasis>exactly</emphasis> equivalent (at runtime) to the
|
|
following snippet:</para>
|
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..." />
|
|
|
|
<bean id="client" class="...">
|
|
<property name="targetName" value="theTargetBean" />
|
|
</bean></programlisting>
|
|
|
|
<para>The main reason the first form is preferable to the second is
|
|
that using the <literal>idref</literal> tag allows the container to
|
|
validate <emphasis>at deployment time</emphasis> that the
|
|
referenced, named bean actually exists. In the second variation, no
|
|
validation is performed on the value that is passed to the
|
|
<literal>'targetName'</literal> property of the
|
|
<literal>'client'</literal> bean. Any typo will only be discovered
|
|
(with most likely fatal results) when the
|
|
<literal>'client'</literal> bean is actually instantiated. If the
|
|
<literal>'client'</literal> bean is a <link
|
|
linkend="beans-factory-scopes">prototype</link> bean, this typo (and
|
|
the resulting exception) may only be discovered long after the
|
|
container is actually deployed.</para>
|
|
|
|
<para>Additionally, if the bean being referred to is in the same XML
|
|
unit, and the bean name is the bean <emphasis>id</emphasis>, the
|
|
<literal>'local'</literal> attribute may be used, which allows the
|
|
XML parser itself to validate the bean id even earlier, at XML
|
|
document parse time.</para>
|
|
|
|
<programlisting language="xml"><property name="targetName">
|
|
<lineannotation><!-- a bean with an id of '<literal>theTargetBean</literal>' must exist; otherwise an XML exception will be thrown --></lineannotation>
|
|
<idref local="theTargetBean"/>
|
|
</property></programlisting>
|
|
|
|
<para>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 <link linkend="aop-pfb-1">AOP
|
|
interceptors</link> in a <classname>ProxyFactoryBean</classname>
|
|
bean definition. If you use <idref/> elements when specifying
|
|
the interceptor names, there is no chance of inadvertently
|
|
misspelling an interceptor id.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-ref-element">
|
|
<title>References to other beans (collaborators)</title>
|
|
|
|
<para>The <literal>ref</literal> element is the final element allowed
|
|
inside a <literal><constructor-arg/></literal> or
|
|
<literal><property/></literal> 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.</para>
|
|
|
|
<para>Specifying the target bean by using the <literal>bean</literal>
|
|
attribute of the <literal><ref/></literal> 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 <literal>'bean'</literal> attribute may be
|
|
the same as either the <literal>'id'</literal> attribute of the target
|
|
bean, or one of the values in the <literal>'name'</literal> attribute
|
|
of the target bean.</para>
|
|
|
|
<programlisting language="xml"><ref bean="someBean"/></programlisting>
|
|
|
|
<para>Specifying the target bean by using the <literal>local</literal>
|
|
attribute leverages the ability of the XML parser to validate XML id
|
|
references within the same file. The value of the
|
|
<literal>local</literal> attribute must be the same as the
|
|
<literal>id</literal> 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.</para>
|
|
|
|
<programlisting language="xml"><ref local="someBean"/></programlisting>
|
|
|
|
<para>Specifying the target bean by using the
|
|
<literal>'parent'</literal> attribute allows a reference to be created
|
|
to a bean which is in a parent container of the current container. The
|
|
value of the <literal>'parent'</literal> attribute may be the same as
|
|
either the <literal>'id'</literal> attribute of the target bean, or
|
|
one of the values in the <literal>'name'</literal> 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.</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- in the parent context --></lineannotation>
|
|
<bean id="accountService" class="com.foo.SimpleAccountService">
|
|
<lineannotation><!-- insert dependencies as required as here --></lineannotation>
|
|
</bean></programlisting>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- in the child (descendant) context --></lineannotation>
|
|
<bean id="accountService" <lineannotation><-- notice that the name of this bean is the <emphasis
|
|
role="bold">same</emphasis> as the name of the <literal>'parent'</literal> bean</lineannotation>
|
|
class="org.springframework.aop.framework.ProxyFactoryBean">
|
|
<property name="target">
|
|
<ref parent="accountService"/> <lineannotation><-- notice how we refer to the <emphasis
|
|
role="bold">parent</emphasis> bean</lineannotation>
|
|
</property>
|
|
<lineannotation><!-- insert other configuration and dependencies as required as here --></lineannotation>
|
|
</bean></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-inner-beans">
|
|
<title>Inner beans</title>
|
|
|
|
<para>A <literal><bean/></literal> element inside the
|
|
<literal><property/></literal> or
|
|
<literal><constructor-arg/></literal> elements is used to define
|
|
a so-called <firstterm>inner bean</firstterm>. 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.</para>
|
|
|
|
<programlisting language="xml"><bean id="outer" class="...">
|
|
<lineannotation><!-- instead of using a reference to a target bean, simply define the target bean inline --></lineannotation>
|
|
<property name="target">
|
|
<bean class="com.example.Person"> <lineannotation><!-- this is the inner bean --></lineannotation>
|
|
<property name="name" value="Fiona Apple"/>
|
|
<property name="age" value="25"/>
|
|
</bean>
|
|
</property>
|
|
</bean></programlisting>
|
|
|
|
<para>Note that in the specific case of inner beans, the
|
|
<literal>'scope'</literal> flag and any <literal>'id'</literal> or
|
|
<literal>'name'</literal> attribute are effectively ignored. Inner
|
|
beans are <emphasis>always</emphasis> anonymous and they are
|
|
<emphasis>always</emphasis> scoped as <link
|
|
linkend="beans-factory-scopes-prototype">prototypes</link>. Please
|
|
also note that it is <emphasis>not</emphasis> possible to inject inner
|
|
beans into collaborating beans other than the enclosing bean.</para>
|
|
</section>
|
|
|
|
<section id="beans-collection-elements">
|
|
<title>Collections</title>
|
|
|
|
<para>The <literal><list/></literal>,
|
|
<literal><set/></literal>, <literal><map/></literal>, and
|
|
<literal><props/></literal> elements allow properties and
|
|
arguments of the Java <interfacename>Collection</interfacename> type
|
|
<interfacename>List</interfacename>,
|
|
<interfacename>Set</interfacename>,
|
|
<interfacename>Map</interfacename>, and
|
|
<interfacename>Properties</interfacename>, respectively, to be defined
|
|
and set.</para>
|
|
|
|
<programlisting language="xml"><bean id="moreComplexObject" class="example.ComplexObject">
|
|
<lineannotation><!-- results in a setAdminEmails(<classname>java.util.Properties</classname>) call --></lineannotation>
|
|
<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>
|
|
<lineannotation><!-- results in a setSomeList(<interfacename>java.util.List</interfacename>) call --></lineannotation>
|
|
<property name="someList">
|
|
<list>
|
|
<value>a list element followed by a reference</value>
|
|
<ref bean="myDataSource" />
|
|
</list>
|
|
</property>
|
|
<lineannotation><!-- results in a setSomeMap(<interfacename>java.util.Map</interfacename>) call --></lineannotation>
|
|
<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>
|
|
<lineannotation><!-- results in a setSomeSet(java.util.Set) call --></lineannotation>
|
|
<property name="someSet">
|
|
<set>
|
|
<value>just some string</value>
|
|
<ref bean="myDataSource" />
|
|
</set>
|
|
</property>
|
|
</bean></programlisting>
|
|
|
|
<note>
|
|
<para>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 <xref
|
|
linkend="xml-config-shortcuts" />.</para>
|
|
</note>
|
|
|
|
<para><emphasis>Note that the value of a map key or value, or a set
|
|
value, can also again be any of the following
|
|
elements:</emphasis></para>
|
|
|
|
<programlisting language="xml">bean | ref | idref | list | set | map | props | value | null</programlisting>
|
|
|
|
<section id="beans-collection-elements-merging">
|
|
<title>Collection merging</title>
|
|
|
|
<para>As of Spring 2.0, the container also supports the
|
|
<emphasis>merging</emphasis> of collections. This allows an
|
|
application developer to define a parent-style
|
|
<literal><list/></literal>, <literal><map/></literal>,
|
|
<literal><set/></literal> or <literal><props/></literal>
|
|
element, and have child-style <literal><list/></literal>,
|
|
<literal><map/></literal>, <literal><set/></literal> or
|
|
<literal><props/></literal> 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.</para>
|
|
|
|
<para><emphasis>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 <link
|
|
linkend="beans-child-bean-definitions">relevant section</link>
|
|
before continuing.</emphasis></para>
|
|
|
|
<para>Find below an example of the collection merging
|
|
feature:</para>
|
|
|
|
<programlisting language="xml"><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">
|
|
<lineannotation><!-- the merge is specified on the *child* collection definition --></lineannotation>
|
|
<props merge="true">
|
|
<prop key="sales">sales@example.com</prop>
|
|
<prop key="support">support@example.co.uk</prop>
|
|
</props>
|
|
</property>
|
|
</bean>
|
|
<beans></programlisting>
|
|
|
|
<para>Notice the use of the <literal>merge=true</literal> attribute
|
|
on the <literal><props/></literal> element of the
|
|
<literal>adminEmails</literal> property of the
|
|
<literal>child</literal> bean definition. When the
|
|
<literal>child</literal> bean is actually resolved and instantiated
|
|
by the container, the resulting instance will have an
|
|
<literal>adminEmails</literal> <classname>Properties</classname>
|
|
collection that contains the result of the merging of the child's
|
|
<literal>adminEmails</literal> collection with the parent's
|
|
<literal>adminEmails</literal> collection.</para>
|
|
|
|
<programlisting>administrator=administrator@example.com
|
|
sales=sales@example.com
|
|
support=support@example.co.uk</programlisting>
|
|
|
|
<para>Notice how the child <classname>Properties</classname>
|
|
collection's value set will have inherited all the property elements
|
|
from the parent <literal><props/></literal>. Notice also how
|
|
the child's value for the <literal>support</literal> value overrides
|
|
the value in the parent collection.</para>
|
|
|
|
<para>This merging behavior applies similarly to the
|
|
<literal><list/></literal>, <literal><map/></literal>,
|
|
and <literal><set/></literal> collection types. In the
|
|
specific case of the <literal><list/></literal> element, the
|
|
semantics associated with the <classname>List</classname> collection
|
|
type, that is the notion of an <literal>ordered</literal> collection
|
|
of values, is maintained; the parent's values will precede all of
|
|
the child list's values. In the case of the
|
|
<interfacename>Map</interfacename>,
|
|
<interfacename>Set</interfacename>, and
|
|
<interfacename>Properties</interfacename> collection types, there is
|
|
no notion of ordering and hence no ordering semantics are in effect
|
|
for the collection types that underlie the associated
|
|
<interfacename>Map</interfacename>,
|
|
<interfacename>Set</interfacename> and
|
|
<interfacename>Properties</interfacename> implementation types used
|
|
internally by the container.</para>
|
|
|
|
<para>Finally, some minor notes about the merging support are in
|
|
order; you cannot merge different collection types (e.g. a
|
|
<interfacename>Map</interfacename> and a
|
|
<interfacename>List</interfacename>), and if you do attempt to do so
|
|
an appropriate <classname>Exception</classname> will be thrown; and
|
|
in case it is not immediately obvious, the
|
|
<literal>'merge'</literal> attribute must be specified on the lower
|
|
level, inherited, child definition; specifying the
|
|
<literal>'merge'</literal> 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).</para>
|
|
</section>
|
|
|
|
<section id="beans-collection-elements-strongly-typed">
|
|
<title>Strongly-typed collection (Java 5+ only)</title>
|
|
|
|
<para>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
|
|
<interfacename>Collection</interfacename> type such that it can only
|
|
contain <classname>String</classname> elements (for example). If you
|
|
are using Spring to dependency inject a strongly-typed
|
|
<interfacename>Collection</interfacename> into a bean, you can take
|
|
advantage of Spring's type-conversion support such that the elements
|
|
of your strongly-typed <interfacename>Collection</interfacename>
|
|
instances will be converted to the appropriate type prior to being
|
|
added to the <interfacename>Collection</interfacename>.</para>
|
|
|
|
<programlisting language="java">public class Foo {
|
|
|
|
private Map<String, Float> accounts;
|
|
|
|
public void setAccounts(Map<String, Float> accounts) {
|
|
this.accounts = accounts;
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="xml"><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></programlisting>
|
|
|
|
<para>When the <literal>'accounts'</literal> property of the
|
|
<literal>'foo'</literal> bean is being prepared for injection, the
|
|
generics information about the element type of the strongly-typed
|
|
<classname>Map<String, Float></classname> is actually
|
|
available via reflection, and so Spring's type conversion
|
|
infrastructure will actually recognize the various value elements as
|
|
being of type <classname>Float</classname> and so the string values
|
|
<literal>'9.99', '2.75'</literal>, and <literal>'3.99'</literal>
|
|
will be converted into an actual <classname>Float</classname>
|
|
type.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-null-element">
|
|
<title><literal>Nulls</literal></title>
|
|
|
|
<para>The <literal><null/></literal> element is used to handle
|
|
<literal>null</literal> values. Spring treats empty arguments for
|
|
properties and the like as empty <literal>Strings</literal>. The
|
|
following XML-based configuration metadata snippet results in the
|
|
email property being set to the empty <classname>String</classname>
|
|
value ("")</para>
|
|
|
|
<programlisting language="xml"><bean class="ExampleBean">
|
|
<property name="email"><value/></property>
|
|
</bean></programlisting>
|
|
|
|
<para>This is equivalent to the following Java code:
|
|
<methodname>exampleBean.setEmail("")</methodname>. The special
|
|
<literal><null></literal> element may be used to indicate a
|
|
<literal>null</literal> value. For example:</para>
|
|
|
|
<programlisting language="xml"><bean class="ExampleBean">
|
|
<property name="email"><null/></property>
|
|
</bean></programlisting>
|
|
|
|
<para>The above configuration is equivalent to the following Java
|
|
code: <methodname>exampleBean.setEmail(null)</methodname>.</para>
|
|
</section>
|
|
|
|
<section id="xml-config-shortcuts">
|
|
<title>Shortcuts and other convenience options for XML-based
|
|
configuration metadata</title>
|
|
|
|
<para>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
|
|
<literal><property/></literal> definition. The second is
|
|
slightly different format of specifying properties altogether.</para>
|
|
|
|
<section id="beans-value-ref-shortcuts">
|
|
<title>XML-based configuration metadata shortcuts</title>
|
|
|
|
<para>The <literal><property/></literal>,
|
|
<literal><constructor-arg/></literal>, and
|
|
<literal><entry/></literal> elements all support a
|
|
<literal>'value'</literal> attribute which may be used instead of
|
|
embedding a full <literal><value/></literal> element.
|
|
Therefore, the following:</para>
|
|
|
|
<programlisting language="xml"><property name="myProperty">
|
|
<value>hello</value>
|
|
</property></programlisting>
|
|
|
|
<programlisting language="xml"><constructor-arg>
|
|
<value>hello</value>
|
|
</constructor-arg></programlisting>
|
|
|
|
<programlisting language="xml"><entry key="myKey">
|
|
<value>hello</value>
|
|
</entry></programlisting>
|
|
|
|
<para>are equivalent to:</para>
|
|
|
|
<programlisting language="xml"><property name="myProperty" value="hello"/></programlisting>
|
|
|
|
<programlisting language="xml"><constructor-arg value="hello"/></programlisting>
|
|
|
|
<programlisting language="xml"><entry key="myKey" value="hello"/></programlisting>
|
|
|
|
<para>The <literal><property/></literal> and
|
|
<literal><constructor-arg/></literal> elements support a
|
|
similar shortcut <literal>'ref'</literal> attribute which may be
|
|
used instead of a full nested <literal><ref/></literal>
|
|
element. Therefore, the following:</para>
|
|
|
|
<programlisting language="xml"><property name="myProperty">
|
|
<ref bean="myBean">
|
|
</property></programlisting>
|
|
|
|
<programlisting language="xml"><constructor-arg>
|
|
<ref bean="myBean">
|
|
</constructor-arg></programlisting>
|
|
|
|
<para>... are equivalent to:</para>
|
|
|
|
<programlisting language="xml"><property name="myProperty" ref="myBean"/></programlisting>
|
|
|
|
<programlisting language="xml"><constructor-arg ref="myBean"/></programlisting>
|
|
|
|
<para>Note however that the shortcut form is equivalent to a
|
|
<literal><ref bean="xxx"></literal> element; there is no
|
|
shortcut for <literal><ref local="xxx"</literal>>. To enforce
|
|
a strict local reference, you must use the long form.</para>
|
|
|
|
<para>Finally, the entry element allows a shortcut form to specify
|
|
the key and/or value of the map, in the form of the
|
|
<literal>'key'</literal> / <literal>'key-ref'</literal> and
|
|
<literal>'value'</literal> / <literal>'value-ref'</literal>
|
|
attributes. Therefore, the following:</para>
|
|
|
|
<programlisting language="xml"><entry>
|
|
<key>
|
|
<ref bean="myKeyBean" />
|
|
</key>
|
|
<ref bean="myValueBean" />
|
|
</entry></programlisting>
|
|
|
|
<para>is equivalent to:</para>
|
|
|
|
<programlisting language="xml"><entry key-ref="myKeyBean" value-ref="myValueBean"/></programlisting>
|
|
|
|
<para>Again, the shortcut form is equivalent to a <literal><ref
|
|
bean="xxx"></literal> element; there is no shortcut for
|
|
<literal><ref local="xxx"</literal>>.</para>
|
|
</section>
|
|
|
|
<section id="beans-p-namespace">
|
|
<title>The p-namespace and how to use it to configure
|
|
properties</title>
|
|
|
|
<para>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 <link linkend="xsd-config">using
|
|
namespaces</link>. Those namespaces are all based on an XML Schema
|
|
definition. In fact, the <literal>beans</literal> configuration
|
|
format that you've been reading about is defined in an XML Schema
|
|
document.</para>
|
|
|
|
<para>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 <literal><property/></literal>
|
|
elements, using the p-namespace you can use attributes as part of
|
|
the <literal>bean</literal> element that describe your property
|
|
values. The values of the attributes will be taken as the values for
|
|
your properties.</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<programlisting language="xml"><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></programlisting>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>This next example includes two more bean definitions that both
|
|
have a reference to another bean:</para>
|
|
|
|
<programlisting language="xml"><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></programlisting>
|
|
|
|
<para>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
|
|
<literal><property name="spouse" ref="jane"/></literal> to
|
|
create a reference from bean <literal>john</literal> to bean
|
|
<literal>jane</literal>, the second bean definition uses
|
|
<literal>p:spouse-ref="jane"</literal> as an attribute to do the
|
|
exact same thing. In this case '<literal>spouse</literal>' is the
|
|
property name whereas the '<literal>-ref</literal>' part indicates
|
|
that this is not a straight value but rather a reference to another
|
|
bean.</para>
|
|
|
|
<note>
|
|
<para>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 '<literal>Ref</literal>', whereas the
|
|
standard XML format would have no problem there. We recommend that
|
|
you choose carefully which approach you are going to use in your
|
|
projects. You should also communicate this to your team members so
|
|
you won't end up with XML documents using all three approaches at
|
|
the same time. This will prevent people from not understanding the
|
|
application because of different ways of configuring it, and will
|
|
add to the overall consistency of your codebase.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-compound-property-names">
|
|
<title>Compound property names</title>
|
|
|
|
<para>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 <literal>null</literal>. Consider the
|
|
following bean definition...</para>
|
|
|
|
<programlisting language="xml"><bean id="foo" class="foo.Bar">
|
|
<property name="fred.bob.sammy" value="123" />
|
|
</bean></programlisting>
|
|
|
|
<para>The <literal>foo</literal> bean has a <literal>fred</literal>
|
|
property which has a <literal>bob</literal> property, which has a
|
|
<literal>sammy</literal> property, and that final
|
|
<literal>sammy</literal> property is being set to the value
|
|
<literal>123</literal>. In order for this to work, the
|
|
<literal>fred</literal> property of <literal>foo</literal>, and the
|
|
<literal>bob</literal> property of <literal>fred</literal> must not be
|
|
<literal>null</literal> be non-null after the bean is constructed, or
|
|
a <exceptionname>NullPointerException</exceptionname> will be
|
|
thrown.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-dependson">
|
|
<title>Using <literal>depends-on</literal></title>
|
|
|
|
<para>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 <link
|
|
linkend="beans-ref-element"><literal><ref/></literal>
|
|
element</link> 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
|
|
<literal>'depends-on'</literal> 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
|
|
<literal>'depends-on'</literal> attribute to express a dependency on a
|
|
single bean.</para>
|
|
|
|
<programlisting language="xml"><bean id="beanOne" class="ExampleBean" depends-on="<emphasis
|
|
role="bold">manager</emphasis>"/>
|
|
|
|
<bean id="<emphasis role="bold">manager</emphasis>" class="ManagerBean" /></programlisting>
|
|
|
|
<para>If you need to express a dependency on multiple beans, you can
|
|
supply a list of bean names as the value of the
|
|
<literal>'depends-on'</literal> attribute, with commas, whitespace and
|
|
semicolons all valid delimiters, like so:</para>
|
|
|
|
<programlisting language="xml"><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" /></programlisting>
|
|
|
|
<note>
|
|
<para>The '<literal>depends-on</literal>' attribute at the bean
|
|
definition level is used not only to specify an initialization time
|
|
dependency, but also to specify the corresponding destroy time
|
|
dependency (in the case of <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link> beans only).
|
|
Dependent beans that define a '<literal>depends-on</literal>'
|
|
relationship with a given bean will be destroyed first - prior to the
|
|
given bean itself being destroyed. As a consequence,
|
|
'<literal>depends-on</literal>' may be used to control shutdown order
|
|
too.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-factory-lazy-init">
|
|
<title>Lazily-instantiated beans</title>
|
|
|
|
<para>The default behavior for
|
|
<interfacename>ApplicationContext</interfacename> implementations is to
|
|
eagerly pre-instantiate all <literal>singleton</literal> beans at
|
|
startup. Pre-instantiation means that an
|
|
<interfacename>ApplicationContext</interfacename> will eagerly create
|
|
and configure all of its <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link> beans as part
|
|
of its initialization process. Generally this is <emphasis>a good
|
|
thing</emphasis>, 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).</para>
|
|
|
|
<para>However, there are times when this behavior is
|
|
<emphasis>not</emphasis> what is wanted. If you do not want a singleton
|
|
bean to be pre-instantiated when using an
|
|
<interfacename>ApplicationContext</interfacename>, 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.</para>
|
|
|
|
<para>When configuring beans via XML, this lazy loading is controlled by
|
|
the <literal>'lazy-init'</literal> attribute on the
|
|
<literal><bean/></literal> element; for example:</para>
|
|
|
|
<programlisting language="xml"><bean id="lazy" class="com.foo.ExpensiveToCreateBean" <emphasis
|
|
role="bold">lazy-init="true"</emphasis>/>
|
|
|
|
<bean name="not.lazy" class="com.foo.AnotherBean"/></programlisting>
|
|
|
|
<para>When the above configuration is consumed by an
|
|
<interfacename>ApplicationContext</interfacename>, the bean named
|
|
<literal>'lazy'</literal> will <emphasis>not</emphasis> be eagerly
|
|
pre-instantiated when the
|
|
<interfacename>ApplicationContext</interfacename> is starting up,
|
|
whereas the <literal>'not.lazy'</literal> bean will be eagerly
|
|
pre-instantiated.</para>
|
|
|
|
<para>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
|
|
<interfacename>ApplicationContext</interfacename> 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.</para>
|
|
|
|
<para>It is also possible to control lazy-initialization at the
|
|
container level by using the <literal>'default-lazy-init'</literal>
|
|
attribute on the <literal><beans/></literal> element; for
|
|
example:</para>
|
|
|
|
<programlisting language="xml"><beans default-lazy-init="true">
|
|
<lineannotation><!-- no beans will be pre-instantiated... --></lineannotation>
|
|
</beans></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-factory-autowire">
|
|
<title>Autowiring collaborators</title>
|
|
|
|
<para>The Spring container is able to <emphasis>autowire</emphasis>
|
|
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
|
|
<interfacename>BeanFactory</interfacename>. The autowiring functionality
|
|
has five modes. Autowiring is specified <emphasis>per</emphasis> 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. <footnote>
|
|
<para>See the section entitled <xref
|
|
linkend="beans-factory-collaborators" /></para>
|
|
</footnote> When using XML-based configuration metadata, the autowire
|
|
mode for a bean definition is specified by using the
|
|
<literal>autowire</literal> attribute of the
|
|
<literal><bean/></literal> element. The following values are
|
|
allowed:</para>
|
|
|
|
<table id="beans-factory-autowiring-modes-tbl">
|
|
<title>Autowiring modes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Mode</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>no</entry>
|
|
|
|
<entry><para>No autowiring at all. Bean references must be
|
|
defined via a <literal>ref</literal> element. This is the
|
|
default, and changing this is discouraged for larger
|
|
deployments, since explicitly specifying collaborators gives
|
|
greater control and clarity. To some extent, it is a form of
|
|
documentation about the structure of a system.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byName</entry>
|
|
|
|
<entry><para>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 <emphasis>master</emphasis> property (that is, it has
|
|
a <emphasis>setMaster(..)</emphasis> method), Spring will look
|
|
for a bean definition named <literal>master</literal>, and use
|
|
it to set the property.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byType</entry>
|
|
|
|
<entry><para>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 <emphasis>byType</emphasis>
|
|
autowiring for that bean. If there are no matching beans,
|
|
nothing happens; the property is not set. If this is not
|
|
desirable, setting the
|
|
<literal>dependency-check="objects"</literal> attribute value
|
|
specifies that an error should be thrown in this
|
|
case.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>constructor</entry>
|
|
|
|
<entry><para>This is analogous to <emphasis>byType</emphasis>,
|
|
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.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>autodetect</entry>
|
|
|
|
<entry><para>Chooses <emphasis>constructor</emphasis> or
|
|
<emphasis>byType</emphasis> through introspection of the bean
|
|
class. If a default constructor is found, the
|
|
<emphasis>byType</emphasis> mode will be applied.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>Note that explicit dependencies in <literal>property</literal> and
|
|
<literal>constructor-arg</literal> settings
|
|
<interfacename>always</interfacename> override autowiring. Please also
|
|
note that it is not currently possible to autowire so-called
|
|
<emphasis>simple</emphasis> properties such as primitives,
|
|
<classname>Strings</classname>, and <classname>Classes</classname> (and
|
|
arrays of such simple properties). (This is by-design and should be
|
|
considered a <emphasis>feature</emphasis>.) When using either the
|
|
<emphasis>byType</emphasis> or <emphasis>constructor</emphasis>
|
|
autowiring mode, it is possible to wire arrays and typed-collections. In
|
|
such cases <emphasis>all</emphasis> 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 <classname>String</classname>. 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.</para>
|
|
|
|
<para>Autowire behavior can be combined with dependency checking, which
|
|
will be performed after all autowiring has been completed.</para>
|
|
|
|
<para>It is important to understand the various advantages and
|
|
disadvantages of autowiring. Some advantages of autowiring
|
|
include:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring can significantly reduce the volume of
|
|
configuration required. However, mechanisms such as the use of a
|
|
bean template (<link
|
|
linkend="beans-child-bean-definitions">discussed elsewhere in this
|
|
chapter</link>) are also valuable in this regard.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>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.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Some disadvantages of autowiring:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>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.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Wiring information may not be available to tools that may
|
|
generate documentation from a Spring container.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>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
|
|
<literal>'autowire-candidate'</literal> attributes to
|
|
<literal>'false'</literal> as described in the next section. Third, you
|
|
may designate a single bean definition as the
|
|
<emphasis>primary</emphasis> candidate by setting the
|
|
<literal>'primary'</literal> attribute of its
|
|
<literal><bean/></literal> element to <literal>'true'</literal>.
|
|
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 <xref
|
|
linkend="beans-annotation-config" />.</para>
|
|
|
|
<para>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.</para>
|
|
|
|
<section id="beans-factory-autowire-candidate">
|
|
<title>Excluding a bean from being available for autowiring</title>
|
|
|
|
<para>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 <literal>'autowire-candidate'</literal> attribute of the
|
|
<literal><bean/></literal> element can be set to
|
|
<literal>'false'</literal>; this has the effect of making the
|
|
container totally exclude that specific bean definition from being
|
|
available to the autowiring infrastructure.</para>
|
|
|
|
<para>Another option is to limit autowire candidates based on
|
|
pattern-matching against bean names. The top-level
|
|
<literal><beans/></literal> element accepts one or more patterns
|
|
within its <literal>'default-autowire-candidates'</literal> attribute.
|
|
For example, to limit autowire candidate status to any bean whose name
|
|
ends with <emphasis>'Repository'</emphasis>, provide a value of
|
|
'*Repository'. To provide multiple patterns, define them in a
|
|
comma-separated list. Note that an explicit value of
|
|
<literal>'true'</literal> or <literal>'false'</literal> for a bean
|
|
definition's <literal>'autowire-candidate'</literal> attribute always
|
|
takes precedence, and for such beans, the pattern matching rules will
|
|
not apply.</para>
|
|
|
|
<para>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.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-dependencies">
|
|
<title>Checking for dependencies</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>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 <emphasis>not</emphasis> check dependencies. Dependency
|
|
checking can be handled in several different modes. When using XML-based
|
|
configuration metadata, this is specified via the
|
|
<literal>'dependency-check'</literal> attribute in a bean definition,
|
|
which may have the following values.</para>
|
|
|
|
<table id="beans-factory-dependency-check-modes-tbl">
|
|
<title>Dependency checking modes</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Mode</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>none</entry>
|
|
|
|
<entry><para>No dependency checking. Properties of the bean
|
|
which have no value specified for them are simply not
|
|
set.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>simple</entry>
|
|
|
|
<entry><para>Dependency checking is performed for primitive
|
|
types and collections (everything except
|
|
collaborators).</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>object</entry>
|
|
|
|
<entry><para>Dependency checking is performed for collaborators
|
|
only.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>all</entry>
|
|
|
|
<entry><para>Dependency checking is done for collaborators,
|
|
primitive types and collections.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>If you are using Java 5 and thus have access to source-level
|
|
annotations, you may find the section entitled <xref
|
|
linkend="metadata-annotations-required" /> to be of interest.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-method-injection">
|
|
<title>Method Injection</title>
|
|
|
|
<para>For most application scenarios, the majority of the beans in the
|
|
container will be <link
|
|
linkend="beans-factory-scopes-singleton">singletons</link>. 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.</para>
|
|
|
|
<para>One solution to this issue is to forego some inversion of control.
|
|
Bean A can be <link linkend="beans-factory-aware-beanfactoryaware">made
|
|
aware of the container</link> by implementing the
|
|
<interfacename>BeanFactoryAware</interfacename> interface, and <link
|
|
linkend="beans-factory-client">use programmatic means</link> to ask the
|
|
container via a <methodname>getBean("B")</methodname> call for (a
|
|
typically new) bean B instance every time it needs it. Find below an
|
|
admittedly somewhat contrived example of this approach:</para>
|
|
|
|
<programlisting language="java"><lineannotation>// a class that uses a stateful Command-style class to perform some processing</lineannotation>
|
|
package fiona.apple;
|
|
|
|
<lineannotation>// lots of Spring-API imports</lineannotation>
|
|
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) {
|
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename></lineannotation>
|
|
Command command = createCommand();
|
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation>
|
|
command.setState(commandState);
|
|
return command.execute();
|
|
}
|
|
|
|
<lineannotation>// the <interfacename>Command</interfacename> returned here could be an implementation that executes asynchronously, or whatever</lineannotation>
|
|
protected Command createCommand() {
|
|
return (Command) this.beanFactory.getBean("command"); <lineannotation>// notice the Spring API dependency</lineannotation>
|
|
}
|
|
|
|
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
|
this.beanFactory = beanFactory;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>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.</para>
|
|
|
|
<section id="beans-factory-lookup-method-injection">
|
|
<title>Lookup method injection</title>
|
|
|
|
<sidebar>
|
|
<title>Isn't this Method Injection...</title>
|
|
|
|
<para>... somewhat like Tapestry 4.0's pages, where folks wrote
|
|
<literal>abstract</literal> properties that Tapestry would override
|
|
at runtime with implementations that did stuff? It sure is (well,
|
|
somewhat).</para>
|
|
|
|
<para>You can read more about the motivation for Method Injection in
|
|
<ulink url="http://blog.springframework.com/rod/?p=1">this blog
|
|
entry</ulink>.</para>
|
|
</sidebar>
|
|
|
|
<para>Lookup method injection refers to the ability of the container
|
|
to override methods on <emphasis>container managed beans</emphasis>,
|
|
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.</para>
|
|
|
|
<para>So if you look at the code from previous code snippet (the
|
|
<classname>CommandManager</classname> class), the Spring container is
|
|
going to dynamically override the implementation of the
|
|
<methodname>createCommand()</methodname> method. Your
|
|
<classname>CommandManager</classname> class is not going to have any
|
|
Spring dependencies, as can be seen in this reworked example
|
|
below:</para>
|
|
|
|
<programlisting language="java">package fiona.apple;
|
|
|
|
<lineannotation>// no more Spring imports! </lineannotation>
|
|
|
|
public abstract class CommandManager {
|
|
|
|
public Object process(Object commandState) {
|
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename> interface</lineannotation>
|
|
Command command = createCommand();
|
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation>
|
|
command.setState(commandState);
|
|
return command.execute();
|
|
}
|
|
|
|
<lineannotation>// okay... but where is the implementation of this method?</lineannotation>
|
|
protected abstract Command createCommand();
|
|
}</programlisting>
|
|
|
|
<para>In the client class containing the method to be injected (the
|
|
<classname>CommandManager</classname> in this case), the method that
|
|
is to be 'injected' must have a signature of the following
|
|
form:</para>
|
|
|
|
<programlisting language="xml"><public|protected> [abstract] <return-type> theMethodName(<lineannotation>no-arguments</lineannotation>);</programlisting>
|
|
|
|
<para>If the method is <literal>abstract</literal>, 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:</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- a stateful bean deployed as a prototype (non-singleton) --></lineannotation>
|
|
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
|
|
<lineannotation><!-- inject dependencies here as required --></lineannotation>
|
|
</bean>
|
|
|
|
<lineannotation><!-- <literal>commandProcessor</literal> uses <literal>statefulCommandHelper</literal> --></lineannotation>
|
|
<bean id="commandManager" class="fiona.apple.CommandManager">
|
|
<lookup-method name="createCommand" bean="command"/>
|
|
</bean></programlisting>
|
|
|
|
<para>The bean identified as <emphasis>commandManager</emphasis> will
|
|
call its own method <methodname>createCommand()</methodname> whenever
|
|
it needs a new instance of the <emphasis>command</emphasis> bean. It
|
|
is important to note that the person deploying the beans must be
|
|
careful to deploy the <literal>command</literal> bean as a prototype
|
|
(if that is actually what is needed). If it is deployed as a <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link>, the same
|
|
instance of the <literal>command</literal> bean will be returned each
|
|
time!</para>
|
|
|
|
<para>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 <literal>final</literal>, and the method that is being
|
|
overridden cannot be <literal>final</literal> either. Also, testing a
|
|
class that has an <literal>abstract</literal> method can be somewhat
|
|
odd in that you will have to subclass the class yourself and supply a
|
|
stub implementation of the <literal>abstract</literal> method.
|
|
Finally, objects that have been the target of method injection cannot
|
|
be serialized.</para>
|
|
|
|
<tip>
|
|
<para>The interested reader may also find the
|
|
<classname>ServiceLocatorFactoryBean</classname> (in the
|
|
<literal>org.springframework.beans.factory.config</literal> package)
|
|
to be of use; the approach is similar to that of the
|
|
<classname>ObjectFactoryCreatingFactoryBean</classname>, but it
|
|
allows you to specify your own lookup interface as opposed to having
|
|
to use a Spring-specific lookup interface such as the
|
|
<interfacename>ObjectFactory</interfacename>. Consult the (copious)
|
|
Javadoc for the <classname>ServiceLocatorFactoryBean</classname> for
|
|
a full treatment of this alternative approach (that
|
|
<emphasis>does</emphasis> reduce the coupling to Spring).</para>
|
|
</tip>
|
|
</section>
|
|
|
|
<section id="beans-factory-arbitrary-method-replacement">
|
|
<title>Arbitrary method replacement</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<para>When using XML-based configuration metadata, the
|
|
<literal>replaced-method</literal> 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:</para>
|
|
|
|
<programlisting language="java">public class MyValueCalculator {
|
|
|
|
public String computeValue(String input) {
|
|
<lineannotation>// some real code...</lineannotation>
|
|
}
|
|
|
|
<lineannotation>// some other methods...</lineannotation>
|
|
|
|
}</programlisting>
|
|
|
|
<para>A class implementing the
|
|
<interfacename>org.springframework.beans.factory.support.MethodReplacer</interfacename>
|
|
interface provides the new method definition.</para>
|
|
|
|
<programlisting language="java"><lineannotation>/** meant to be used to override the existing <methodname>computeValue(String)</methodname>
|
|
implementation in <classname>MyValueCalculator</classname>
|
|
*/</lineannotation>
|
|
public class ReplacementComputeValue implements MethodReplacer {
|
|
|
|
public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
|
|
<lineannotation>// get the input value, work with it, and return a computed result</lineannotation>
|
|
String input = (String) args[0];
|
|
...
|
|
return ...;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>The bean definition to deploy the original class and specify the
|
|
method override would look like this:</para>
|
|
|
|
<programlisting language="xml"><bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
|
|
|
|
<lineannotation><!-- arbitrary method replacement --></lineannotation>
|
|
<replaced-method name="computeValue" replacer="replacementComputeValue">
|
|
<arg-type>String</arg-type>
|
|
</replaced-method>
|
|
</bean>
|
|
|
|
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/></programlisting>
|
|
|
|
<para>One or more contained <literal><arg-type/></literal>
|
|
elements within the <literal><replaced-method/></literal>
|
|
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
|
|
<classname>java.lang.String</classname>.</para>
|
|
|
|
<programlisting language="java"> java.lang.String
|
|
String
|
|
Str</programlisting>
|
|
|
|
<para>Since 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.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes">
|
|
<title>Bean scopes</title>
|
|
|
|
<para>When you create a bean definition what you are actually creating is
|
|
a <emphasis>recipe</emphasis> for creating actual instances of the class
|
|
defined by that bean definition. The idea that a bean definition is a
|
|
recipe is important, because it means that, just like a class, you can
|
|
potentially have many object instances created from a single
|
|
recipe.</para>
|
|
|
|
<para>You can control not only the various dependencies and configuration
|
|
values that are to be plugged into an object that is created from a
|
|
particular bean definition, but also the <firstterm>scope</firstterm> of
|
|
the objects created from a particular bean definition. This approach is
|
|
very powerful and gives you the flexibility to <emphasis>choose</emphasis>
|
|
the scope of the objects you create through configuration instead of
|
|
having to 'bake in' the scope of an object at the Java class level. Beans
|
|
can be defined to be deployed in one of a number of scopes: out of the
|
|
box, the Spring Framework supports exactly five scopes (of which three are
|
|
available only if you are using a web-aware
|
|
<interfacename>ApplicationContext</interfacename>).</para>
|
|
|
|
<para>The scopes supported out of the box are listed below:</para>
|
|
|
|
<table id="beans-factory-scopes-tbl">
|
|
<title>Bean scopes</title>
|
|
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry align="center">Scope</entry>
|
|
|
|
<entry align="center">Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><para> <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link>
|
|
</para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to a single object
|
|
instance per Spring IoC container.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para> <link
|
|
linkend="beans-factory-scopes-prototype">prototype</link>
|
|
</para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to any number of
|
|
object instances.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para> <link
|
|
linkend="beans-factory-scopes-request">request</link>
|
|
</para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of a
|
|
single HTTP request; that is each and every HTTP request will have
|
|
its own instance of a bean created off the back of a single bean
|
|
definition. Only valid in the context of a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename>.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para> <link
|
|
linkend="beans-factory-scopes-global-session">session</link>
|
|
</para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of a
|
|
HTTP <interfacename>Session</interfacename>. Only valid in the
|
|
context of a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename>.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para> <link
|
|
linkend="beans-factory-scopes-global-session">global
|
|
session</link> </para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of a
|
|
global HTTP <interfacename>Session</interfacename>. Typically only
|
|
valid when used in a portlet context. Only valid in the context of
|
|
a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename>.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<section id="beans-factory-scopes-singleton">
|
|
<title>The singleton scope</title>
|
|
|
|
<para>When a bean is a singleton, only one <emphasis>shared</emphasis>
|
|
instance of the bean will be managed, and all requests for beans with an
|
|
id or <literal>id</literal>s matching that bean definition will result
|
|
in that one specific bean instance being returned by the Spring
|
|
container.</para>
|
|
|
|
<para>To put it another way, when you define a bean definition and it is
|
|
scoped as a singleton, then the Spring IoC container will create
|
|
<emphasis>exactly one</emphasis> instance of the object defined by that
|
|
bean definition. This single instance will be stored in a cache of such
|
|
singleton beans, and <emphasis>all subsequent requests and
|
|
references</emphasis> for that named bean will result in the cached
|
|
object being returned.</para>
|
|
|
|
<para><mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata align="center" fileref="images/singleton.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
|
|
<imageobject role="html">
|
|
<imagedata align="center" fileref="images/singleton.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
</mediaobject></para>
|
|
|
|
<para>Please be aware that Spring's concept of a singleton bean is quite
|
|
different from the Singleton pattern as defined in the seminal Gang of
|
|
Four (GoF) patterns book. The GoF Singleton hard codes the scope of an
|
|
object such that one <emphasis>and only one</emphasis> instance of a
|
|
particular class will ever be created<emphasis> per
|
|
<classname>ClassLoader</classname></emphasis>. The scope of the Spring
|
|
singleton is best described as <emphasis>per container and per
|
|
bean</emphasis>. This means that if you define one bean for a particular
|
|
class in a single Spring container, then the Spring container will
|
|
create one <emphasis>and only one</emphasis> instance of the class
|
|
defined by that bean definition. <emphasis>The singleton scope is the
|
|
default scope in Spring</emphasis>. To define a bean as a singleton in
|
|
XML, you would write configuration like so:</para>
|
|
|
|
<programlisting language="xml"><bean id="accountService" class="com.foo.DefaultAccountService"/>
|
|
|
|
<lineannotation><!-- the following is equivalent, though redundant (singleton scope is the default); using <literal>spring-beans-2.0.dtd</literal> --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>
|
|
|
|
<lineannotation><!-- the following is equivalent and preserved for backward compatibility in <literal>spring-beans.dtd</literal> --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" singleton="true"/></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-prototype">
|
|
<title>The prototype scope</title>
|
|
|
|
<para>The non-singleton, prototype scope of bean deployment results in
|
|
the <emphasis>creation of a new bean instance</emphasis> every time a
|
|
request for that specific bean is made (that is, it is injected into
|
|
another bean or it is requested via a programmatic
|
|
<literal>getBean()</literal> method call on the container). As a rule of
|
|
thumb, you should use the prototype scope for all beans that are
|
|
stateful, while the singleton scope should be used for stateless
|
|
beans.</para>
|
|
|
|
<para>The following diagram illustrates the Spring prototype scope.
|
|
<emphasis>Please note that a DAO would not typically be configured as a
|
|
prototype, since a typical DAO would not hold any conversational state;
|
|
it was just easier for this author to reuse the core of the singleton
|
|
diagram.</emphasis></para>
|
|
|
|
<para><mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata align="center" fileref="images/prototype.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
|
|
<imageobject role="html">
|
|
<imagedata align="center" fileref="images/prototype.png"
|
|
format="PNG" />
|
|
</imageobject>
|
|
</mediaobject></para>
|
|
|
|
<para>To define a bean as a prototype in XML, you would write
|
|
configuration like so:</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- using <literal>spring-beans-2.0.dtd</literal> --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
|
|
|
|
<lineannotation><!-- the following is equivalent and preserved for backward compatibility in <literal>spring-beans.dtd</literal> --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/></programlisting>
|
|
|
|
<para>There is one quite important thing to be aware of when deploying a
|
|
bean in the prototype scope, in that the lifecycle of the bean changes
|
|
slightly. Spring does not manage the complete lifecycle of a prototype
|
|
bean: the container instantiates, configures, decorates and otherwise
|
|
assembles a prototype object, hands it to the client and then has no
|
|
further knowledge of that prototype instance. This means that while
|
|
<emphasis>initialization</emphasis> lifecycle callback methods will be
|
|
called on all objects regardless of scope, in the case of prototypes,
|
|
any configured <emphasis>destruction</emphasis> lifecycle callbacks will
|
|
<emphasis>not</emphasis> be called. It is the responsibility of the
|
|
client code to clean up prototype scoped objects and release any
|
|
expensive resources that the prototype bean(s) are holding onto. (One
|
|
possible way to get the Spring container to release resources used by
|
|
prototype-scoped beans is through the use of a custom <link
|
|
linkend="beans-factory-extension-bpp">bean post-processor</link> which
|
|
would hold a reference to the beans that need to be cleaned up.)</para>
|
|
|
|
<para>In some respects, you can think of the Spring containers role when
|
|
talking about a prototype-scoped bean as somewhat of a replacement for
|
|
the Java <literal>'new'</literal> operator. All lifecycle aspects past
|
|
that point have to be handled by the client. (The lifecycle of a bean in
|
|
the Spring container is further described in the section entitled <xref
|
|
linkend="beans-factory-lifecycle" />.)</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-sing-prot-interaction">
|
|
<title>Singleton beans with prototype-bean dependencies</title>
|
|
|
|
<para>When using singleton-scoped beans that have dependencies on beans
|
|
that are scoped as prototypes, please be aware that
|
|
<emphasis>dependencies are resolved at instantiation time</emphasis>.
|
|
This means that if you dependency inject a prototype-scoped bean into a
|
|
singleton-scoped bean, a brand new prototype bean will be instantiated
|
|
and then dependency injected into the singleton bean... <emphasis>but
|
|
that is all</emphasis>. That exact same prototype instance will be the
|
|
sole instance that is ever supplied to the singleton-scoped bean, which
|
|
is fine if that is what you want.</para>
|
|
|
|
<para>However, sometimes what you actually want is for the
|
|
singleton-scoped bean to be able to acquire a brand new instance of the
|
|
prototype-scoped bean again and again and again at runtime. In that case
|
|
it is no use just dependency injecting a prototype-scoped bean into your
|
|
singleton bean, because as explained above, that only happens
|
|
<emphasis>once</emphasis> when the Spring container is instantiating the
|
|
singleton bean and resolving and injecting its dependencies. If you are
|
|
in the scenario where you need to get a brand new instance of a
|
|
(prototype) bean again and again and again at runtime, you are referred
|
|
to the section entitled <xref
|
|
linkend="beans-factory-method-injection" /></para>
|
|
|
|
<note>
|
|
<title>Backwards compatibility note: specifying the lifecycle scope in
|
|
XML</title>
|
|
|
|
<para>If you are referencing the
|
|
<filename>'spring-beans.dtd'</filename> DTD in a bean definition
|
|
file(s), and you are being explicit about the lifecycle scope of your
|
|
beans you must use the "<literal>singleton</literal>" attribute to
|
|
express the lifecycle scope (remembering that the <link
|
|
linkend="beans-factory-scopes-singleton">singleton lifecycle
|
|
scope</link> is the default). If you are referencing the
|
|
<filename>'spring-beans-2.0.dtd'</filename> DTD or the Spring 2.0 XSD
|
|
schema, then you will need to use the "<literal>scope</literal>"
|
|
attribute (because the "<literal>singleton</literal>" attribute was
|
|
removed from the definition of the new DTD and XSD files in favor of
|
|
the "<literal>scope</literal>" attribute).</para>
|
|
|
|
<para>To be totally clear about this, this means that if you use the
|
|
"<literal>singleton</literal>" attribute in an XML bean definition
|
|
then you <emphasis>must</emphasis> be referencing the
|
|
<filename>'spring-beans.dtd'</filename> DTD <emphasis>in that
|
|
file</emphasis>. If you are using the "<literal>scope</literal>"
|
|
attribute then you <emphasis>must</emphasis> be referencing either the
|
|
<filename>'spring-beans-2.0.dtd'</filename> DTD or the
|
|
<filename>'spring-beans-3.0.xsd'</filename> XSD <emphasis>in that
|
|
file</emphasis>.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-other">
|
|
<title>The other scopes</title>
|
|
|
|
<para>The other scopes, namely <literal>request</literal>,
|
|
<literal>session</literal>, and <literal>global session</literal> are
|
|
for use only in web-based applications (and can be used irrespective of
|
|
which particular web application framework you are using, if indeed
|
|
any). In the interest of keeping related concepts together in one place
|
|
in the reference documentation, these scopes are described here.</para>
|
|
|
|
<note>
|
|
<para>The scopes that are described in the following paragraphs are
|
|
<emphasis>only</emphasis> available if you are using a web-aware
|
|
Spring <interfacename>ApplicationContext</interfacename>
|
|
implementation (such as
|
|
<classname>XmlWebApplicationContext</classname>). If you try using
|
|
these next scopes with regular Spring IoC containers such as the
|
|
<classname>XmlBeanFactory</classname> or
|
|
<classname>ClassPathXmlApplicationContext</classname>, you
|
|
<emphasis>will</emphasis> get an
|
|
<classname>IllegalStateException</classname> complaining about an
|
|
unknown bean scope.</para>
|
|
</note>
|
|
|
|
<section id="beans-factory-scopes-other-web-configuration">
|
|
<title>Initial web configuration</title>
|
|
|
|
<para>In order to support the scoping of beans at the
|
|
<literal>request</literal>, <literal>session</literal>, and
|
|
<literal>global session</literal> levels (web-scoped beans), some
|
|
minor initial configuration is required before you can set about
|
|
defining your bean definitions. Please note that this extra setup is
|
|
<emphasis>not</emphasis> required if you just want to use the
|
|
'standard' scopes (namely singleton and prototype).</para>
|
|
|
|
<para>Now as things stand, there are a couple of ways to effect this
|
|
initial setup depending on your particular Servlet
|
|
environment...</para>
|
|
|
|
<para>If you are accessing scoped beans within Spring Web MVC, i.e.
|
|
within a request that is processed by the Spring
|
|
<classname>DispatcherServlet</classname>, or
|
|
<classname>DispatcherPortlet</classname>, then no special setup is
|
|
necessary: <classname>DispatcherServlet</classname> and
|
|
<classname>DispatcherPortlet</classname> already expose all relevant
|
|
state.</para>
|
|
|
|
<para>When using a Servlet 2.4+ web container, with requests processed
|
|
outside of Spring's DispatcherServlet (e.g. when using JSF or Struts),
|
|
you need to add the following
|
|
<interfacename>javax.servlet.ServletRequestListener</interfacename> to
|
|
the declarations in your web application's
|
|
<literal>'web.xml'</literal> file.</para>
|
|
|
|
<programlisting language="xml"><web-app>
|
|
...
|
|
<listener>
|
|
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
|
|
</listener>
|
|
...
|
|
</web-app></programlisting>
|
|
|
|
<para>If you are using an older web container (Servlet 2.3), you will
|
|
need to use the provided
|
|
<interfacename>javax.servlet.Filter</interfacename> implementation.
|
|
Find below a snippet of XML configuration that has to be included in
|
|
the <literal>'web.xml'</literal> file of your web application if you
|
|
want to have access to web-scoped beans in requests outside of
|
|
Spring's DispatcherServlet on a Servlet 2.3 container. (The filter
|
|
mapping depends on the surrounding web application configuration and
|
|
so you will have to change it as appropriate.)</para>
|
|
|
|
<programlisting language="xml"><web-app>
|
|
..
|
|
<filter>
|
|
<filter-name>requestContextFilter</filter-name>
|
|
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
|
|
</filter>
|
|
<filter-mapping>
|
|
<filter-name>requestContextFilter</filter-name>
|
|
<url-pattern>/*</url-pattern>
|
|
</filter-mapping>
|
|
...
|
|
</web-app></programlisting>
|
|
|
|
<para>That's it. <classname>DispatcherServlet</classname>,
|
|
<classname>RequestContextListener</classname> and
|
|
<classname>RequestContextFilter</classname> all do exactly the same
|
|
thing, namely bind the HTTP request object to the
|
|
<classname>Thread</classname> that is servicing that request. This
|
|
makes beans that are request- and session-scoped available further
|
|
down the call chain.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-request">
|
|
<title>The request scope</title>
|
|
|
|
<para>Consider the following bean definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="loginAction" class="com.foo.LoginAction" scope="request"/></programlisting>
|
|
|
|
<para>With the above bean definition in place, the Spring container
|
|
will create a brand new instance of the
|
|
<classname>LoginAction</classname> bean using the
|
|
<literal>'loginAction'</literal> bean definition for each and every
|
|
HTTP request. That is, the <literal>'loginAction'</literal> bean will
|
|
be effectively scoped at the HTTP request level. You can change or
|
|
dirty the internal state of the instance that is created as much as
|
|
you want, safe in the knowledge that other requests that are also
|
|
using instances created off the back of the same
|
|
<literal>'loginAction'</literal> bean definition will not be seeing
|
|
these changes in state since they are particular to an individual
|
|
request. When the request is finished processing, the bean that is
|
|
scoped to the request will be discarded.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-session">
|
|
<title>The session scope</title>
|
|
|
|
<para>Consider the following bean definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/></programlisting>
|
|
|
|
<para>With the above bean definition in place, the Spring container
|
|
will create a brand new instance of the
|
|
<classname>UserPreferences</classname> bean using the
|
|
<literal>'userPreferences'</literal> bean definition for the lifetime
|
|
of a single HTTP <interfacename>Session</interfacename>. In other
|
|
words, the <literal>'userPreferences'</literal> bean will be
|
|
effectively scoped at the HTTP <interfacename>Session</interfacename>
|
|
level. Just like <literal>request-scoped</literal> beans, you can
|
|
change the internal state of the instance that is created as much as
|
|
you want, safe in the knowledge that other HTTP
|
|
<interfacename>Session</interfacename> instances that are also using
|
|
instances created off the back of the same
|
|
<literal>'userPreferences'</literal> bean definition will not be
|
|
seeing these changes in state since they are particular to an
|
|
individual HTTP <interfacename>Session</interfacename>. When the HTTP
|
|
<interfacename>Session</interfacename> is eventually discarded, the
|
|
bean that is scoped to that particular HTTP
|
|
<interfacename>Session</interfacename> will also be discarded.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-global-session">
|
|
<title>The global session scope</title>
|
|
|
|
<para>Consider the following bean definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/></programlisting>
|
|
|
|
<para>The <literal>global session</literal> scope is similar to the
|
|
standard HTTP <interfacename>Session</interfacename> scope (<link
|
|
linkend="beans-factory-scopes-session">described immediately
|
|
above</link>), and really only makes sense in the context of
|
|
portlet-based web applications. The portlet specification defines the
|
|
notion of a global <interfacename>Session</interfacename> that is
|
|
shared amongst all of the various portlets that make up a single
|
|
portlet web application. Beans defined at the <literal>global
|
|
session</literal> scope are scoped (or bound) to the lifetime of the
|
|
global portlet <interfacename>Session</interfacename>.</para>
|
|
|
|
<para>Please note that if you are writing a standard Servlet-based web
|
|
application and you define one or more beans as having <literal>global
|
|
session</literal> scope, the standard HTTP
|
|
<interfacename>Session</interfacename> scope will be used, and no
|
|
error will be raised.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-other-injection">
|
|
<title>Scoped beans as dependencies</title>
|
|
|
|
<para>Being able to define a bean scoped to a HTTP request or
|
|
<interfacename>Session</interfacename> (or indeed <link
|
|
linkend="beans-factory-scopes-custom">a custom scope</link> of your
|
|
own devising) is all very well, but one of the main value-adds of the
|
|
Spring IoC container is that it manages not only the instantiation of
|
|
your objects (beans), but also the wiring up of collaborators (or
|
|
dependencies). If you want to inject a (for example) HTTP request
|
|
scoped bean into another bean, you will need to inject an AOP proxy in
|
|
place of the scoped bean. That is, you need to inject a proxy object
|
|
that exposes the same public interface as the scoped object, but that
|
|
is smart enough to be able to retrieve the real, target object from
|
|
the relevant scope (for example a HTTP request) and delegate method
|
|
calls onto the real object.</para>
|
|
|
|
<note>
|
|
<para>You <emphasis>do not</emphasis> need to use the
|
|
<literal><aop:scoped-proxy/></literal> in conjunction with
|
|
beans that are scoped as <literal>singletons</literal> or
|
|
<literal>prototypes</literal>. It is an error to try to create a
|
|
scoped proxy for a singleton bean (and the resulting
|
|
<exceptionname>BeanCreationException</exceptionname> will certainly
|
|
set you straight in this regard).</para>
|
|
</note>
|
|
|
|
<para>Let's look at the configuration that is required to effect this;
|
|
the configuration is not hugely complex (it takes just one line), but
|
|
it is important to understand the <quote>why</quote> as well as the
|
|
<quote>how</quote> behind it.</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:aop="http://www.springframework.org/schema/aop"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/aop
|
|
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
|
|
|
|
<lineannotation><!-- a HTTP <interfacename>Session</interfacename>-scoped bean exposed as a proxy --></lineannotation>
|
|
<bean id="userPreferences" class="com.foo.UserPreferences" <emphasis
|
|
role="bold">scope="session"</emphasis>>
|
|
|
|
<lineannotation><!-- this next element effects the proxying of the surrounding bean --></lineannotation>
|
|
<emphasis role="bold"><aop:scoped-proxy/></emphasis>
|
|
</bean>
|
|
|
|
<lineannotation><!-- a singleton-scoped bean <emphasis role="bold">injected with a proxy to the above bean</emphasis> --></lineannotation>
|
|
<bean id="userService" class="com.foo.SimpleUserService">
|
|
|
|
<lineannotation><!-- a reference to the <emphasis role="bold">proxied</emphasis> <literal>'userPreferences'</literal> bean --></lineannotation>
|
|
<property name="userPreferences" ref="userPreferences"/>
|
|
|
|
</bean>
|
|
</beans>
|
|
</programlisting>
|
|
|
|
<para>To create such a proxy, you need only to insert a child
|
|
<literal><aop:scoped-proxy/></literal> element into a scoped
|
|
bean definition (you may also need the CGLIB library on your classpath
|
|
so that the container can effect class-based proxying; you will also
|
|
need to be using <xref linkend="xsd-config" />). So, just why do you
|
|
need this <literal><aop:scoped-proxy/></literal> element in the
|
|
definition of beans scoped at the <literal>request</literal>,
|
|
<literal>session</literal>, <literal>globalSession</literal> and
|
|
'<emphasis>insert your custom scope here</emphasis>' level? The reason
|
|
is best explained by picking apart the following bean definition
|
|
(please note that the following <literal>'userPreferences'</literal>
|
|
bean definition as it stands is
|
|
<emphasis>incomplete</emphasis>):</para>
|
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
|
|
|
|
<bean id="userManager" class="com.foo.UserManager">
|
|
<property name="userPreferences" ref="userPreferences"/>
|
|
</bean></programlisting>
|
|
|
|
<para>From the above configuration it is evident that the singleton
|
|
bean <literal>'userManager'</literal> is being injected with a
|
|
reference to the HTTP <interfacename>Session</interfacename>-scoped
|
|
bean <literal>'userPreferences'</literal>. The salient point here is
|
|
that the <literal>'userManager'</literal> bean is a singleton... it
|
|
will be instantiated <emphasis>exactly once</emphasis> per container,
|
|
and its dependencies (in this case only one, the
|
|
<literal>'userPreferences'</literal> bean) will also only be injected
|
|
(once!). This means that the <literal>'userManager'</literal> will
|
|
(conceptually) only ever operate on the exact same
|
|
<literal>'userPreferences'</literal> object, that is the one that it
|
|
was originally injected with. This is <emphasis>not</emphasis> what
|
|
you want when you inject a HTTP
|
|
<interfacename>Session</interfacename>-scoped bean as a dependency
|
|
into a collaborating object (typically). Rather, what we
|
|
<emphasis>do</emphasis> want is a single
|
|
<literal>'userManager'</literal> object, and then, for the lifetime of
|
|
a HTTP <interfacename>Session</interfacename>, we want to see and use
|
|
a <literal>'userPreferences'</literal> object that is specific to said
|
|
HTTP <interfacename>Session</interfacename>.</para>
|
|
|
|
<para>Rather what you need then is to inject some sort of object that
|
|
exposes the exact same public interface as the
|
|
<classname>UserPreferences</classname> class (ideally an object that
|
|
<emphasis>is a</emphasis> <classname>UserPreferences</classname>
|
|
instance) and that is smart enough to be able to go off and fetch the
|
|
<interfacename>real</interfacename>
|
|
<classname>UserPreferences</classname> object from whatever underlying
|
|
scoping mechanism we have chosen (HTTP request,
|
|
<interfacename>Session</interfacename>, etc.). We can then safely
|
|
inject this proxy object into the <literal>'userManager'</literal>
|
|
bean, which will be blissfully unaware that the
|
|
<classname>UserPreferences</classname> reference that it is holding
|
|
onto is a proxy. In the case of this example, when a
|
|
<interfacename>UserManager</interfacename> instance invokes a method
|
|
on the dependency-injected <classname>UserPreferences</classname>
|
|
object, it is really invoking a method on the proxy... the proxy will
|
|
then go off and fetch the real <classname>UserPreferences</classname>
|
|
object from (in this case) the HTTP
|
|
<interfacename>Session</interfacename>, and delegate the method
|
|
invocation onto the retrieved real
|
|
<classname>UserPreferences</classname> object.</para>
|
|
|
|
<para>That is why you need the following, correct and complete,
|
|
configuration when injecting <literal>request-</literal>,
|
|
<literal>session-</literal>, and
|
|
<literal>globalSession-scoped</literal> beans into collaborating
|
|
objects:</para>
|
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
|
|
<emphasis role="bold"><literal><aop:scoped-proxy/></literal></emphasis>
|
|
</bean>
|
|
|
|
<bean id="userManager" class="com.foo.UserManager">
|
|
<property name="userPreferences" ref="userPreferences"/>
|
|
</bean></programlisting>
|
|
|
|
<section id="beans-factory-scopes-other-injection-proxies">
|
|
<title>Choosing the type of proxy created</title>
|
|
|
|
<para>By default, when the Spring container is creating a proxy for
|
|
a bean that is marked up with the
|
|
<literal><aop:scoped-proxy/></literal> element, <emphasis>a
|
|
CGLIB-based class proxy will be created</emphasis>. This means that
|
|
you need to have the CGLIB library on the classpath of your
|
|
application.</para>
|
|
|
|
<para><emphasis>Note: CGLIB proxies will only intercept public
|
|
method calls!</emphasis> Do not call non-public methods on such a
|
|
proxy; they will not be delegated to the scoped target
|
|
object.</para>
|
|
|
|
<para>You can choose to have the Spring container create 'standard'
|
|
JDK interface-based proxies for such scoped beans by specifying
|
|
'<literal>false</literal>' for the value of the
|
|
'<literal>proxy-target-class</literal>' attribute of the
|
|
<literal><aop:scoped-proxy/></literal> element. Using JDK
|
|
interface-based proxies does mean that you don't need any additional
|
|
libraries on your application's classpath to effect such proxying,
|
|
but it does mean that the class of the scoped bean must implement at
|
|
least one interface, and <emphasis>all</emphasis> of the
|
|
collaborators into which the scoped bean is injected must be
|
|
referencing the bean via one of its interfaces.</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- <classname>DefaultUserPreferences</classname> implements the <interfacename>UserPreferences</interfacename> interface --></lineannotation>
|
|
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session">
|
|
<aop:scoped-proxy <emphasis role="bold">proxy-target-class="false"<literal></literal></emphasis>/>
|
|
</bean>
|
|
|
|
<bean id="userManager" class="com.foo.UserManager">
|
|
<property name="userPreferences" ref="userPreferences"/>
|
|
</bean></programlisting>
|
|
|
|
<para>The section entitled <xref linkend="aop-proxying" /> may also
|
|
be of some interest with regard to understanding the nuances of
|
|
choosing whether class-based or interface-based proxying is right
|
|
for you.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-custom">
|
|
<title>Custom scopes</title>
|
|
|
|
<para>As of Spring 2.0, the bean scoping mechanism in Spring is
|
|
extensible. This means that you are not limited to just the bean scopes
|
|
that Spring provides out of the box; you can define your own scopes, or
|
|
even redefine the existing scopes (although that last one would probably
|
|
be considered bad practice - please note that you
|
|
<emphasis>cannot</emphasis> override the built-in
|
|
<literal>singleton</literal> and <literal>prototype</literal>
|
|
scopes).</para>
|
|
|
|
<section id="beans-factory-scopes-custom-creating">
|
|
<title>Creating your own custom scope</title>
|
|
|
|
<para>Scopes are defined by the
|
|
<interfacename>org.springframework.beans.factory.config.Scope</interfacename>
|
|
interface. This is the interface that you will need to implement in
|
|
order to integrate your own custom scope(s) into the Spring container,
|
|
and is described in detail below. You may wish to look at the
|
|
<interfacename>Scope</interfacename> implementations that are supplied
|
|
with the Spring Framework itself for an idea of how to go about
|
|
implementing your own. The <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/config/Scope.html">Scope
|
|
Javadoc</ulink> explains the main class to implement when you need
|
|
your own scope in more detail too.</para>
|
|
|
|
<para>The <literal>Scope</literal> interface has four methods dealing
|
|
with getting objects from the scope, removing them from the scope and
|
|
allowing them to be 'destroyed' if needed.</para>
|
|
|
|
<para>The first method should return the object from the underlying
|
|
scope. The session scope implementation for example will return the
|
|
session-scoped bean (and if it does not exist, return a new instance
|
|
of the bean, after having bound it to the session for future
|
|
reference).</para>
|
|
|
|
<programlisting language="java">Object get(String name, ObjectFactory objectFactory)</programlisting>
|
|
|
|
<para>The second method should remove the object from the underlying
|
|
scope. The session scope implementation for example, removes the
|
|
session-scoped bean from the underlying session. The object should be
|
|
returned (you are allowed to return null if the object with the
|
|
specified name wasn't found)</para>
|
|
|
|
<programlisting language="java">Object remove(String name)</programlisting>
|
|
|
|
<para>The third method is used to register callbacks the scope should
|
|
execute when it is destroyed or when the specified object in the scope
|
|
is destroyed. Please refer to the Javadoc or a Spring scope
|
|
implementation for more information on destruction callbacks.</para>
|
|
|
|
<programlisting language="java">void registerDestructionCallback(String name, Runnable destructionCallback)</programlisting>
|
|
|
|
<para>The last method deals with obtaining the conversation identifier
|
|
for the underlying scope. This identifier is different for each scope.
|
|
For a session for example, this can be the session identifier.</para>
|
|
|
|
<programlisting language="java">String getConversationId()</programlisting>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-custom-using">
|
|
<title>Using a custom scope</title>
|
|
|
|
<para>After you have written and tested one or more custom
|
|
<interfacename>Scope</interfacename> implementations, you then need to
|
|
make the Spring container aware of your new scope(s). The central
|
|
method to register a new <interfacename>Scope</interfacename> with the
|
|
Spring container is declared on the
|
|
<interfacename>ConfigurableBeanFactory</interfacename> interface
|
|
(implemented by most of the concrete
|
|
<interfacename>BeanFactory</interfacename> implementations that ship
|
|
with Spring); this central method is displayed below:</para>
|
|
|
|
<programlisting language="java">void registerScope(String scopeName, Scope scope);</programlisting>
|
|
|
|
<para>The first argument to the
|
|
<methodname>registerScope(..)</methodname> method is the unique name
|
|
associated with a scope; examples of such names in the Spring
|
|
container itself are <literal>'singleton'</literal> and
|
|
<literal>'prototype'</literal>. The second argument to the
|
|
<methodname>registerScope(..)</methodname> method is an actual
|
|
instance of the custom <interfacename>Scope</interfacename>
|
|
implementation that you wish to register and use.</para>
|
|
|
|
<para>Let's assume that you have written your own custom
|
|
<interfacename>Scope</interfacename> implementation, and you have
|
|
registered it like so:</para>
|
|
|
|
<programlisting language="java"><lineannotation>// note: the <classname>ThreadScope</classname> class does <emphasis
|
|
role="bold">not</emphasis> ship with the Spring Framework</lineannotation>
|
|
Scope customScope = new ThreadScope();
|
|
beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", customScope);</programlisting>
|
|
|
|
<para>You can then create bean definitions that adhere to the scoping
|
|
rules of your custom <interfacename>Scope</interfacename> like
|
|
so:</para>
|
|
|
|
<programlisting language="xml"><bean id="..." class="..." <emphasis
|
|
role="bold">scope="thread"</emphasis>/></programlisting>
|
|
|
|
<para>If you have your own custom <interfacename>Scope</interfacename>
|
|
implementation(s), you are not just limited to only programmatic
|
|
registration of the custom scope(s). You can also do the
|
|
<interfacename>Scope</interfacename> registration declaratively, using
|
|
the <classname>CustomScopeConfigurer</classname> class.</para>
|
|
|
|
<para>The declarative registration of custom
|
|
<interfacename>Scope</interfacename> implementations using the
|
|
<classname>CustomScopeConfigurer</classname> class is shown
|
|
below:</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:aop="http://www.springframework.org/schema/aop"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/aop
|
|
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
|
|
|
|
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
|
|
<property name="scopes">
|
|
<map><emphasis role="bold">
|
|
<entry key="thread">
|
|
<bean class="com.foo.ThreadScope"/>
|
|
</entry></emphasis>
|
|
</map>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="bar" class="x.y.Bar" <emphasis role="bold">scope="thread"</emphasis>>
|
|
<property name="name" value="Rick"/>
|
|
<aop:scoped-proxy/>
|
|
</bean>
|
|
|
|
<bean id="foo" class="x.y.Foo">
|
|
<property name="bar" ref="bar"/>
|
|
</bean>
|
|
|
|
</beans></programlisting>
|
|
|
|
<note>
|
|
<para>Note that, when placing a <aop:scoped-proxy/> in a
|
|
<interfacename>FactoryBean</interfacename> implementation, it is the
|
|
factory bean itself that is scoped, not the object returned from
|
|
<methodname>getObject()</methodname>.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-nature">
|
|
<title>Customizing the nature of a bean</title>
|
|
|
|
<section id="beans-factory-lifecycle">
|
|
<title>Lifecycle callbacks</title>
|
|
|
|
<para>The Spring Framework provides several callback interfaces to
|
|
change the behavior of your bean in the container; they include
|
|
<interfacename>InitializingBean</interfacename> and
|
|
<interfacename>DisposableBean</interfacename>. Implementing these
|
|
interfaces will result in the container calling
|
|
<methodname>afterPropertiesSet()</methodname> for the former and
|
|
<methodname>destroy()</methodname> for the latter to allow the bean to
|
|
perform certain actions upon initialization and destruction.</para>
|
|
|
|
<para>Internally, the Spring Framework uses
|
|
<interfacename>BeanPostProcessor</interfacename> implementations to
|
|
process any callback interfaces it can find and call the appropriate
|
|
methods. If you need custom features or other lifecycle behavior Spring
|
|
doesn't offer out-of-the-box, you can implement a
|
|
<interfacename>BeanPostProcessor</interfacename> yourself. More
|
|
information about this can be found in the section entitled <xref
|
|
linkend="beans-factory-extension" />.</para>
|
|
|
|
<para>All the different lifecycle callback interfaces are described
|
|
below. In one of the appendices, you can find diagrams that show how
|
|
Spring manages beans, how those lifecycle features change the nature of
|
|
your beans, and how they are managed.</para>
|
|
|
|
<section id="beans-factory-lifecycle-initializingbean">
|
|
<title>Initialization callbacks</title>
|
|
|
|
<para>Implementing the
|
|
<interfacename>org.springframework.beans.factory.InitializingBean</interfacename>
|
|
interface allows a bean to perform initialization work after all
|
|
necessary properties on the bean have been set by the container. The
|
|
<interfacename>InitializingBean</interfacename> interface specifies
|
|
exactly one method:</para>
|
|
|
|
<programlisting language="java">void afterPropertiesSet() throws Exception;</programlisting>
|
|
|
|
<para>Generally, the use of the
|
|
<interfacename>InitializingBean</interfacename> interface can be
|
|
avoided and is actually discouraged since it unnecessarily couples the
|
|
code to Spring. As an alternative, bean definitions provide support
|
|
for a generic initialization method to be specified. In the case of
|
|
XML-based configuration metadata, this is done using the
|
|
<literal>'init-method'</literal> attribute. For example, the following
|
|
definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/></programlisting>
|
|
|
|
<programlisting language="java">public class ExampleBean {
|
|
|
|
public void init() {
|
|
<lineannotation>// do some initialization work</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>...is exactly the same as...</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.AnotherExampleBean"/></programlisting>
|
|
|
|
<programlisting language="java">public class AnotherExampleBean implements InitializingBean {
|
|
|
|
public void afterPropertiesSet() {
|
|
<lineannotation>// do some initialization work</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>... but does not couple the code to Spring.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-lifecycle-disposablebean">
|
|
<title>Destruction callbacks</title>
|
|
|
|
<para>Implementing the
|
|
<interfacename>org.springframework.beans.factory.DisposableBean</interfacename>
|
|
interface allows a bean to get a callback when the container
|
|
containing it is destroyed. The
|
|
<interfacename>DisposableBean</interfacename> interface specifies a
|
|
single method:</para>
|
|
|
|
<programlisting language="java">void destroy() throws Exception;</programlisting>
|
|
|
|
<para>Generally, the use of the
|
|
<interfacename>DisposableBean</interfacename> callback interface can
|
|
be avoided and is actually discouraged since it unnecessarily couples
|
|
the code to Spring. As an alternative, bean definitions provide
|
|
support for a generic destroy method to be specified. When using
|
|
XML-based configuration metadata this is done via the
|
|
<literal>'destroy-method'</literal> attribute on the
|
|
<literal><bean/></literal>. For example, the following
|
|
definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/></programlisting>
|
|
|
|
<programlisting language="java">public class ExampleBean {
|
|
|
|
public void cleanup() {
|
|
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>...is exactly the same as...</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.AnotherExampleBean"/></programlisting>
|
|
|
|
<programlisting language="java">public class AnotherExampleBean implements DisposableBean {
|
|
|
|
public void destroy() {
|
|
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>... but does not couple the code to Spring.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-lifecycle-default-init-destroy-methods">
|
|
<title>Default initialization & destroy methods</title>
|
|
|
|
<para>When writing initialization and destroy method callbacks that do
|
|
not use the Spring-specific
|
|
<interfacename>InitializingBean</interfacename> and
|
|
<interfacename>DisposableBean</interfacename> callback interfaces, one
|
|
typically finds oneself writing methods with names such as
|
|
<literal>init()</literal>, <literal>initialize()</literal>,
|
|
<literal>dispose()</literal>, etc. The names of such lifecycle
|
|
callback methods are (hopefully!) standardized across a project so
|
|
that all developers on a team use the same method names and thus
|
|
ensure some level of consistency.</para>
|
|
|
|
<para>The Spring container can be configured to
|
|
<literal>'look'</literal> for named initialization and destroy
|
|
callback method names on <emphasis>every</emphasis> bean. This means
|
|
that you, as an application developer, can simply write your
|
|
application classes, use a convention of having an initialization
|
|
callback called <literal>init()</literal>, and then (without having to
|
|
configure each and every bean with, in the case of XML-based
|
|
configuration, an <literal>'init-method="init"'</literal> attribute)
|
|
be safe in the knowledge that the Spring IoC container
|
|
<emphasis>will</emphasis> call that method when the bean is being
|
|
created (and in accordance with the standard lifecycle callback
|
|
contract described previously).</para>
|
|
|
|
<para>Let's look at an example to make the use of this feature
|
|
completely clear. For the sake of the example, let us say that one of
|
|
the coding conventions on a project is that all initialization
|
|
callback methods are to be named <literal>init()</literal> and that
|
|
destroy callback methods are to be called
|
|
<literal>destroy()</literal>. This leads to classes like so...</para>
|
|
|
|
<programlisting language="java">public class DefaultBlogService implements BlogService {
|
|
|
|
private BlogDao blogDao;
|
|
|
|
public void setBlogDao(BlogDao blogDao) {
|
|
this.blogDao = blogDao;
|
|
}
|
|
|
|
<lineannotation>// this is (unsurprisingly) the initialization callback method</lineannotation>
|
|
public void init() {
|
|
if (this.blogDao == null) {
|
|
throw new IllegalStateException("The [blogDao] property must be set.");
|
|
}
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="xml"><beans <emphasis role="bold">default-init-method="init"</emphasis>>
|
|
|
|
<bean id="blogService" class="com.foo.DefaultBlogService">
|
|
<property name="blogDao" ref="blogDao" />
|
|
</bean>
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>Notice the use of the <literal>'default-init-method'</literal>
|
|
attribute on the top-level <literal><beans/></literal> element.
|
|
The presence of this attribute means that the Spring IoC container
|
|
will recognize a method called <literal>'init'</literal> on beans as
|
|
being the initialization method callback, and when a bean is being
|
|
created and assembled, if the bean's class has such a method, it will
|
|
be invoked at the appropriate time.</para>
|
|
|
|
<para>Destroy method callbacks are configured similarly (in XML that
|
|
is) using the <literal>'default-destroy-method'</literal> attribute on
|
|
the top-level <literal><beans/></literal> element.</para>
|
|
|
|
<para>The use of this feature can save you the (small) housekeeping
|
|
chore of specifying an initialization and destroy method callback on
|
|
each and every bean, and it is great for enforcing a consistent naming
|
|
convention for initialization and destroy method callbacks, as
|
|
consistency is something that should always be aimed for.</para>
|
|
|
|
<para>Consider the case where you have some existing beans where the
|
|
underlying classes already have initialization callback methods that
|
|
are named at variance with the convention. You can
|
|
<emphasis>always</emphasis> override the default by specifying (in XML
|
|
that is) the method name using the <literal>'init-method'</literal>
|
|
and <literal>'destroy-method'</literal> attributes on the
|
|
<literal><bean/></literal> element itself.</para>
|
|
|
|
<para>Finally, please be aware that the Spring container guarantees
|
|
that a configured initialization callback is called immediately after
|
|
a bean has been supplied with all of its dependencies. This means that
|
|
the initialization callback will be called on the raw bean reference,
|
|
which means that any AOP interceptors or suchlike that will ultimately
|
|
be applied to the bean will not yet be in place. A target bean is
|
|
fully created <emphasis>first</emphasis>, <emphasis>then</emphasis> an
|
|
AOP proxy (for example) with its interceptor chain is applied. Note
|
|
that, if the target bean and the proxy are defined separately, your
|
|
code can even interact with the raw target bean, bypassing the proxy.
|
|
Hence, it would be very inconsistent to apply the interceptors to the
|
|
init method, since that would couple the lifecycle of the target bean
|
|
with its proxy/interceptors and leave strange semantics when talking
|
|
to the raw target bean directly.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-lifecycle-combined-effects">
|
|
<title>Combining lifecycle mechanisms</title>
|
|
|
|
<para>As of Spring 2.5, there are three options for controlling bean
|
|
lifecycle behavior: the <link
|
|
linkend="beans-factory-lifecycle-initializingbean"><interfacename>InitializingBean</interfacename></link>
|
|
and <link
|
|
linkend="beans-factory-lifecycle-disposablebean"><interfacename>DisposableBean</interfacename></link>
|
|
callback interfaces; custom <literal>init()</literal> and
|
|
<literal>destroy()</literal> methods; and the <link
|
|
linkend="beans-postconstruct-and-predestroy-annotations"><interfacename>@PostConstruct</interfacename>
|
|
and <interfacename>@PreDestroy</interfacename>
|
|
annotations</link>.</para>
|
|
|
|
<para>When combining different lifecycle mechanisms - for example, in
|
|
a class hierarchy in which various lifecycle mechanisms are in use -
|
|
developers should be aware of the order in which these mechanisms are
|
|
applied. The following is the ordering for initialization
|
|
methods:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Methods annotated with
|
|
<interfacename>@PostConstruct</interfacename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>afterPropertiesSet()</literal> as defined by the
|
|
<interfacename>InitializingBean</interfacename> callback
|
|
interface</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A custom configured <literal>init()</literal> method</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Destroy methods are called in the same order:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Methods annotated with
|
|
<interfacename>@PreDestroy</interfacename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>destroy()</literal> as defined by the
|
|
<interfacename>DisposableBean</interfacename> callback
|
|
interface</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>A custom configured <literal>destroy()</literal>
|
|
method</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<note>
|
|
<para>If multiple lifecycle mechanisms are configured for a given
|
|
bean, and each mechanism is configured with a different method name,
|
|
then each configured method will be executed in the order listed
|
|
above; however, if the same method name is configured - for example,
|
|
<literal>init()</literal> for an initialization method - for more
|
|
than one of the aforementioned lifecycle mechanisms, that method
|
|
will only be executed once.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-factory-shutdown">
|
|
<title>Shutting down the Spring IoC container gracefully in non-web
|
|
applications</title>
|
|
|
|
<note>
|
|
<para>This next section does not apply to web applications (in case
|
|
the title of this section did not make that abundantly clear).
|
|
Spring's web-based <interfacename>ApplicationContext</interfacename>
|
|
implementations already have code in place to handle shutting down
|
|
the Spring IoC container gracefully when the relevant web
|
|
application is being shutdown.</para>
|
|
</note>
|
|
|
|
<para>If you are using Spring's IoC container in a non-web application
|
|
environment, for example in a rich client desktop environment, and you
|
|
want the container to shutdown gracefully and call the relevant
|
|
destroy callbacks on your singleton beans, you will need to register a
|
|
shutdown hook with the JVM. This is quite easy to do (see below), and
|
|
will ensure that your Spring IoC container shuts down gracefully and
|
|
that all resources held by your singletons are released. Of course it
|
|
is still up to you to both configure the destroy callbacks for your
|
|
singletons and implement such destroy callbacks correctly.</para>
|
|
|
|
<para>So to register a shutdown hook that enables the graceful
|
|
shutdown of the relevant Spring IoC container, you simply need to call
|
|
the <methodname>registerShutdownHook()</methodname> method that is
|
|
declared on the <classname>AbstractApplicationContext</classname>
|
|
class. To wit...</para>
|
|
|
|
<programlisting language="java">import org.springframework.context.support.AbstractApplicationContext;
|
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
|
|
public final class Boot {
|
|
|
|
public static void main(final String[] args) throws Exception {
|
|
AbstractApplicationContext ctx
|
|
= new ClassPathXmlApplicationContext(new String []{"beans.xml"});
|
|
|
|
<lineannotation>// add a shutdown hook for the above context... </lineannotation>
|
|
ctx.registerShutdownHook();
|
|
|
|
<lineannotation>// app runs here...</lineannotation>
|
|
|
|
<lineannotation>// main method exits, hook is called prior to the app shutting down...</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-aware">
|
|
<title>Knowing who you are</title>
|
|
|
|
<section id="beans-factory-aware-beanfactoryaware">
|
|
<title><interfacename>BeanFactoryAware</interfacename></title>
|
|
|
|
<para>A class which implements the
|
|
<interfacename>org.springframework.beans.factory.BeanFactoryAware</interfacename>
|
|
interface is provided with a reference to the
|
|
<interfacename>BeanFactory</interfacename> that created it, when it is
|
|
created by that <interfacename>BeanFactory</interfacename>.</para>
|
|
|
|
<programlisting language="java">public interface BeanFactoryAware {
|
|
|
|
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
|
|
}</programlisting>
|
|
|
|
<para>This allows beans to manipulate the
|
|
<interfacename>BeanFactory</interfacename> that created them
|
|
programmatically, through the
|
|
<interfacename>BeanFactory</interfacename> interface, or by casting
|
|
the reference to a known subclass of this which exposes additional
|
|
functionality. Primarily this would consist of programmatic retrieval
|
|
of other beans. While there are cases when this capability is useful,
|
|
it should generally be avoided, since it couples the code to Spring
|
|
and does not follow the Inversion of Control style, where
|
|
collaborators are provided to beans as properties.</para>
|
|
|
|
<para>An alternative option that is equivalent in effect to the
|
|
<interfacename>BeanFactoryAware</interfacename>-based approach is to
|
|
use the
|
|
<classname>org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean</classname>.
|
|
(It should be noted that this approach still does not reduce the
|
|
coupling to Spring, but it does not violate the central principle of
|
|
IoC as much as the
|
|
<interfacename>BeanFactoryAware</interfacename>-based
|
|
approach.)</para>
|
|
|
|
<para>The <classname>ObjectFactoryCreatingFactoryBean</classname> is a
|
|
<link
|
|
linkend="beans-factory-extension-factorybean"><interfacename>FactoryBean</interfacename></link>
|
|
implementation that returns a reference to an object (factory) that
|
|
can in turn be used to effect a bean lookup. The
|
|
<classname>ObjectFactoryCreatingFactoryBean</classname> class does
|
|
itself implement the <interfacename>BeanFactoryAware</interfacename>
|
|
interface; what client beans are actually injected with is an instance
|
|
of the <interfacename>ObjectFactory</interfacename> interface. This is
|
|
a Spring-specific interface (and hence there is still no total
|
|
decoupling from Spring), but clients can then use the
|
|
<interfacename>ObjectFactory</interfacename>'s
|
|
<methodname>getObject()</methodname> method to effect the bean lookup
|
|
(under the hood the <interfacename>ObjectFactory</interfacename>
|
|
implementation instance that is returned simply delegates down to a
|
|
<interfacename>BeanFactory</interfacename> to actually lookup a bean
|
|
by name). All that you need to do is supply the
|
|
<classname>ObjectFactoryCreatingFactoryBean</classname> with the name
|
|
of the bean that is to be looked up. Let's look at an example:</para>
|
|
|
|
<programlisting language="java">package x.y;
|
|
|
|
public class NewsFeed {
|
|
|
|
private String news;
|
|
|
|
public void setNews(String news) {
|
|
this.news = news;
|
|
}
|
|
|
|
public String getNews() {
|
|
return this.toString() + ": '" + news + "'";
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">package x.y;
|
|
|
|
import org.springframework.beans.factory.ObjectFactory;
|
|
|
|
public class NewsFeedManager {
|
|
|
|
private ObjectFactory factory;
|
|
|
|
public void setFactory(ObjectFactory factory) {
|
|
this.factory = factory;
|
|
}
|
|
|
|
public void printNews() {
|
|
// here is where the lookup is performed; note that there is no
|
|
// need to hard code the name of the bean that is being looked up...
|
|
NewsFeed news = (NewsFeed) factory.getObject();
|
|
System.out.println(news.getNews());
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Find below the XML configuration to wire together the above
|
|
classes using the
|
|
<classname>ObjectFactoryCreatingFactoryBean</classname>
|
|
approach.</para>
|
|
|
|
<programlisting language="xml"><beans>
|
|
<bean id="newsFeedManager" class="x.y.NewsFeedManager">
|
|
<property name="factory">
|
|
<bean
|
|
class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
|
|
<property name="targetBeanName">
|
|
<idref local="newsFeed" />
|
|
</property>
|
|
</bean>
|
|
</property>
|
|
</bean>
|
|
<bean id="newsFeed" class="x.y.NewsFeed" scope="prototype">
|
|
<property name="news" value="... that's fit to print!" />
|
|
</bean>
|
|
</beans></programlisting>
|
|
|
|
<para>And here is a small driver program to test the fact that new
|
|
(prototype) instances of the <literal>newsFeed</literal> bean are
|
|
actually being returned for each call to the injected
|
|
<interfacename>ObjectFactory</interfacename> inside the
|
|
<classname>NewsFeedManager</classname>'s
|
|
<methodname>printNews()</methodname> method.</para>
|
|
|
|
<programlisting language="java">import org.springframework.context.ApplicationContext;
|
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
import x.y.NewsFeedManager;
|
|
|
|
public class Main {
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
|
|
NewsFeedManager manager = (NewsFeedManager) ctx.getBean("newsFeedManager");
|
|
manager.printNews();
|
|
manager.printNews();
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>The output from running the above program will look like so
|
|
(results will of course vary on your machine).</para>
|
|
|
|
<programlisting language="java">x.y.NewsFeed@1292d26: '... that's fit to print!'
|
|
x.y.NewsFeed@5329c5: '... that's fit to print!'</programlisting>
|
|
|
|
<para>As of Spring 2.5, you can rely upon autowiring of the
|
|
<interfacename>BeanFactory</interfacename> as yet another alternative
|
|
to implementing the <interfacename>BeanFactoryAware</interfacename>
|
|
interface. The "traditional" <literal>constructor</literal> and
|
|
<literal>byType</literal> autowiring modes (as described in the
|
|
section entitled <xref linkend="beans-factory-autowire" />) are now
|
|
capable of providing a dependency of type
|
|
<interfacename>BeanFactory</interfacename> for either a constructor
|
|
argument or setter method parameter respectively. For more flexibility
|
|
(including the ability to autowire fields and multiple parameter
|
|
methods), consider using the new annotation-based autowiring features.
|
|
In that case, the <interfacename>BeanFactory</interfacename> will be
|
|
autowired into a field, constructor argument, or method parameter that
|
|
is expecting the <interfacename>BeanFactory</interfacename> type as
|
|
long as the field, constructor, or method in question carries the
|
|
<interfacename>@Autowired</interfacename> annotation. For more
|
|
information, see the section entitled <xref
|
|
linkend="beans-autowired-annotation" />.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-aware-beannameaware">
|
|
<title><interfacename>BeanNameAware</interfacename></title>
|
|
|
|
<para>If a bean implements the
|
|
<interfacename>org.springframework.beans.factory.BeanNameAware</interfacename>
|
|
interface and is deployed in a
|
|
<interfacename>BeanFactory</interfacename>, the
|
|
<interfacename>BeanFactory</interfacename> will call the bean through
|
|
this interface to inform the bean of the <emphasis>name</emphasis> it
|
|
was deployed under. The callback will be invoked after population of
|
|
normal bean properties but before an initialization callback like
|
|
<interfacename>InitializingBean</interfacename>'s
|
|
<emphasis>afterPropertiesSet</emphasis> or a custom
|
|
init-method.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-child-bean-definitions">
|
|
<title>Bean definition inheritance</title>
|
|
|
|
<para>A bean definition potentially contains a large amount of
|
|
configuration information, including container specific information (for
|
|
example initialization method, static factory method name, and so forth)
|
|
and constructor arguments and property values. A child bean definition is
|
|
a bean definition that inherits configuration data from a parent
|
|
definition. It is then able to override some values, or add others, as
|
|
needed. Using parent and child bean definitions can potentially save a lot
|
|
of typing. Effectively, this is a form of templating.</para>
|
|
|
|
<para>When working with a <interfacename>BeanFactory</interfacename>
|
|
programmatically, child bean definitions are represented by the
|
|
<classname>ChildBeanDefinition</classname> class. Most users will never
|
|
work with them on this level, instead configuring bean definitions
|
|
declaratively in something like the <classname>XmlBeanFactory</classname>.
|
|
When using XML-based configuration metadata a child bean definition is
|
|
indicated simply by using the <literal>'parent'</literal> attribute,
|
|
specifying the parent bean as the value of this attribute.</para>
|
|
|
|
<programlisting language="xml"><bean id="inheritedTestBean" abstract="true"
|
|
class="org.springframework.beans.TestBean">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</bean>
|
|
|
|
<bean id="inheritsWithDifferentClass"
|
|
class="org.springframework.beans.DerivedTestBean"
|
|
<emphasis role="bold">parent="inheritedTestBean"</emphasis> init-method="initialize">
|
|
|
|
<property name="name" value="override"/>
|
|
<lineannotation><!-- the age property value of 1 will be inherited from parent --></lineannotation>
|
|
|
|
</bean></programlisting>
|
|
|
|
<para>A child bean definition will use the bean class from the parent
|
|
definition if none is specified, but can also override it. In the latter
|
|
case, the child bean class must be compatible with the parent, that is it
|
|
must accept the parent's property values.</para>
|
|
|
|
<para>A child bean definition will inherit constructor argument values,
|
|
property values and method overrides from the parent, with the option to
|
|
add new values. If any init-method, destroy-method and/or
|
|
<literal>static</literal> factory method settings are specified, they will
|
|
override the corresponding parent settings.</para>
|
|
|
|
<para>The remaining settings will <emphasis>always</emphasis> be taken
|
|
from the child definition: <emphasis>depends on</emphasis>,
|
|
<emphasis>autowire mode</emphasis>, <emphasis>dependency check</emphasis>,
|
|
<emphasis>singleton</emphasis>, <emphasis>scope</emphasis>, <emphasis>lazy
|
|
init</emphasis>.</para>
|
|
|
|
<para>Note that in the example above, we have explicitly marked the parent
|
|
bean definition as abstract by using the <literal>abstract</literal>
|
|
attribute. In the case that the parent definition does not specify a
|
|
class, and so explicitly marking the parent bean definition as
|
|
<literal>abstract</literal> is required:</para>
|
|
|
|
<programlisting language="xml"><bean id="inheritedTestBeanWithoutClass" abstract="true">
|
|
<property name="name" value="parent"/>
|
|
<property name="age" value="1"/>
|
|
</bean>
|
|
|
|
<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
|
|
parent="inheritedTestBeanWithoutClass" init-method="initialize">
|
|
<property name="name" value="override"/>
|
|
<lineannotation><!-- age will inherit the value of <literal>1</literal> from the parent bean definition--></lineannotation>
|
|
</bean></programlisting>
|
|
|
|
<para>The parent bean cannot get instantiated on its own since it is
|
|
incomplete, and it is also explicitly marked as
|
|
<literal>abstract</literal>. When a definition is defined to be
|
|
<literal>abstract</literal> like this, it is usable only as a pure
|
|
template bean definition that will serve as a parent definition for child
|
|
definitions. Trying to use such an <literal>abstract</literal> parent bean
|
|
on its own (by referring to it as a ref property of another bean, or doing
|
|
an explicit <methodname>getBean()</methodname> call with the parent bean
|
|
id), will result in an error. Similarly, the container's internal
|
|
<methodname>preInstantiateSingletons()</methodname> method will completely
|
|
ignore bean definitions which are defined as abstract.</para>
|
|
|
|
<note>
|
|
<para><literal>ApplicationContexts</literal> (but
|
|
<emphasis>not</emphasis> <literal>BeanFactories</literal>) will by
|
|
default pre-instantiate all singletons. Therefore it is important (at
|
|
least for singleton beans) that if you have a (parent) bean definition
|
|
which you intend to use only as a template, and this definition
|
|
specifies a class, you must make sure to set the
|
|
<emphasis>'abstract'</emphasis> attribute to
|
|
<emphasis>'true'</emphasis>, otherwise the application context will
|
|
actually (attempt to) pre-instantiate the <literal>abstract</literal>
|
|
bean.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-factory-extension">
|
|
<title>Container extension points</title>
|
|
|
|
<para>The IoC component of the Spring Framework has been designed for
|
|
extension. There is typically no need for an application developer to
|
|
subclass any of the various <interfacename>BeanFactory</interfacename> or
|
|
<interfacename>ApplicationContext</interfacename> implementation classes.
|
|
The Spring IoC container can be infinitely extended by plugging in
|
|
implementations of special integration interfaces. The next few sections
|
|
are devoted to detailing all of these various integration
|
|
interfaces.</para>
|
|
|
|
<section id="beans-factory-extension-bpp">
|
|
<title>Customizing beans using
|
|
<literal>BeanPostProcessors</literal></title>
|
|
|
|
<para>The first extension point that we will look at is the
|
|
<interfacename>BeanPostProcessor</interfacename> interface. This
|
|
interface defines a number of <firstterm>callback methods</firstterm>
|
|
that you as an application developer can implement in order to provide
|
|
your own (or override the containers default) instantiation logic,
|
|
dependency-resolution logic, and so forth. If you want to do some custom
|
|
logic after the Spring container has finished instantiating, configuring
|
|
and otherwise initializing a bean, you can plug in one or more
|
|
<interfacename>BeanPostProcessor</interfacename> implementations.</para>
|
|
|
|
<para>You can configure multiple <literal>BeanPostProcessors</literal>
|
|
if you wish. You can control the order in which these
|
|
<literal>BeanPostProcessors</literal> execute by setting the
|
|
<literal>'order'</literal> property (you can only set this property if
|
|
the <interfacename>BeanPostProcessor</interfacename> implements the
|
|
<interfacename>Ordered</interfacename> interface; if you write your own
|
|
<interfacename>BeanPostProcessor</interfacename> you should consider
|
|
implementing the <interfacename>Ordered</interfacename> interface too);
|
|
consult the Javadoc for the
|
|
<interfacename>BeanPostProcessor</interfacename> and
|
|
<interfacename>Ordered</interfacename> interfaces for more
|
|
details.</para>
|
|
|
|
<note>
|
|
<para><literal>BeanPostProcessors</literal> operate on bean (or
|
|
object) <emphasis>instances</emphasis>; that is to say, the Spring IoC
|
|
container will have instantiated a bean instance for you, and
|
|
<emphasis>then</emphasis> <literal>BeanPostProcessors</literal> get a
|
|
chance to do their stuff.</para>
|
|
|
|
<para>If you want to change the actual bean definition (that is the
|
|
recipe that defines the bean), then you rather need to use a
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> (described
|
|
below in the section entitled <xref
|
|
linkend="beans-factory-extension-factory-postprocessors" />.</para>
|
|
|
|
<para>Also, <literal>BeanPostProcessors</literal> are scoped
|
|
<emphasis>per-container</emphasis>. This is only relevant if you are
|
|
using container hierarchies. If you define a
|
|
<interfacename>BeanPostProcessor</interfacename> in one container, it
|
|
will <emphasis>only</emphasis> do its stuff on the beans in that
|
|
container. Beans that are defined in another container will not be
|
|
post-processed by <literal>BeanPostProcessors</literal> in another
|
|
container, even if both containers are part of the same
|
|
hierarchy.</para>
|
|
</note>
|
|
|
|
<para>The
|
|
<interfacename>org.springframework.beans.factory.config.BeanPostProcessor</interfacename>
|
|
interface consists of exactly two callback methods. When such a class is
|
|
registered as a post-processor with the container (see below for how
|
|
this registration is effected), for each bean instance that is created
|
|
by the container, the post-processor will get a callback from the
|
|
container both <emphasis>before</emphasis> any container initialization
|
|
methods (such as <emphasis>afterPropertiesSet</emphasis> and any
|
|
declared init method) are called, and also afterwards. The
|
|
post-processor is free to do what it wishes with the bean instance,
|
|
including ignoring the callback completely. A bean post-processor will
|
|
typically check for callback interfaces, or do something such as wrap a
|
|
bean with a proxy; some of the Spring AOP infrastructure classes are
|
|
implemented as bean post-processors and they do this proxy-wrapping
|
|
logic.</para>
|
|
|
|
<para>It is important to know that a
|
|
<interfacename>BeanFactory</interfacename> treats bean post-processors
|
|
slightly differently than an
|
|
<interfacename>ApplicationContext</interfacename>. An
|
|
<interfacename>ApplicationContext</interfacename> will
|
|
<emphasis>automatically detect</emphasis> any beans which are defined in
|
|
the configuration metadata which is supplied to it that implement the
|
|
<interfacename>BeanPostProcessor</interfacename> interface, and register
|
|
them as post-processors, to be then called appropriately by the
|
|
container on bean creation. Nothing else needs to be done other than
|
|
deploying the post-processors in a similar fashion to any other bean. On
|
|
the other hand, when using a <interfacename>BeanFactory</interfacename>
|
|
implementation, bean post-processors explicitly have to be registered,
|
|
with code like this:</para>
|
|
|
|
<programlisting language="java">ConfigurableBeanFactory factory = new XmlBeanFactory(...);
|
|
|
|
<lineannotation>// now register any needed <interfacename>BeanPostProcessor</interfacename> instances</lineannotation>
|
|
MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
|
|
factory.addBeanPostProcessor(postProcessor);
|
|
|
|
<lineannotation>// now start using the factory</lineannotation></programlisting>
|
|
|
|
<para>This explicit registration step is not convenient, and this is one
|
|
of the reasons why the various
|
|
<interfacename>ApplicationContext</interfacename> implementations are
|
|
preferred above plain <interfacename>BeanFactory</interfacename>
|
|
implementations in the vast majority of Spring-backed applications,
|
|
especially when using <literal>BeanPostProcessors</literal>.</para>
|
|
|
|
<note>
|
|
<title><interfacename>BeanPostProcessors</interfacename> and AOP
|
|
auto-proxying</title>
|
|
|
|
<para>Classes that implement the
|
|
<interfacename>BeanPostProcessor</interfacename> interface are
|
|
<emphasis>special</emphasis>, and so they are treated differently by
|
|
the container. All <interfacename>BeanPostProcessors</interfacename>
|
|
<emphasis>and their directly referenced beans</emphasis> will be
|
|
instantiated on startup, as part of the special startup phase of the
|
|
<interfacename>ApplicationContext</interfacename>,
|
|
<emphasis>then</emphasis> all those
|
|
<interfacename>BeanPostProcessors</interfacename> will be registered
|
|
in a sorted fashion - and applied to all further beans. Since AOP
|
|
auto-proxying is implemented as a
|
|
<interfacename>BeanPostProcessor</interfacename> itself, no
|
|
<interfacename>BeanPostProcessors</interfacename> or directly
|
|
referenced beans are eligible for auto-proxying (and thus will not
|
|
have aspects 'woven' into them.</para>
|
|
|
|
<para>For any such bean, you should see an info log message:
|
|
<emphasis><quote>Bean 'foo' is not eligible for getting processed by
|
|
all BeanPostProcessors (for example: not eligible for
|
|
auto-proxying)</quote>.</emphasis></para>
|
|
</note>
|
|
|
|
<para>Find below some examples of how to write, register, and use
|
|
<literal>BeanPostProcessors</literal> in the context of an
|
|
<interfacename>ApplicationContext</interfacename>.</para>
|
|
|
|
<section id="beans-factory-extension-bpp-examples-hw">
|
|
<title>Example: Hello World,
|
|
<interfacename>BeanPostProcessor</interfacename>-style</title>
|
|
|
|
<para>This first example is hardly compelling, but serves to
|
|
illustrate basic usage. All we are going to do is code a custom
|
|
<interfacename>BeanPostProcessor</interfacename> implementation that
|
|
simply invokes the <methodname>toString()</methodname> method of each
|
|
bean as it is created by the container and prints the resulting string
|
|
to the system console. Yes, it is not hugely useful, but serves to get
|
|
the basic concepts across before we move into the second example which
|
|
<emphasis>is</emphasis> actually useful.</para>
|
|
|
|
<para>Find below the custom
|
|
<interfacename>BeanPostProcessor</interfacename> implementation class
|
|
definition:</para>
|
|
|
|
<programlisting language="java">package scripting;
|
|
|
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
import org.springframework.beans.BeansException;
|
|
|
|
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
|
|
|
|
<lineannotation>// simply return the instantiated bean as-is</lineannotation>
|
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
|
return bean; <lineannotation>// we could potentially return <emphasis>any</emphasis> object reference here...</lineannotation>
|
|
}
|
|
|
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
|
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
|
|
return bean;
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:lang="http://www.springframework.org/schema/lang"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/lang
|
|
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
|
|
|
|
<lang:groovy id="messenger"
|
|
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
|
|
<lang:property name="message" value="Fiona Apple Is Just So Dreamy."/>
|
|
</lang:groovy>
|
|
|
|
<lineannotation><!--
|
|
when the above bean ('messenger') is instantiated, this custom
|
|
<interfacename>BeanPostProcessor</interfacename> implementation will output the fact to the system console
|
|
--></lineannotation>
|
|
<bean class="scripting.InstantiationTracingBeanPostProcessor"/>
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>Notice how the
|
|
<classname>InstantiationTracingBeanPostProcessor</classname> is simply
|
|
defined; it doesn't even have a name, and because it is a bean it can
|
|
be dependency injected just like any other bean. (The above
|
|
configuration also just so happens to define a bean that is backed by
|
|
a Groovy script. The Spring 2.0 dynamic language support is detailed
|
|
in the chapter entitled <xref linkend="dynamic-language" />.)</para>
|
|
|
|
<para>Find below a small driver script to exercise the above code and
|
|
configuration;</para>
|
|
|
|
<programlisting language="java">import org.springframework.context.ApplicationContext;
|
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
import org.springframework.scripting.Messenger;
|
|
|
|
public final class Boot {
|
|
|
|
public static void main(final String[] args) throws Exception {
|
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
|
|
Messenger messenger = (Messenger) ctx.getBean("messenger");
|
|
System.out.println(messenger);
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>The output of executing the above program will be (something
|
|
like) this:</para>
|
|
|
|
<programlisting>Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
|
|
org.springframework.scripting.groovy.GroovyMessenger@272961</programlisting>
|
|
</section>
|
|
|
|
<section id="beans-factory-extension-bpp-examples-rabpp">
|
|
<title>Example: The
|
|
<classname>RequiredAnnotationBeanPostProcessor</classname></title>
|
|
|
|
<para>Using callback interfaces or annotations in conjunction with a
|
|
custom <interfacename>BeanPostProcessor</interfacename> implementation
|
|
is a common means of extending the Spring IoC container. This next
|
|
example is a bit of a cop-out, in that you are directed to the section
|
|
entitled <xref linkend="metadata-annotations-required" /> which
|
|
demonstrates the usage of a custom
|
|
<interfacename>BeanPostProcessor</interfacename> implementation that
|
|
ships with the Spring distribution which ensures that JavaBean
|
|
properties on beans that are marked with an (arbitrary) annotation are
|
|
actually (configured to be) dependency-injected with a value.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-extension-factory-postprocessors">
|
|
<title>Customizing configuration metadata with
|
|
<literal>BeanFactoryPostProcessors</literal></title>
|
|
|
|
<para>The next extension point that we will look at is the
|
|
<interfacename>org.springframework.beans.factory.config.BeanFactoryPostProcessor</interfacename>.
|
|
The semantics of this interface are similar to the
|
|
<interfacename>BeanPostProcessor</interfacename>, with one major
|
|
difference: <literal>BeanFactoryPostProcessors</literal> operate on the
|
|
<emphasis>bean configuration metadata</emphasis>; that is, the Spring
|
|
IoC container will allow <literal>BeanFactoryPostProcessors</literal> to
|
|
read the configuration metadata and potentially change it
|
|
<emphasis>before</emphasis> the container has actually instantiated any
|
|
other beans.</para>
|
|
|
|
<para>You can configure multiple
|
|
<literal>BeanFactoryPostProcessors</literal> if you wish. You can
|
|
control the order in which these
|
|
<literal>BeanFactoryPostProcessors</literal> execute by setting the
|
|
<literal>'order'</literal> property (you can only set this property if
|
|
the <interfacename>BeanFactoryPostProcessor</interfacename> implements
|
|
the <interfacename>Ordered</interfacename> interface; if you write your
|
|
own <interfacename>BeanFactoryPostProcessor</interfacename> you should
|
|
consider implementing the <interfacename>Ordered</interfacename>
|
|
interface too); consult the Javadoc for the
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> and
|
|
<interfacename>Ordered</interfacename> interfaces for more
|
|
details.</para>
|
|
|
|
<note>
|
|
<para>If you want to change the actual bean
|
|
<emphasis>instances</emphasis> (the objects that are created from the
|
|
configuration metadata), then you rather need to use a
|
|
<interfacename>BeanPostProcessor</interfacename> (described above in
|
|
the section entitled <xref
|
|
linkend="beans-factory-extension-bpp" />.</para>
|
|
|
|
<para>Also, <literal>BeanFactoryPostProcessors</literal> are scoped
|
|
<emphasis>per-container</emphasis>. This is only relevant if you are
|
|
using container hierarchies. If you define a
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> in one
|
|
container, it will <emphasis>only</emphasis> do its stuff on the bean
|
|
definitions in that container. Bean definitions in another container
|
|
will not be post-processed by
|
|
<literal>BeanFactoryPostProcessors</literal> in another container,
|
|
even if both containers are part of the same hierarchy.</para>
|
|
</note>
|
|
|
|
<para>A bean factory post-processor is executed manually (in the case of
|
|
a <interfacename>BeanFactory</interfacename>) or automatically (in the
|
|
case of an <interfacename>ApplicationContext</interfacename>) to apply
|
|
changes of some sort to the configuration metadata that defines a
|
|
container. Spring includes a number of pre-existing bean factory
|
|
post-processors, such as
|
|
<classname>PropertyOverrideConfigurer</classname> and
|
|
<classname>PropertyPlaceholderConfigurer</classname>, both described
|
|
below. A custom <interfacename>BeanFactoryPostProcessor</interfacename>
|
|
can also be used to register custom property editors, for
|
|
example.</para>
|
|
|
|
<para>In a <interfacename>BeanFactory</interfacename>, the process of
|
|
applying a <interfacename>BeanFactoryPostProcessor</interfacename> is
|
|
manual, and will be similar to this:</para>
|
|
|
|
<programlisting language="java">XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
|
|
|
|
<lineannotation>// bring in some property values from a <classname>Properties</classname> file</lineannotation>
|
|
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
|
|
cfg.setLocation(new FileSystemResource("jdbc.properties"));
|
|
|
|
<lineannotation>// now actually do the replacement</lineannotation>
|
|
cfg.postProcessBeanFactory(factory);</programlisting>
|
|
|
|
<para>This explicit registration step is not convenient, and this is one
|
|
of the reasons why the various
|
|
<interfacename>ApplicationContext</interfacename> implementations are
|
|
preferred above plain <interfacename>BeanFactory</interfacename>
|
|
implementations in the vast majority of Spring-backed applications,
|
|
especially when using
|
|
<literal>BeanFactoryPostProcessors</literal>.</para>
|
|
|
|
<anchor id="beans-factory-autodetect-beanfactorypostprocessors" />
|
|
|
|
<para>An <interfacename>ApplicationContext</interfacename> will detect
|
|
any beans which are deployed into it which implement the
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> interface, and
|
|
automatically use them as bean factory post-processors, at the
|
|
appropriate time. Nothing else needs to be done other than deploying
|
|
these post-processor in a similar fashion to any other bean.</para>
|
|
|
|
<note>
|
|
<para>Just as in the case of <literal>BeanPostProcessors</literal>,
|
|
you typically don't want to have
|
|
<literal>BeanFactoryPostProcessors</literal> marked as being
|
|
lazily-initialized. If they are marked as such, then the Spring
|
|
container will never instantiate them, and thus they won't get a
|
|
chance to apply their custom logic. If you are using the
|
|
<literal>'default-lazy-init'</literal> attribute on the declaration of
|
|
your <literal><beans/></literal> element, be sure to mark your
|
|
various <interfacename>BeanFactoryPostProcessor</interfacename> bean
|
|
definitions with <literal>'lazy-init="false"'</literal>.</para>
|
|
</note>
|
|
|
|
<section id="beans-factory-placeholderconfigurer">
|
|
<title>Example: the
|
|
<interfacename>PropertyPlaceholderConfigurer</interfacename></title>
|
|
|
|
<para>The <interfacename>PropertyPlaceholderConfigurer</interfacename>
|
|
is used to externalize property values from a
|
|
<interfacename>BeanFactory</interfacename> definition, into another
|
|
separate file in the standard Java <classname>Properties</classname>
|
|
format. This is useful to allow the person deploying an application to
|
|
customize environment-specific properties (for example database URLs,
|
|
usernames and passwords), without the complexity or risk of modifying
|
|
the main XML definition file or files for the container.</para>
|
|
|
|
<para>Consider the following XML-based configuration metadata
|
|
fragment, where a <interfacename>DataSource</interfacename> with
|
|
placeholder values is defined. We will configure some properties from
|
|
an external <classname>Properties</classname> file, and at runtime, we
|
|
will apply a <classname>PropertyPlaceholderConfigurer</classname> to
|
|
the metadata which will replace some properties of the
|
|
DataSource:</para>
|
|
|
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
|
<property name="locations">
|
|
<value>classpath:com/foo/jdbc.properties</value>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="dataSource" destroy-method="close"
|
|
class="org.apache.commons.dbcp.BasicDataSource">
|
|
<property name="driverClassName" value="<emphasis role="bold">${jdbc.driverClassName}</emphasis>"/>
|
|
<property name="url" value="<emphasis role="bold">${jdbc.url}</emphasis>"/>
|
|
<property name="username" value="<emphasis role="bold">${jdbc.username}</emphasis>"/>
|
|
<property name="password" value="<emphasis role="bold">${jdbc.password}</emphasis>"/>
|
|
</bean></programlisting>
|
|
|
|
<para>The actual values come from another file in the standard Java
|
|
<classname>Properties</classname> format:</para>
|
|
|
|
<programlisting language="java">jdbc.driverClassName=org.hsqldb.jdbcDriver
|
|
jdbc.url=jdbc:hsqldb:hsql://production:9002
|
|
jdbc.username=sa
|
|
jdbc.password=root</programlisting>
|
|
|
|
<para>With the <literal>context</literal> namespace introduced in
|
|
Spring 2.5, it is possible to configure property placeholders with a
|
|
dedicated configuration element. Multiple locations may be provided as
|
|
a comma-separated list for the <literal>location</literal>
|
|
attribute.</para>
|
|
|
|
<programlisting language="xml"><context:property-placeholder location="classpath:com/foo/jdbc.properties"/></programlisting>
|
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> doesn't
|
|
only look for properties in the <classname>Properties</classname> file
|
|
you specify, but also checks against the Java
|
|
<classname>System</classname> properties if it cannot find a property
|
|
you are trying to use. This behavior can be customized by setting the
|
|
<literal>systemPropertiesMode</literal> property of the configurer. It
|
|
has three values, one to tell the configurer to always override, one
|
|
to let it <emphasis>never</emphasis> override and one to let it
|
|
override only if the property cannot be found in the properties file
|
|
specified. Please consult the Javadoc for the
|
|
<classname>PropertyPlaceholderConfigurer</classname> for more
|
|
information.</para>
|
|
|
|
<tip>
|
|
<title>Class name substitution</title>
|
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> can
|
|
be used to substitute class names, which is sometimes useful when
|
|
you have to pick a particular implementation class at runtime. For
|
|
example:</para>
|
|
|
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
|
<property name="locations">
|
|
<value>classpath:com/foo/strategy.properties</value>
|
|
</property>
|
|
<property name="properties">
|
|
<value>custom.strategy.class=com.foo.DefaultStrategy</value>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="serviceStrategy" class="${custom.strategy.class}"/></programlisting>
|
|
|
|
<para>If the class is unable to be resolved at runtime to a valid
|
|
class, resolution of the bean will fail once it is about to be
|
|
created (which is during the
|
|
<methodname>preInstantiateSingletons()</methodname> phase of an
|
|
<interfacename>ApplicationContext</interfacename> for a
|
|
non-lazy-init bean.)</para>
|
|
</tip>
|
|
</section>
|
|
|
|
<section id="beans-factory-overrideconfigurer">
|
|
<title>Example: the
|
|
<classname>PropertyOverrideConfigurer</classname></title>
|
|
|
|
<para>The <classname>PropertyOverrideConfigurer</classname>, another
|
|
bean factory post-processor, is similar to the
|
|
<interfacename>PropertyPlaceholderConfigurer</interfacename>, but in
|
|
contrast to the latter, the original definitions can have default
|
|
values or no values at all for bean properties. If an overriding
|
|
<classname>Properties</classname> file does not have an entry for a
|
|
certain bean property, the default context definition is used.</para>
|
|
|
|
<para>Note that the bean factory definition is
|
|
<emphasis>not</emphasis> aware of being overridden, so it is not
|
|
immediately obvious when looking at the XML definition file that the
|
|
override configurer is being used. In case that there are multiple
|
|
<classname>PropertyOverrideConfigurer</classname> instances that
|
|
define different values for the same bean property, the last one will
|
|
win (due to the overriding mechanism).</para>
|
|
|
|
<para>Properties file configuration lines are expected to be in the
|
|
format:</para>
|
|
|
|
<programlisting language="java">beanName.property=value</programlisting>
|
|
|
|
<para>An example properties file might look like this:</para>
|
|
|
|
<programlisting language="java">dataSource.driverClassName=com.mysql.jdbc.Driver
|
|
dataSource.url=jdbc:mysql:mydb</programlisting>
|
|
|
|
<para>This example file would be usable against a container definition
|
|
which contains a bean called <emphasis>dataSource</emphasis>, which
|
|
has <emphasis>driver</emphasis> and <emphasis>url</emphasis>
|
|
properties.</para>
|
|
|
|
<para>Note that compound property names are also supported, as long as
|
|
every component of the path except the final property being overridden
|
|
is already non-null (presumably initialized by the constructors). In
|
|
this example...</para>
|
|
|
|
<programlisting language="java">foo.fred.bob.sammy=123</programlisting>
|
|
|
|
<para>... the <literal>sammy</literal> property of the
|
|
<literal>bob</literal> property of the <literal>fred</literal>
|
|
property of the <literal>foo</literal> bean is being set to the scalar
|
|
value <literal>123</literal>.</para>
|
|
|
|
<para><emphasis>Note:</emphasis> Specified override values are always
|
|
<emphasis>literal</emphasis> values; they are not translated into bean
|
|
references. This also applies when the original value in the XML bean
|
|
definition specifies a bean reference</para>
|
|
|
|
<para>With the <literal>context</literal> namespace introduced in
|
|
Spring 2.5, it is possible to configure property overriding with a
|
|
dedicated configuration element:</para>
|
|
|
|
<programlisting language="xml"><context:property-override location="classpath:override.properties"/></programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-extension-factorybean">
|
|
<title>Customizing instantiation logic using
|
|
<literal>FactoryBeans</literal></title>
|
|
|
|
<para>The
|
|
<interfacename>org.springframework.beans.factory.FactoryBean</interfacename>
|
|
interface is to be implemented by objects that <emphasis>are themselves
|
|
factories</emphasis>.</para>
|
|
|
|
<para>The <interfacename>FactoryBean</interfacename> interface is a
|
|
point of pluggability into the Spring IoC containers instantiation
|
|
logic. If you have some complex initialization code that is better
|
|
expressed in Java as opposed to a (potentially) verbose amount of XML,
|
|
you can create your own <interfacename>FactoryBean</interfacename>,
|
|
write the complex initialization inside that class, and then plug your
|
|
custom <interfacename>FactoryBean</interfacename> into the
|
|
container.</para>
|
|
|
|
<para>The <interfacename>FactoryBean</interfacename> interface provides
|
|
three methods:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><methodname>Object getObject()</methodname>: has to return an
|
|
instance of the object this factory creates. The instance can
|
|
possibly be shared (depending on whether this factory returns
|
|
singletons or prototypes).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>boolean isSingleton()</methodname>: has to return
|
|
<literal>true</literal> if this
|
|
<interfacename>FactoryBean</interfacename> returns singletons,
|
|
<literal>false</literal> otherwise</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>Class getObjectType()</methodname>: has to return
|
|
either the object type returned by the
|
|
<methodname>getObject()</methodname> method or
|
|
<literal>null</literal> if the type isn't known in advance</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The <interfacename>FactoryBean</interfacename> concept and
|
|
interface is used in a number of places within the Spring Framework; at
|
|
the time of writing there are over 50 implementations of the
|
|
<interfacename>FactoryBean</interfacename> interface that ship with
|
|
Spring itself.</para>
|
|
|
|
<para>Finally, there is sometimes a need to ask a container for an
|
|
actual <interfacename>FactoryBean</interfacename> instance itself, not
|
|
the bean it produces. This may be achieved by prepending the bean id
|
|
with <literal>'&'</literal> (sans quotes) when calling the
|
|
<methodname>getBean</methodname> method of the
|
|
<interfacename>BeanFactory</interfacename> (including
|
|
<interfacename>ApplicationContext</interfacename>). So for a given
|
|
<interfacename>FactoryBean</interfacename> with an id of
|
|
<literal>myBean</literal>, invoking <literal>getBean("myBean")</literal>
|
|
on the container will return the product of the
|
|
<interfacename>FactoryBean</interfacename>, but invoking
|
|
<literal>getBean("&myBean")</literal> will return the
|
|
<interfacename>FactoryBean</interfacename> instance itself.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="context-introduction">
|
|
<title>The <interfacename>ApplicationContext</interfacename></title>
|
|
|
|
<para>While the <literal>beans</literal> package provides basic
|
|
functionality for managing and manipulating beans, including in a
|
|
programmatic way, the <literal>context</literal> package adds the <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/ApplicationContext.html"><interfacename>ApplicationContext</interfacename></ulink>
|
|
interface, which enhances <interfacename>BeanFactory</interfacename>
|
|
functionality in a more <emphasis>framework-oriented style</emphasis>.
|
|
Many users will use <interfacename>ApplicationContext</interfacename> in a
|
|
completely declarative fashion, not even having to create it manually, but
|
|
instead relying on support classes such as
|
|
<classname>ContextLoader</classname> to automatically instantiate an
|
|
<interfacename>ApplicationContext</interfacename> as part of the normal
|
|
startup process of a J2EE web-app. (Of course, it is still possible to
|
|
create an <interfacename>ApplicationContext</interfacename>
|
|
programmatically.)</para>
|
|
|
|
<para>The basis for the context package is the
|
|
<interfacename>ApplicationContext</interfacename> interface, located in
|
|
the <literal>org.springframework.context</literal> package. Deriving from
|
|
the <interfacename>BeanFactory</interfacename> interface, it provides all
|
|
the functionality of <interfacename>BeanFactory</interfacename>. To allow
|
|
working in a more framework-oriented fashion, using layering and
|
|
hierarchical contexts, the context package also provides the following
|
|
functionality:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><interfacename>MessageSource</interfacename>, providing access
|
|
to messages in i18n-style.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Access to resources</emphasis>, such as URLs and
|
|
files.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Event propagation</emphasis> to beans implementing the
|
|
<interfacename>ApplicationListener</interfacename> interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Loading of multiple (hierarchical)
|
|
contexts</emphasis>, allowing each to be focused on one particular
|
|
layer, for example the web layer of an application.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<section id="context-introduction-ctx-vs-beanfactory">
|
|
<title><interfacename>BeanFactory</interfacename> or
|
|
<interfacename>ApplicationContext</interfacename>?</title>
|
|
|
|
<para>Short version: <emphasis>use an
|
|
<interfacename>ApplicationContext</interfacename> unless you have a
|
|
really good reason for not doing so. For those of you that are looking
|
|
for slightly more depth as to the 'but why' of the above recommendation,
|
|
keep reading.</emphasis></para>
|
|
|
|
<para>As the <interfacename>ApplicationContext</interfacename> includes
|
|
all functionality of the <interfacename>BeanFactory</interfacename>, it
|
|
is generally recommended that it be used in preference to the
|
|
<interfacename>BeanFactory</interfacename>, except for a few limited
|
|
situations such as in an <classname>Applet</classname>, where memory
|
|
consumption might be critical and a few extra kilobytes might make a
|
|
difference. However, for most 'typical' enterprise applications and
|
|
systems, the <interfacename>ApplicationContext</interfacename> is what
|
|
you will want to use. Versions of Spring 2.0 and above make
|
|
<emphasis>heavy</emphasis> use of the <link
|
|
linkend="beans-factory-extension-bpp"><interfacename>BeanPostProcessor</interfacename>
|
|
extension point</link> (to effect proxying and suchlike), and if you are
|
|
using just a plain <interfacename>BeanFactory</interfacename> then a
|
|
fair amount of support such as transactions and AOP will not take effect
|
|
(at least not without some extra steps on your part), which could be
|
|
confusing because nothing will actually be wrong with the
|
|
configuration.</para>
|
|
|
|
<para>Find below a feature matrix that lists what features are provided
|
|
by the <interfacename>BeanFactory</interfacename> and
|
|
<interfacename>ApplicationContext</interfacename> interfaces (and
|
|
attendant implementations). (The following sections describe
|
|
functionality that <interfacename>ApplicationContext</interfacename>
|
|
adds to the basic <interfacename>BeanFactory</interfacename>
|
|
capabilities in a lot more depth than the said feature matrix.)</para>
|
|
|
|
<table id="context-introduction-ctx-vs-beanfactory-feature-matrix"
|
|
pgwide="1">
|
|
<title>Feature Matrix</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec align="left" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry align="center">Feature</entry>
|
|
|
|
<entry
|
|
align="center"><interfacename>BeanFactory</interfacename></entry>
|
|
|
|
<entry
|
|
align="center"><interfacename>ApplicationContext</interfacename></entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><para>Bean instantiation/wiring</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<interfacename>BeanPostProcessor</interfacename>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Automatic
|
|
<interfacename>BeanFactoryPostProcessor</interfacename>
|
|
registration</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para>Convenient
|
|
<interfacename>MessageSource</interfacename> access (for
|
|
i18n)</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><para><interfacename>ApplicationEvent</interfacename>
|
|
publication</para></entry>
|
|
|
|
<entry align="center"><para>No</para></entry>
|
|
|
|
<entry align="center"><para>Yes</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</section>
|
|
|
|
<section id="context-functionality-messagesource">
|
|
<title>Internationalization using
|
|
<literal>MessageSources</literal></title>
|
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> interface
|
|
extends an interface called
|
|
<interfacename>MessageSource</interfacename>, and therefore provides
|
|
messaging (i18n or internationalization) functionality. Together with
|
|
the <classname>HierarchicalMessageSource</classname>, capable of
|
|
resolving hierarchical messages, these are the basic interfaces Spring
|
|
provides to do message resolution. Let's quickly review the methods
|
|
defined there:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><methodname>String getMessage(String code, Object[] args,
|
|
String default, Locale loc)</methodname>: the basic method used to
|
|
retrieve a message from the
|
|
<interfacename>MessageSource</interfacename>. When no message is
|
|
found for the specified locale, the default message is used. Any
|
|
arguments passed in are used as replacement values, using the
|
|
<interfacename>MessageFormat</interfacename> functionality provided
|
|
by the standard library.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>String getMessage(String code, Object[] args,
|
|
Locale loc)</methodname>: essentially the same as the previous
|
|
method, but with one difference: no default message can be
|
|
specified; if the message cannot be found, a
|
|
<classname>NoSuchMessageException</classname> is thrown.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>String getMessage(MessageSourceResolvable
|
|
resolvable, Locale locale)</methodname>: all properties used in the
|
|
methods above are also wrapped in a class named
|
|
<interfacename>MessageSourceResolvable</interfacename>, which you
|
|
can use via this method.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>When an <interfacename>ApplicationContext</interfacename> gets
|
|
loaded, it automatically searches for a
|
|
<interfacename>MessageSource</interfacename> bean defined in the
|
|
context. The bean has to have the name
|
|
<literal>'messageSource'</literal>. If such a bean is found, all calls
|
|
to the methods described above will be delegated to the message source
|
|
that was found. If no message source was found, the
|
|
<interfacename>ApplicationContext</interfacename> attempts to see if it
|
|
has a parent containing a bean with the same name. If so, it uses that
|
|
bean as the <interfacename>MessageSource</interfacename>. If it can't
|
|
find any source for messages, an empty
|
|
<classname>DelegatingMessageSource</classname> will be instantiated in
|
|
order to be able to accept calls to the methods defined above.</para>
|
|
|
|
<para>Spring currently provides two
|
|
<interfacename>MessageSource</interfacename> implementations. These are
|
|
the <classname>ResourceBundleMessageSource</classname> and the
|
|
<classname>StaticMessageSource</classname>. Both implement
|
|
<interfacename>HierarchicalMessageSource</interfacename> in order to do
|
|
nested messaging. The <classname>StaticMessageSource</classname> is
|
|
hardly ever used but provides programmatic ways to add messages to the
|
|
source. The <classname>ResourceBundleMessageSource</classname> is more
|
|
interesting and is the one we will provide an example for:</para>
|
|
|
|
<programlisting language="xml"><beans>
|
|
<bean id="messageSource"
|
|
class="org.springframework.context.support.ResourceBundleMessageSource">
|
|
<property name="basenames">
|
|
<list>
|
|
<value>format</value>
|
|
<value>exceptions</value>
|
|
<value>windows</value>
|
|
</list>
|
|
</property>
|
|
</bean>
|
|
</beans></programlisting>
|
|
|
|
<para>This assumes you have three resource bundles defined on your
|
|
classpath called <literal>format</literal>,
|
|
<literal>exceptions</literal> and <literal>windows</literal>. Using the
|
|
JDK standard way of resolving messages through ResourceBundles, any
|
|
request to resolve a message will be handled. For the purposes of the
|
|
example, lets assume the contents of two of the above resource bundle
|
|
files are...</para>
|
|
|
|
<programlisting language="java"><lineannotation># in 'format.properties'</lineannotation>
|
|
message=Alligators rock!</programlisting>
|
|
|
|
<programlisting language="java"><lineannotation># in 'exceptions.properties'</lineannotation>
|
|
argument.required=The '{0}' argument is required.</programlisting>
|
|
|
|
<para>Some (admittedly trivial) driver code to exercise the
|
|
<classname>MessageSource</classname> functionality can be found below.
|
|
Remember that all <classname>ApplicationContext</classname>
|
|
implementations are also <classname>MessageSource</classname>
|
|
implementations and so can be cast to the
|
|
<classname>MessageSource</classname> interface.</para>
|
|
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
|
|
String message = resources.getMessage("message", null, "Default", null);
|
|
System.out.println(message);
|
|
}</programlisting>
|
|
|
|
<para>The resulting output from the above program will be...</para>
|
|
|
|
<programlisting>Alligators rock!</programlisting>
|
|
|
|
<para>So to summarize, the <classname>MessageSource</classname> is
|
|
defined in a file called <literal>'beans.xml'</literal> (this file
|
|
exists at the root of your classpath). The
|
|
<literal>'messageSource'</literal> bean definition refers to a number of
|
|
resource bundles via its <literal>basenames</literal> property; the
|
|
three files that are passed in the list to the
|
|
<literal>basenames</literal> property exist as files at the root of your
|
|
classpath (and are called <literal>format.properties</literal>,
|
|
<literal>exceptions.properties</literal>, and
|
|
<literal>windows.properties</literal> respectively).</para>
|
|
|
|
<para>Lets look at another example, and this time we will look at
|
|
passing arguments to the message lookup; these arguments will be
|
|
converted into Strings and inserted into placeholders in the lookup
|
|
message. This is perhaps best explained with an example:</para>
|
|
|
|
<programlisting language="xml"><beans>
|
|
|
|
<lineannotation><!-- this <interfacename>MessageSource</interfacename> is being used in a web application --></lineannotation>
|
|
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
|
|
<property name="basename" value="test-messages"/>
|
|
</bean>
|
|
|
|
<lineannotation><!-- let's inject the above <interfacename>MessageSource</interfacename> into this POJO --></lineannotation>
|
|
<bean id="example" class="com.foo.Example">
|
|
<property name="messages" ref="messageSource"/>
|
|
</bean>
|
|
|
|
</beans></programlisting>
|
|
|
|
<programlisting language="java">public class Example {
|
|
|
|
private MessageSource messages;
|
|
|
|
public void setMessages(MessageSource messages) {
|
|
this.messages = messages;
|
|
}
|
|
|
|
public void execute() {
|
|
String message = this.messages.getMessage("argument.required",
|
|
new Object [] {"userDao"}, "Required", null);
|
|
System.out.println(message);
|
|
}
|
|
|
|
}</programlisting>
|
|
|
|
<para>The resulting output from the invocation of the
|
|
<methodname>execute()</methodname> method will be...</para>
|
|
|
|
<programlisting>The 'userDao' argument is required.</programlisting>
|
|
|
|
<para>With regard to internationalization (i18n), Spring's various
|
|
<classname>MessageResource</classname> implementations follow the same
|
|
locale resolution and fallback rules as the standard JDK
|
|
<classname>ResourceBundle</classname>. In short, and continuing with the
|
|
example <literal>'messageSource'</literal> defined previously, if you
|
|
want to resolve messages against the British (en-GB) locale, you would
|
|
create files called <literal>format_en_GB.properties</literal>,
|
|
<literal>exceptions_en_GB.properties</literal>, and
|
|
<literal>windows_en_GB.properties</literal> respectively.</para>
|
|
|
|
<para>Locale resolution is typically going to be managed by the
|
|
surrounding environment of the application. For the purpose of this
|
|
example though, we'll just manually specify the locale that we want to
|
|
resolve our (British) messages against.</para>
|
|
|
|
<programlisting><lineannotation># in 'exceptions_en_GB.properties'</lineannotation>
|
|
argument.required=Ebagum lad, the '{0}' argument is required, I say, required.</programlisting>
|
|
|
|
<programlisting language="java">public static void main(final String[] args) {
|
|
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
|
|
String message = resources.getMessage("argument.required",
|
|
new Object [] {"userDao"}, "Required", Locale.UK);
|
|
System.out.println(message);
|
|
}</programlisting>
|
|
|
|
<para>The resulting output from the running of the above program will
|
|
be...</para>
|
|
|
|
<programlisting>Ebagum lad, the 'userDao' argument is required, I say, required.</programlisting>
|
|
|
|
<para>The <classname>MessageSourceAware</classname> interface can also
|
|
be used to acquire a reference to any
|
|
<classname>MessageSource</classname> that has been defined. Any bean
|
|
that is defined in an <classname>ApplicationContext</classname> that
|
|
implements the <classname>MessageSourceAware</classname> interface will
|
|
be injected with the application context's
|
|
<classname>MessageSource</classname> when it (the bean) is being created
|
|
and configured.</para>
|
|
|
|
<para><emphasis>Note: As an alternative to
|
|
<classname>ResourceBundleMessageSource</classname>, Spring also provides
|
|
a <classname>ReloadableResourceBundleMessageSource</classname> class.
|
|
This variant supports the same bundle file format but is more flexible
|
|
than the standard JDK based
|
|
<classname>ResourceBundleMessageSource</classname>
|
|
implementation.</emphasis> In particular, it allows for reading files
|
|
from any Spring resource location (not just from the classpath) and
|
|
supports hot reloading of bundle property files (while efficiently
|
|
caching them in between). Check out the
|
|
<classname>ReloadableResourceBundleMessageSource</classname> javadoc for
|
|
details.</para>
|
|
</section>
|
|
|
|
<section id="context-functionality-events">
|
|
<title>Events</title>
|
|
|
|
<para>Event handling in the
|
|
<interfacename>ApplicationContext</interfacename> is provided through
|
|
the <classname>ApplicationEvent</classname> class and
|
|
<interfacename>ApplicationListener</interfacename> interface. If a bean
|
|
which implements the <interfacename>ApplicationListener</interfacename>
|
|
interface is deployed into the context, every time an
|
|
<classname>ApplicationEvent</classname> gets published to the
|
|
<interfacename>ApplicationContext</interfacename>, that bean will be
|
|
notified. Essentially, this is the standard
|
|
<emphasis>Observer</emphasis> design pattern. Spring provides the
|
|
following standard events:</para>
|
|
|
|
<table id="beans-ctx-events-tbl">
|
|
<title>Built-in Events</title>
|
|
|
|
<tgroup cols="2">
|
|
<colspec colname="c1" colwidth="2*" />
|
|
|
|
<colspec colname="c2" colwidth="5*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Event</entry>
|
|
|
|
<entry>Explanation</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><classname>ContextRefreshedEvent</classname></entry>
|
|
|
|
<entry>Published when the
|
|
<interfacename>ApplicationContext</interfacename> is initialized
|
|
or refreshed, e.g. using the <methodname>refresh()</methodname>
|
|
method on the
|
|
<interfacename>ConfigurableApplicationContext</interfacename>
|
|
interface. "Initialized" here means that all beans are loaded,
|
|
post-processor beans are detected and activated, singletons are
|
|
pre-instantiated, and the
|
|
<interfacename>ApplicationContext</interfacename> object is
|
|
ready for use. A refresh may be triggered multiple times, as
|
|
long as the context hasn't been closed - provided that the
|
|
chosen <interfacename>ApplicationContext</interfacename>
|
|
actually supports such "hot" refreshes (which e.g.
|
|
<classname>XmlWebApplicationContext</classname> does but
|
|
<classname>GenericApplicationContext</classname>
|
|
doesn't).</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><classname>ContextStartedEvent</classname></entry>
|
|
|
|
<entry>Published when the
|
|
<interfacename>ApplicationContext</interfacename> is started,
|
|
using the <methodname>start()</methodname> method on the
|
|
<interfacename>ConfigurableApplicationContext</interfacename>
|
|
interface. "Started" here means that all
|
|
<interfacename>Lifecycle</interfacename> beans will receive an
|
|
explicit start signal. This will typically be used for
|
|
restarting after an explicit stop, but may also be used for
|
|
starting components that haven't been configured for autostart
|
|
(e.g. haven't started on initialization already).</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><classname>ContextStoppedEvent</classname></entry>
|
|
|
|
<entry>Published when the
|
|
<interfacename>ApplicationContext</interfacename> is stopped,
|
|
using the <methodname>stop()</methodname> method on the
|
|
<interfacename>ConfigurableApplicationContext</interfacename>
|
|
interface. "Stopped" here means that all
|
|
<interfacename>Lifecycle</interfacename> beans will receive an
|
|
explicit stop signal. A stopped context may be restarted through
|
|
a <methodname>start()</methodname> call.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><classname>ContextClosedEvent</classname></entry>
|
|
|
|
<entry>Published when the
|
|
<interfacename>ApplicationContext</interfacename> is closed,
|
|
using the <methodname>close()</methodname> method on the
|
|
<interfacename>ConfigurableApplicationContext</interfacename>
|
|
interface. "Closed" here means that all singleton beans are
|
|
destroyed. A closed context has reached its end of life; it
|
|
cannot be refreshed or restarted.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><classname>RequestHandledEvent</classname></entry>
|
|
|
|
<entry>A web-specific event telling all beans that an HTTP
|
|
request has been serviced (this will be published
|
|
<emphasis>after</emphasis> the request has been finished). Note
|
|
that this event is only applicable for web applications using
|
|
Spring's <classname>DispatcherServlet</classname>.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>Implementing custom events can be done as well. Simply call the
|
|
<methodname>publishEvent()</methodname> method on the
|
|
<interfacename>ApplicationContext</interfacename>, specifying a
|
|
parameter which is an instance of your custom event class implementing
|
|
<classname>ApplicationEvent</classname>. Event listeners receive events
|
|
synchronously. This means the <methodname>publishEvent()</methodname>
|
|
method blocks until all listeners have finished processing the event (it
|
|
is possible to supply an alternate event publishing strategy via a
|
|
<interfacename>ApplicationEventMulticaster</interfacename>
|
|
implementation). Furthermore, when a listener receives an event it
|
|
operates inside the transaction context of the publisher, if a
|
|
transaction context is available.</para>
|
|
|
|
<para>Let's look at an example. First, the
|
|
<interfacename>ApplicationContext</interfacename>:</para>
|
|
|
|
<programlisting language="xml"><bean id="emailer" class="example.EmailBean">
|
|
<property name="blackList">
|
|
<list>
|
|
<value>black@list.org</value>
|
|
<value>white@list.org</value>
|
|
<value>john@doe.org</value>
|
|
</list>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="blackListListener" class="example.BlackListNotifier">
|
|
<property name="notificationAddress" value="spam@list.org"/>
|
|
</bean></programlisting>
|
|
|
|
<para>Now, let's look at the actual classes:</para>
|
|
|
|
<programlisting language="java">public class EmailBean implements ApplicationContextAware {
|
|
|
|
private List blackList;
|
|
private ApplicationContext ctx;
|
|
|
|
public void setBlackList(List blackList) {
|
|
this.blackList = blackList;
|
|
}
|
|
|
|
public void setApplicationContext(ApplicationContext ctx) {
|
|
this.ctx = ctx;
|
|
}
|
|
|
|
public void sendEmail(String address, String text) {
|
|
if (blackList.contains(address)) {
|
|
BlackListEvent event = new BlackListEvent(address, text);
|
|
ctx.publishEvent(event);
|
|
return;
|
|
}
|
|
<lineannotation>// send email...</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">public class BlackListNotifier implements ApplicationListener {
|
|
|
|
private String notificationAddress;
|
|
|
|
public void setNotificationAddress(String notificationAddress) {
|
|
this.notificationAddress = notificationAddress;
|
|
}
|
|
|
|
public void onApplicationEvent(ApplicationEvent event) {
|
|
if (event instanceof BlackListEvent) {
|
|
<lineannotation>// notify appropriate person...</lineannotation>
|
|
}
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Of course, this particular example could probably be implemented
|
|
in better ways (perhaps by using AOP features), but it should be
|
|
sufficient to illustrate the basic event mechanism.</para>
|
|
</section>
|
|
|
|
<section id="context-functionality-resources">
|
|
<title>Convenient access to low-level resources</title>
|
|
|
|
<para>For optimal usage and understanding of application contexts, users
|
|
should generally familiarize themselves with Spring's
|
|
<interfacename>Resource</interfacename> abstraction, as described in the
|
|
chapter entitled <xref linkend="resources" />.</para>
|
|
|
|
<para>An application context is a
|
|
<interfacename>ResourceLoader</interfacename>, able to be used to load
|
|
<interfacename>Resource</interfacename>s. A
|
|
<interfacename>Resource</interfacename> is essentially a
|
|
<literal>java.net.URL</literal> on steroids (in fact, it just wraps and
|
|
uses a URL where appropriate), which can be used to obtain low-level
|
|
resources from almost any location in a transparent fashion, including
|
|
from the classpath, a filesystem location, anywhere describable with a
|
|
standard URL, and some other variations. If the resource location string
|
|
is a simple path without any special prefixes, where those resources
|
|
come from is specific and appropriate to the actual application context
|
|
type.</para>
|
|
|
|
<para>A bean deployed into the application context may implement the
|
|
special callback interface,
|
|
<interfacename>ResourceLoaderAware</interfacename>, to be automatically
|
|
called back at initialization time with the application context itself
|
|
passed in as the <interfacename>ResourceLoader</interfacename>. A bean
|
|
may also expose properties of type
|
|
<interfacename>Resource</interfacename>, to be used to access static
|
|
resources, and expect that they will be injected into it like any other
|
|
properties. The person deploying the bean may specify those
|
|
<interfacename>Resource</interfacename> properties as simple String
|
|
paths, and rely on a special JavaBean
|
|
<interfacename>PropertyEditor</interfacename> that is automatically
|
|
registered by the context, to convert those text strings to actual
|
|
<interfacename>Resource</interfacename> objects.</para>
|
|
|
|
<para>The location path or paths supplied to an
|
|
<interfacename>ApplicationContext</interfacename> constructor are
|
|
actually resource strings, and in simple form are treated appropriately
|
|
to the specific context implementation (
|
|
<classname>ClassPathXmlApplicationContext</classname> treats a simple
|
|
location path as a classpath location), but may also be used with
|
|
special prefixes to force loading of definitions from the classpath or a
|
|
URL, regardless of the actual context type.</para>
|
|
</section>
|
|
|
|
<section id="context-create">
|
|
<title>Convenient <interfacename>ApplicationContext</interfacename>
|
|
instantiation for web applications</title>
|
|
|
|
<para>As opposed to the <interfacename>BeanFactory</interfacename>,
|
|
which will often be created programmatically,
|
|
<interfacename>ApplicationContext</interfacename> instances can be
|
|
created declaratively using for example a
|
|
<classname>ContextLoader</classname>. Of course you can also create
|
|
<interfacename>ApplicationContext</interfacename> instances
|
|
programmatically using one of the
|
|
<interfacename>ApplicationContext</interfacename> implementations.
|
|
First, let's examine the <classname>ContextLoader</classname> mechanism
|
|
and its implementations.</para>
|
|
|
|
<para>The <classname>ContextLoader</classname> mechanism comes in two
|
|
flavors: the <classname>ContextLoaderListener</classname> and the
|
|
<classname>ContextLoaderServlet</classname>. They both have the same
|
|
functionality but differ in that the listener version cannot be reliably
|
|
used in Servlet 2.3 containers. Since the Servlet 2.4 specification,
|
|
servlet context listeners are required to execute immediately after the
|
|
servlet context for the web application has been created and is
|
|
available to service the first request (and also when the servlet
|
|
context is about to be shut down): as such a servlet context listener is
|
|
an ideal place to initialize the Spring
|
|
<interfacename>ApplicationContext</interfacename>. It is up to you as to
|
|
which one you use, but all things being equal you should probably prefer
|
|
<classname>ContextLoaderListener</classname>; for more information on
|
|
compatibility, have a look at the Javadoc for the
|
|
<classname>ContextLoaderServlet</classname>.</para>
|
|
|
|
<para>You can register an
|
|
<interfacename>ApplicationContext</interfacename> using the
|
|
<classname>ContextLoaderListener</classname> as follows:</para>
|
|
|
|
<programlisting language="xml"><context-param>
|
|
<param-name>contextConfigLocation</param-name>
|
|
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
|
|
</context-param>
|
|
|
|
<listener>
|
|
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
|
</listener>
|
|
|
|
<lineannotation><!-- or use the <classname>ContextLoaderServlet</classname> instead of the above listener</lineannotation><emphasis>
|
|
<servlet>
|
|
<servlet-name>context</servlet-name>
|
|
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
|
|
<load-on-startup>1</load-on-startup>
|
|
</servlet>
|
|
--</emphasis>></programlisting>
|
|
|
|
<para>The listener inspects the
|
|
<literal>'contextConfigLocation'</literal> parameter. If the parameter
|
|
does not exist, the listener will use
|
|
<literal>/WEB-INF/applicationContext.xml</literal> as a default. When it
|
|
<emphasis>does</emphasis> exist, it will separate the String using
|
|
predefined delimiters (comma, semicolon and whitespace) and use the
|
|
values as locations where application contexts will be searched for.
|
|
Ant-style path patterns are supported as well: e.g.
|
|
<literal>/WEB-INF/*Context.xml</literal> (for all files whose name ends
|
|
with "Context.xml", residing in the "WEB-INF" directory) or
|
|
<literal>/WEB-INF/**/*Context.xml</literal> (for all such files in any
|
|
subdirectory of "WEB-INF").</para>
|
|
|
|
<para>The <classname>ContextLoaderServlet</classname> can be used
|
|
instead of the <classname>ContextLoaderListener</classname>. The servlet
|
|
will use the <literal>'contextConfigLocation'</literal> parameter just
|
|
as the listener does.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-glue-code-and-singletons">
|
|
<title>Glue code and the evil singleton</title>
|
|
|
|
<para>The majority of the code inside an application is best written in a
|
|
DI style, where that code is served out of a Spring IoC container, has its
|
|
own dependencies supplied by the container when it is created, and is
|
|
completely unaware of the container. However, for the small glue layers of
|
|
code that are sometimes needed to tie other code together, there is
|
|
sometimes a need for singleton (or quasi-singleton) style access to a
|
|
Spring IoC container. For example, third party code may try to construct
|
|
new objects directly (<literal>Class.forName()</literal> style), without
|
|
the ability to force it to get these objects out of a Spring IoC
|
|
container. If the object constructed by the third party code is just a
|
|
small stub or proxy, which then uses a singleton style access to a Spring
|
|
IoC container to get a real object to delegate to, then inversion of
|
|
control has still been achieved for the majority of the code (the object
|
|
coming out of the container); thus most code is still unaware of the
|
|
container or how it is accessed, and remains decoupled from other code,
|
|
with all ensuing benefits. EJBs may also use this stub/proxy approach to
|
|
delegate to a plain Java implementation object, coming out of a Spring IoC
|
|
container. While the Spring IoC container itself ideally does not have to
|
|
be a singleton, it may be unrealistic in terms of memory usage or
|
|
initialization times (when using beans in the Spring IoC container such as
|
|
a Hibernate <interfacename>SessionFactory</interfacename>) for each bean
|
|
to use its own, non-singleton Spring IoC container.</para>
|
|
|
|
<para>As another example, in complex J2EE applications with multiple
|
|
layers (various JAR files, EJBs, and WAR files packaged as an EAR), with
|
|
each layer having its own Spring IoC container definition (effectively
|
|
forming a hierarchy), the preferred approach when there is only one
|
|
web-app (WAR) in the top hierarchy is to simply create one composite
|
|
Spring IoC container from the multiple XML definition files from each
|
|
layer. All of the various Spring IoC container implementations may be
|
|
constructed from multiple definition files in this fashion. However, if
|
|
there are multiple sibling web-applications at the root of the hierarchy,
|
|
it is problematic to create a Spring IoC container for each
|
|
web-application which consists of mostly identical bean definitions from
|
|
lower layers, as there may be issues due to increased memory usage, issues
|
|
with creating multiple copies of beans which take a long time to
|
|
initialize (for example a Hibernate
|
|
<interfacename>SessionFactory</interfacename>), and possible issues due to
|
|
side-effects. As an alternative, classes such as <literal><ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html">ContextSingletonBeanFactoryLocator</ulink></literal>
|
|
or <literal><ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.html">SingletonBeanFactoryLocator</ulink></literal>
|
|
may be used to demand-load multiple hierarchical (that is one container is
|
|
the parent of another) Spring IoC container instances in a singleton
|
|
fashion, which may then be used as the parents of the web-application
|
|
Spring IoC container instances. The result is that bean definitions for
|
|
lower layers are loaded only as needed, and loaded only once.</para>
|
|
|
|
<para>You can see a detailed example of the usage of these classes by
|
|
viewing the Javadoc for the <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/access/SingletonBeanFactoryLocator.html">SingletonBeanFactoryLocator</ulink>
|
|
and <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html">ContextSingletonBeanFactoryLocator</ulink>
|
|
classes. As mentioned in the <link linkend="ejb">chapter on EJBs</link>,
|
|
the Spring convenience base classes for EJBs normally use a non-singleton
|
|
<interfacename>BeanFactoryLocator</interfacename> implementation, which is
|
|
easily replaced by the use of
|
|
<classname>SingletonBeanFactoryLocator</classname> and
|
|
<classname>ContextSingletonBeanFactoryLocator</classname>.</para>
|
|
</section>
|
|
|
|
<section id="beans-rar-deployment">
|
|
<title>Deploying a Spring ApplicationContext as a J2EE RAR file</title>
|
|
|
|
<para>Since Spring 2.5, it is possible to deploy a Spring
|
|
ApplicationContext as a RAR file, encapsulating the context and all of its
|
|
required bean classes and library JARs in a J2EE RAR deployment unit. This
|
|
is the equivalent of bootstrapping a standalone ApplicationContext, just
|
|
hosted in J2EE environment, being able to access the J2EE server's
|
|
facilities. RAR deployment is intended as a more 'natural' alternative to
|
|
the not uncommon scenario of deploying a headless WAR file - i.e. a WAR
|
|
file without any HTTP entry points, just used for bootstrapping a Spring
|
|
ApplicationContext in a J2EE environment.</para>
|
|
|
|
<para>RAR deployment is ideal for application contexts that do not need
|
|
any HTTP entry points but rather just consist of message endpoints and
|
|
scheduled jobs etc. Beans in such a context may use application server
|
|
resources such as the JTA transaction manager and JNDI-bound JDBC
|
|
DataSources and JMS ConnectionFactory instances, and may also register
|
|
with the platform's JMX server - all through Spring's standard transaction
|
|
management and JNDI and JMX support facilities. Application components may
|
|
also interact with the application's server JCA WorkManager through
|
|
Spring's <interfacename>TaskExecutor</interfacename> abstraction.</para>
|
|
|
|
<para>Check out the JavaDoc of the <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/jca/context/SpringContextResourceAdapter.html">SpringContextResourceAdapter</ulink>
|
|
class for the configuration details involved in RAR deployment.</para>
|
|
|
|
<para><emphasis>For simple deployment needs, all you need to do is the
|
|
following:</emphasis> Package all application classes into a RAR file
|
|
(which is just a standard JAR file with a different file extension), add
|
|
all required library jars into the root of the RAR archive, add a
|
|
"META-INF/ra.xml" deployment descriptor (as shown in
|
|
<classname>SpringContextResourceAdapter</classname>'s JavaDoc) as well as
|
|
the corresponding Spring XML bean definition file(s) (typically
|
|
"META-INF/applicationContext.xml"), and drop the resulting RAR file into
|
|
your application server's deployment directory!</para>
|
|
|
|
<para><emphasis>NOTE:</emphasis> Such RAR deployment units are usually
|
|
self-contained; they do not expose components to the 'outside' world, not
|
|
even to other modules of the same application. Interaction with a
|
|
RAR-based ApplicationContext usually happens through JMS destinations that
|
|
it shares with other modules. A RAR-based ApplicationContext may also -
|
|
for example - schedule some jobs, reacting to new files in the file system
|
|
(or the like). If it actually needs to allow for synchronous access from
|
|
the outside, it could for example export RMI endpoints, which of course
|
|
may be used by other application modules on the same machine as
|
|
well.</para>
|
|
</section>
|
|
|
|
<section id="beans-annotation-config">
|
|
<title>Annotation-based configuration</title>
|
|
|
|
<para>As mentioned in the section entitled <xref
|
|
linkend="beans-factory-extension-bpp-examples-rabpp" />, using a
|
|
<interfacename>BeanPostProcessor</interfacename> in conjunction with
|
|
annotations is a common means of extending the Spring IoC container. For
|
|
example, Spring 2.0 introduced the possibility of enforcing required
|
|
properties with the <link
|
|
linkend="metadata-annotations-required">@Required</link> annotation. As of
|
|
Spring 2.5, it is now possible to follow that same general approach to
|
|
drive Spring's dependency injection. Essentially, the
|
|
<interfacename>@Autowired</interfacename> annotation provides the same
|
|
capabilities as described in <xref linkend="beans-factory-autowire" /> but
|
|
with more fine-grained control and wider applicability. Spring 2.5 also
|
|
adds support for JSR-250 annotations such as
|
|
<interfacename>@Resource</interfacename>,
|
|
<interfacename>@PostConstruct</interfacename>, and
|
|
<interfacename>@PreDestroy</interfacename>. Use of these annotations also
|
|
requires that certain <interfacename>BeanPostProcessors</interfacename> be
|
|
registered within the Spring container. As always, these can be registered
|
|
as individual bean definitions, but they can also be implicitly registered
|
|
by including the following tag in an XML-based Spring configuration
|
|
(notice the inclusion of the '<literal>context</literal>'
|
|
namespace):</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
<lineannotation>xmlns:context="http://www.springframework.org/schema/context"</lineannotation>
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
|
|
|
<lineannotation><context:annotation-config/></lineannotation>
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>(The implicitly registered post-processors include <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"><classname>AutowiredAnnotationBeanPostProcessor</classname></ulink>,
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"><classname>CommonAnnotationBeanPostProcessor</classname></ulink>,
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html"><classname>PersistenceAnnotationBeanPostProcessor</classname></ulink>,
|
|
as well as the aforementioned <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"><classname>RequiredAnnotationBeanPostProcessor</classname></ulink>.)</para>
|
|
|
|
<note>
|
|
<para>Note that <literal><context:annotation-config/></literal>
|
|
only looks for annotations on beans in the same application context it
|
|
is defined in. This means that, if you put
|
|
<literal><context:annotation-config/></literal> in a
|
|
<interfacename>WebApplicationContext</interfacename> for a
|
|
<classname>DispatcherServlet</classname>, it only checks for
|
|
<interfacename>@Autowired</interfacename> beans in your controllers, and
|
|
not your services. See <xref linkend="mvc-servlet" /> for more
|
|
information.</para>
|
|
</note>
|
|
|
|
<section id="beans-required-annotation">
|
|
<title><interfacename>@Required</interfacename></title>
|
|
|
|
<para>The <interfacename>@Required</interfacename> annotation applies to
|
|
bean property setter methods, as in the following example:</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
@Required
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>This annotation simply indicates that the affected bean property
|
|
must be populated at configuration time: either through an explicit
|
|
property value in a bean definition or through autowiring. The container
|
|
will throw an exception if the affected bean property has not been
|
|
populated; this allows for eager and explicit failure, avoiding
|
|
<classname>NullPointerException</classname>s or the like later on. Note
|
|
that it is still recommended to put assertions into the bean class
|
|
itself (for example into an init method) in order to enforce those
|
|
required references and values even when using the class outside of a
|
|
container.</para>
|
|
</section>
|
|
|
|
<section id="beans-autowired-annotation">
|
|
<title><interfacename>@Autowired</interfacename></title>
|
|
|
|
<para>As expected, the <interfacename>@Autowired</interfacename>
|
|
annotation may be applied to "traditional" setter methods:</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
@Autowired
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The annotation may also be applied to methods with arbitrary names
|
|
and/or multiple arguments:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
private MovieCatalog movieCatalog;
|
|
|
|
private CustomerPreferenceDao customerPreferenceDao;
|
|
|
|
@Autowired
|
|
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
|
|
this.movieCatalog = movieCatalog;
|
|
this.customerPreferenceDao = customerPreferenceDao;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The <interfacename>@Autowired</interfacename> annotation may even
|
|
be applied on constructors and fields:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
private MovieCatalog movieCatalog;
|
|
|
|
private CustomerPreferenceDao customerPreferenceDao;
|
|
|
|
@Autowired
|
|
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
|
|
this.customerPreferenceDao = customerPreferenceDao;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>It is also possible to provide <emphasis>all</emphasis> beans of a
|
|
particular type from the
|
|
<interfacename>ApplicationContext</interfacename> by adding the
|
|
annotation to a field or method that expects an array of that
|
|
type:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
private MovieCatalog[] movieCatalogs;
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The same applies for typed collections:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
private Set<MovieCatalog> movieCatalogs;
|
|
|
|
@Autowired
|
|
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
|
|
this.movieCatalogs = movieCatalogs;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>Even typed Maps may be autowired as long as the expected key type
|
|
is <classname>String</classname>. The Map values will contain all beans
|
|
of the expected type, and the keys will contain the corresponding bean
|
|
names:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
private Map<String, MovieCatalog> movieCatalogs;
|
|
|
|
@Autowired
|
|
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
|
|
this.movieCatalogs = movieCatalogs;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>By default, the autowiring will fail whenever
|
|
<emphasis>zero</emphasis> candidate beans are available; the default
|
|
behavior is to treat annotated methods, constructors, and fields as
|
|
indicating <emphasis>required</emphasis> dependencies. This behavior can
|
|
be changed as demonstrated below.</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
@Autowired(required=false)
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>Only <emphasis>one annotated constructor per-class</emphasis>
|
|
may be marked as <emphasis>required</emphasis>, but multiple
|
|
non-required constructors can be annotated. In that case, each will be
|
|
considered among the candidates and Spring will use the
|
|
<emphasis>greediest</emphasis> constructor whose dependencies can be
|
|
satisfied.</para>
|
|
|
|
<para>Prefer the use of <interfacename>@Autowired</interfacename>'s
|
|
<emphasis>required</emphasis> attribute over the
|
|
<interfacename>@Required</interfacename> annotation. The
|
|
<emphasis>required</emphasis> attribute indicates that the property is
|
|
not required for autowiring purposes, simply skipping it if it cannot
|
|
be autowired. <interfacename>@Required</interfacename>, on the other
|
|
hand, is stronger in that it enforces the property to have been set in
|
|
any of the container's supported ways; if no value has been injected,
|
|
a corresponding exception will be raised.</para>
|
|
</note>
|
|
|
|
<para><interfacename>@Autowired</interfacename> may also be used for
|
|
well-known "resolvable dependencies": the
|
|
<interfacename>BeanFactory</interfacename> interface, the
|
|
<interfacename>ApplicationContext</interfacename> interface, the
|
|
<interfacename>ResourceLoader</interfacename> interface, the
|
|
<interfacename>ApplicationEventPublisher</interfacename> interface and
|
|
the <interfacename>MessageSource</interfacename> interface. These
|
|
interfaces (and their extended interfaces such as
|
|
<interfacename>ConfigurableApplicationContext</interfacename> or
|
|
<interfacename>ResourcePatternResolver</interfacename>) will be
|
|
automatically resolved, with no special setup necessary.</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
private ApplicationContext context;
|
|
|
|
public MovieRecommender() {
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
</section>
|
|
|
|
<section id="beans-autowired-annotation-qualifiers">
|
|
<title>Fine-tuning annotation-based autowiring with qualifiers</title>
|
|
|
|
<para>Since autowiring by type may lead to multiple candidates, it is
|
|
often necessary to have more control over the selection process. One way
|
|
to accomplish this is with Spring's
|
|
<interfacename>@Qualifier</interfacename> annotation. This allows for
|
|
associating qualifier values with specific arguments, narrowing the set
|
|
of type matches so that a specific bean is chosen for each argument. In
|
|
the simplest case, this can be a plain descriptive value:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
<emphasis role="bold">@Qualifier("main")</emphasis>
|
|
private MovieCatalog movieCatalog;
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The <interfacename>@Qualifier</interfacename> annotation can also
|
|
be specified on individual constructor arguments or method
|
|
parameters:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
private MovieCatalog movieCatalog;
|
|
|
|
private CustomerPreferenceDao customerPreferenceDao;
|
|
|
|
@Autowired
|
|
public void prepare(<emphasis role="bold">@Qualifier("main")</emphasis> MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
|
|
this.movieCatalog = movieCatalog;
|
|
this.customerPreferenceDao = customerPreferenceDao;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The corresponding bean definitions would look like as follows. The
|
|
bean with qualifier value "main" would be wired with the constructor
|
|
argument that has been qualified with the same value.</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:context="http://www.springframework.org/schema/context"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
|
|
|
<context:annotation-config/>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<emphasis role="bold"><qualifier value="main"/></emphasis>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<emphasis role="bold"><qualifier value="action"/></emphasis>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean id="movieRecommender" class="example.MovieRecommender"/>
|
|
|
|
</beans>
|
|
</programlisting>
|
|
|
|
<para>For a fallback match, the bean name is considered as a default
|
|
qualifier value. This means that the bean may be defined with an id
|
|
"main" instead of the nested qualifier element, leading to the same
|
|
matching result. However, note that while this can be used to refer to
|
|
specific beans by name, <interfacename>@Autowired</interfacename> is
|
|
fundamentally about type-driven injection with optional semantic
|
|
qualifiers. This means that qualifier values, even when using the bean
|
|
name fallback, always have narrowing semantics within the set of type
|
|
matches; they do not semantically express a reference to a unique bean
|
|
id. Good qualifier values would be "main" or "EMEA" or "persistent",
|
|
expressing characteristics of a specific component - independent from
|
|
the bean id (which may be auto-generated in case of an anonymous bean
|
|
definition like the one above).</para>
|
|
|
|
<para>Qualifiers also apply to typed collections (as discussed above):
|
|
e.g. to <literal>Set<MovieCatalog></literal>. In such a case, all
|
|
matching beans according to the declared qualifiers are going to be
|
|
injected as a collection. This implies that qualifiers do not have to be
|
|
unique; they rather simply constitute filtering criteria. For example,
|
|
there could be multiple <classname>MovieCatalog</classname> beans
|
|
defined with the same qualifier value "action"; all of which would be
|
|
injected into a <literal>Set<MovieCatalog></literal> annotated
|
|
with <literal>@Qualifier("action")</literal>.</para>
|
|
|
|
<tip>
|
|
<para>If you intend to express annotation-driven injection by name, do
|
|
not primarily use <interfacename>@Autowired</interfacename> - even if
|
|
is technically capable of referring to a bean name through
|
|
<interfacename>@Qualifier</interfacename> values. Instead, prefer the
|
|
JSR-250 <interfacename>@Resource</interfacename> annotation which is
|
|
semantically defined to identify a specific target component by its
|
|
unique name, with the declared type being irrelevant for the matching
|
|
process.</para>
|
|
|
|
<para>As a specific consequence of this semantic difference, beans
|
|
which are themselves defined as a collection or map type cannot be
|
|
injected via <interfacename>@Autowired</interfacename> since type
|
|
matching is not properly applicable to them. Use
|
|
<interfacename>@Resource</interfacename> for such beans, referring to
|
|
the specific collection/map bean by unique name.</para>
|
|
|
|
<para><emphasis>Note:</emphasis> In contrast to
|
|
<interfacename>@Autowired</interfacename> which is applicable to
|
|
fields, constructors and multi-argument methods (allowing for
|
|
narrowing through qualifier annotations at the parameter level),
|
|
<interfacename>@Resource</interfacename> is only supported for fields
|
|
and bean property setter methods with a single argument. As a
|
|
consequence, stick with qualifiers if your injection target is a
|
|
constructor or a multi-argument method.</para>
|
|
</tip>
|
|
|
|
<para>You may create your own custom qualifier annotations as well.
|
|
Simply define an annotation and provide the
|
|
<interfacename>@Qualifier</interfacename> annotation within your
|
|
definition:</para>
|
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
<emphasis role="bold">@Qualifier</emphasis>
|
|
public @interface Genre {
|
|
|
|
String value();
|
|
}</programlisting>
|
|
|
|
<para>Then you can provide the custom qualifier on autowired fields and
|
|
parameters:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
<emphasis role="bold">@Genre("Action")</emphasis>
|
|
private MovieCatalog actionCatalog;
|
|
|
|
private MovieCatalog comedyCatalog;
|
|
|
|
@Autowired
|
|
public void setComedyCatalog(<emphasis role="bold">@Genre("Comedy")</emphasis> MovieCatalog comedyCatalog) {
|
|
this.comedyCatalog = comedyCatalog;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>The next step is to provide the information on the candidate bean
|
|
definitions. You can add <literal><qualifier/></literal> tags as
|
|
sub-elements of the <literal><bean/></literal> tag and then
|
|
specify the <literal>'type'</literal> and <literal>'value'</literal> to
|
|
match your custom qualifier annotations. The type will be matched
|
|
against the fully-qualified class name of the annotation, or as a
|
|
convenience when there is no risk of conflicting names, you may use the
|
|
'short' class name. Both are demonstrated in the following
|
|
example.</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:context="http://www.springframework.org/schema/context"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
|
|
|
<context:annotation-config/>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<emphasis role="bold"><qualifier type="Genre" value="Action"/></emphasis>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<emphasis role="bold"><qualifier type="example.Genre" value="Comedy"/></emphasis>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean id="movieRecommender" class="example.MovieRecommender"/>
|
|
|
|
</beans>
|
|
</programlisting>
|
|
|
|
<para>In the next section, entitled <xref
|
|
linkend="beans-classpath-scanning" />, you will see an annotation-based
|
|
alternative to providing the qualifier metadata in XML. Specifically,
|
|
see: <xref linkend="beans-scanning-qualifiers" />.</para>
|
|
|
|
<para>In some cases, it may be sufficient to use an annotation without a
|
|
value. This may be useful when the annotation serves a more generic
|
|
purpose and could be applied across several different types of
|
|
dependencies. For example, you may provide an
|
|
<emphasis>offline</emphasis> catalog that would be searched when no
|
|
Internet connection is available. First define the simple
|
|
annotation:</para>
|
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
@Qualifier
|
|
public @interface Offline {
|
|
|
|
}</programlisting>
|
|
|
|
<para>Then add the annotation to the field or property to be
|
|
autowired:</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
<emphasis role="bold">@Offline</emphasis>
|
|
private MovieCatalog offlineCatalog;
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>Now the bean definition only needs a qualifier
|
|
<literal>'type'</literal>:</para>
|
|
|
|
<programlisting language="xml"><bean class="example.SimpleMovieCatalog">
|
|
<emphasis role="bold"><qualifier type="Offline"/></emphasis>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean></programlisting>
|
|
|
|
<para>It is also possible to define custom qualifier annotations that
|
|
accept named attributes in addition to or instead of the simple
|
|
<literal>'value'</literal> attribute. If multiple attribute values are
|
|
then specified on a field or parameter to be autowired, a bean
|
|
definition must match <emphasis>all</emphasis> such attribute values to
|
|
be considered an autowire candidate. As an example, consider the
|
|
following annotation definition:</para>
|
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
@Qualifier
|
|
public @interface MovieQualifier {
|
|
|
|
String genre();
|
|
|
|
Format format();
|
|
}</programlisting>
|
|
|
|
<para>In this case <literal>Format</literal> is an enum:</para>
|
|
|
|
<programlisting language="java">public enum Format {
|
|
|
|
VHS, DVD, BLURAY
|
|
}</programlisting>
|
|
|
|
<para>The fields to be autowired are annotated with the custom qualifier
|
|
and include values for both attributes: <literal>'genre'</literal> and
|
|
<literal>'format'</literal>.</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Autowired
|
|
@MovieQualifier(format=Format.VHS, genre="Action")
|
|
private MovieCatalog actionVhsCatalog;
|
|
|
|
@Autowired
|
|
@MovieQualifier(format=Format.VHS, genre="Comedy")
|
|
private MovieCatalog comedyVhsCatalog;
|
|
|
|
@Autowired
|
|
@MovieQualifier(format=Format.DVD, genre="Action")
|
|
private MovieCatalog actionDvdCatalog;
|
|
|
|
@Autowired
|
|
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
|
|
private MovieCatalog comedyBluRayCatalog;
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>Finally, the bean definitions should contain matching qualifier
|
|
values. This example also demonstrates that bean
|
|
<emphasis>meta</emphasis> attributes may be used instead of the
|
|
<literal><qualifier/></literal> sub-elements. If available, the
|
|
<literal><qualifier/></literal> and its attributes would take
|
|
precedence, but the autowiring mechanism will fallback on the values
|
|
provided within the <literal><meta/></literal> tags if no such
|
|
qualifier is present (see the last 2 bean definitions below).</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:context="http://www.springframework.org/schema/context"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
|
|
|
<context:annotation-config/>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<qualifier type="MovieQualifier">
|
|
<attribute key="format" value="VHS"/>
|
|
<attribute key="genre" value="Action"/>
|
|
</qualifier>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<qualifier type="MovieQualifier">
|
|
<attribute key="format" value="VHS"/>
|
|
<attribute key="genre" value="Comedy"/>
|
|
</qualifier>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<meta key="format" value="DVD"/>
|
|
<meta key="genre" value="Action"/>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
<bean class="example.SimpleMovieCatalog">
|
|
<meta key="format" value="BLURAY"/>
|
|
<meta key="genre" value="Comedy"/>
|
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation>
|
|
</bean>
|
|
|
|
</beans></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-custom-autowire-configurer">
|
|
<title><classname>CustomAutowireConfigurer</classname></title>
|
|
|
|
<para>The <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"><classname>CustomAutowireConfigurer</classname></ulink>
|
|
is a <interfacename>BeanFactoryPostProcessor</interfacename> that
|
|
enables further customization of the autowiring process. Specifically,
|
|
it allows you to register your own custom qualifier annotation types
|
|
even if they are not themselves annotated with Spring's
|
|
<interfacename>@Qualifier</interfacename> annotation.</para>
|
|
|
|
<programlisting language="xml"><bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
|
|
<property name="customQualifierTypes">
|
|
<set>
|
|
<value>example.CustomQualifier</value>
|
|
</set>
|
|
</property>
|
|
</bean></programlisting>
|
|
|
|
<para>Note that the particular implementation of
|
|
<interfacename>AutowireCandidateResolver</interfacename> that will be
|
|
activated for the application context depends upon the Java version. If
|
|
running on less than Java 5, the qualifier annotations are not
|
|
supported, and therefore autowire candidates are solely determined by
|
|
the <literal>'autowire-candidate'</literal> value of each bean
|
|
definition as well as any
|
|
<literal>'default-autowire-candidates'</literal> pattern(s) available on
|
|
the <literal><beans/></literal> element. If running on Java 5 or
|
|
greater, the presence of <interfacename>@Qualifier</interfacename>
|
|
annotations or any custom annotations registered with the
|
|
<classname>CustomAutowireConfigurer</classname> will also play a
|
|
role.</para>
|
|
|
|
<para>Regardless of the Java version, the determination of a "primary"
|
|
candidate (when multiple beans qualify as autowire candidates) is the
|
|
same: if exactly one bean definition among the candidates has a
|
|
<literal>'primary'</literal> attribute set to <literal>'true'</literal>,
|
|
it will be selected.</para>
|
|
</section>
|
|
|
|
<section id="beans-resource-annotation">
|
|
<title><interfacename>@Resource</interfacename></title>
|
|
|
|
<para>Spring also supports injection using the JSR-250
|
|
<interfacename>@Resource</interfacename> annotation on fields or bean
|
|
property setter methods. This is a common pattern found in Java EE 5 and
|
|
Java 6 (e.g. in JSF 1.2 managed beans or JAX-WS 2.0 endpoints), which
|
|
Spring supports for Spring-managed objects as well.</para>
|
|
|
|
<para><interfacename>@Resource</interfacename> takes a 'name' attribute,
|
|
and by default Spring will interpret that value as the bean name to be
|
|
injected. In other words, it follows <emphasis>by-name</emphasis>
|
|
semantics as demonstrated in this example:</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
<emphasis role="bold">@Resource(name="myMovieFinder")</emphasis>
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>If no name is specified explicitly, then the default name will be
|
|
derived from the name of the field or setter method: In case of a field,
|
|
it will simply be equivalent to the field name; in case of a setter
|
|
method, it will be equivalent to the bean property name. So the
|
|
following example is going to have the bean with name "movieFinder"
|
|
injected into its setter method:</para>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
<emphasis role="bold">@Resource</emphasis>
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>The name provided with the annotation will be resolved as a bean
|
|
name by the <interfacename>BeanFactory</interfacename> of which the
|
|
<classname>CommonAnnotationBeanPostProcessor</classname> is aware.
|
|
Note that the names may be resolved via JNDI if Spring's <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"><classname>SimpleJndiBeanFactory</classname></ulink>
|
|
is configured explicitly. However, it is recommended to rely on the
|
|
default behavior and simply use Spring's JNDI lookup capabilities to
|
|
preserve the level of indirection.</para>
|
|
</note>
|
|
|
|
<para>Similar to <interfacename>@Autowired</interfacename>,
|
|
<interfacename>@Resource</interfacename> may fall back to standard bean
|
|
type matches (i.e. find a primary type match instead of a specific named
|
|
bean) as well as resolve well-known "resolvable dependencies": the
|
|
<interfacename>BeanFactory</interfacename> interface, the
|
|
<interfacename>ApplicationContext</interfacename> interface, the
|
|
<interfacename>ResourceLoader</interfacename> interface, the
|
|
<interfacename>ApplicationEventPublisher</interfacename> interface and
|
|
the <interfacename>MessageSource</interfacename> interface. Note that
|
|
this only applies to <interfacename>@Resource</interfacename> usage with
|
|
no explicit name specified!</para>
|
|
|
|
<para>So the following example will have its
|
|
<literal>customerPreferenceDao</literal> field looking for a bean with
|
|
name "customerPreferenceDao" first, then falling back to a primary type
|
|
match for the type <classname>CustomerPreferenceDao</classname>. The
|
|
"context" field will simply be injected based on the known resolvable
|
|
dependency type
|
|
<interfacename>ApplicationContext</interfacename>.</para>
|
|
|
|
<programlisting language="java">public class MovieRecommender {
|
|
|
|
@Resource
|
|
private CustomerPreferenceDao customerPreferenceDao;
|
|
|
|
@Resource
|
|
private ApplicationContext context;
|
|
|
|
public MovieRecommender() {
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
</section>
|
|
|
|
<section id="beans-postconstruct-and-predestroy-annotations">
|
|
<title><interfacename>@PostConstruct</interfacename> and
|
|
<interfacename>@PreDestroy</interfacename></title>
|
|
|
|
<para>The <classname>CommonAnnotationBeanPostProcessor</classname> not
|
|
only recognizes the <interfacename>@Resource</interfacename> annotation
|
|
but also the JSR-250 <emphasis>lifecycle</emphasis> annotations.
|
|
Introduced in Spring 2.5, the support for these annotations offers yet
|
|
another alternative to those described in the sections on <link
|
|
linkend="beans-factory-lifecycle-initializingbean">initialization
|
|
callbacks</link> and <link
|
|
linkend="beans-factory-lifecycle-disposablebean">destruction
|
|
callbacks</link>. Provided that the
|
|
<classname>CommonAnnotationBeanPostProcessor</classname> is registered
|
|
within the Spring <interfacename>ApplicationContext</interfacename>, a
|
|
method carrying one of these annotations will be invoked at the same
|
|
point in the lifecycle as the corresponding Spring lifecycle interface's
|
|
method or explicitly declared callback method. In the example below, the
|
|
cache will be pre-populated upon initialization and cleared upon
|
|
destruction.</para>
|
|
|
|
<programlisting language="java">public class CachingMovieLister {
|
|
|
|
@PostConstruct
|
|
public void populateMovieCache() {
|
|
<lineannotation>// populates the movie cache upon initialization...</lineannotation>
|
|
}
|
|
|
|
@PreDestroy
|
|
public void clearMovieCache() {
|
|
<lineannotation>// clears the movie cache upon destruction...</lineannotation>
|
|
}
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>For details regarding the effects of combining various lifecycle
|
|
mechanisms, see <xref
|
|
linkend="beans-factory-lifecycle-combined-effects" />.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-classpath-scanning">
|
|
<title>Classpath scanning, managed components and writing configurations
|
|
using Java</title>
|
|
|
|
<para>Thus far most of the examples within this chapter have used XML for
|
|
specifying the configuration metadata that produces each
|
|
<interfacename>BeanDefinition</interfacename> within the Spring container.
|
|
The previous section (<xref linkend="beans-annotation-config" />)
|
|
demonstrated the possibility of providing a considerable amount of the
|
|
configuration metadata using source-level annotations. Even in those
|
|
examples however, the "base" bean definitions were explicitly defined in
|
|
the XML file while the annotations were driving the dependency injection
|
|
only. The current section introduces an option for implicitly detecting
|
|
the <emphasis>candidate components</emphasis> by scanning the classpath
|
|
and matching against <emphasis>filters</emphasis>.</para>
|
|
|
|
<note>
|
|
<para>Starting with Spring 3.0 many of the features provided by the
|
|
<ulink url="http://www.springsource.org/javaconfig">Spring JavaConfig
|
|
project</ulink> have been added to the core Spring Framework. This
|
|
allows you to define beans using Java rather than using the traditional
|
|
XML files. Take a look at the
|
|
<interfacename>@Configuration</interfacename>, <interfacename>@Bean,
|
|
@Import</interfacename> and <interfacename>@DependsOn</interfacename>
|
|
annotations for how to use these new features.</para>
|
|
</note>
|
|
|
|
<section id="beans-stereotype-annotations">
|
|
<title><interfacename>@Component</interfacename> and further stereotype
|
|
annotations</title>
|
|
|
|
<para>Beginning with Spring 2.0, the
|
|
<interfacename>@Repository</interfacename> annotation was introduced as
|
|
a marker for any class that fulfills the role or
|
|
<emphasis>stereotype</emphasis> of a repository (a.k.a. Data Access
|
|
Object or DAO). Among the possibilities for leveraging such a marker is
|
|
the automatic translation of exceptions as described in <xref
|
|
linkend="orm-jpa-exceptions" />.</para>
|
|
|
|
<para>Spring 2.5 introduces further stereotype annotations:
|
|
<interfacename>@Component</interfacename>,
|
|
<interfacename>@Service</interfacename> and
|
|
<interfacename>@Controller</interfacename>.
|
|
<interfacename>@Component</interfacename> serves as a generic stereotype
|
|
for any Spring-managed component; whereas,
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, and
|
|
<interfacename>@Controller</interfacename> serve as specializations of
|
|
<interfacename>@Component</interfacename> for more specific use cases
|
|
(e.g., in the persistence, service, and presentation layers,
|
|
respectively). What this means is that you can annotate your component
|
|
classes with <interfacename>@Component</interfacename>, but by
|
|
annotating them with <interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, or
|
|
<interfacename>@Controller</interfacename> instead, your classes are
|
|
more properly suited for processing by tools or associating with
|
|
aspects. For example, these stereotype annotations make ideal targets
|
|
for pointcuts. Of course, it is also possible that
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, and
|
|
<interfacename>@Controller</interfacename> may carry additional
|
|
semantics in future releases of the Spring Framework. Thus, if you are
|
|
making a decision between using
|
|
<interfacename>@Component</interfacename> or
|
|
<interfacename>@Service</interfacename> for your service layer,
|
|
<interfacename>@Service</interfacename> is clearly the better choice.
|
|
Similarly, as stated above, <interfacename>@Repository</interfacename>
|
|
is already supported as a marker for automatic exception translation in
|
|
your persistence layer.</para>
|
|
</section>
|
|
|
|
<section id="beans-scanning-autodetection">
|
|
<title>Auto-detecting components</title>
|
|
|
|
<para>Spring provides the capability of automatically detecting
|
|
'stereotyped' classes and registering corresponding
|
|
<interfacename>BeanDefinition</interfacename>s with the
|
|
<interfacename>ApplicationContext</interfacename>. For example, the
|
|
following two classes are eligible for such autodetection:</para>
|
|
|
|
<programlisting language="java">@Service
|
|
public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
@Autowired
|
|
public SimpleMovieLister(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@Repository
|
|
public class JpaMovieFinder implements MovieFinder {
|
|
<lineannotation>// implementation elided for clarity</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>To autodetect these classes and register the corresponding beans
|
|
requires the inclusion of the following element in XML where
|
|
'basePackage' would be a common parent package for the two classes (or
|
|
alternatively a comma-separated list could be specified that included
|
|
the parent package of each class).</para>
|
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xmlns:context="http://www.springframework.org/schema/context"
|
|
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
|
http://www.springframework.org/schema/context
|
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
|
|
|
<context:component-scan base-package="org.example"/>
|
|
|
|
</beans></programlisting>
|
|
|
|
<note>
|
|
<para>Note that the scanning of classpath packages requires the
|
|
presence of corresponding directory entries in the classpath. When
|
|
building jars with Ant, make sure to <emphasis>not</emphasis> activate
|
|
the files-only switch of the jar task!</para>
|
|
</note>
|
|
|
|
<para>Furthermore, the
|
|
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and
|
|
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> are
|
|
both included implicitly when using the component-scan element. That
|
|
means that the two components are autodetected <emphasis>and</emphasis>
|
|
wired together - all without any bean configuration metadata provided in
|
|
XML.</para>
|
|
|
|
<note>
|
|
<para>The registration of those post-processors can be disabled by
|
|
including the <emphasis>annotation-config</emphasis> attribute with a
|
|
value of 'false'.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-scanning-filters">
|
|
<title>Using filters to customize scanning</title>
|
|
|
|
<para>By default, classes annotated with
|
|
<interfacename>@Component</interfacename>,
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, or
|
|
<interfacename>@Controller</interfacename> (or classes annotated with a
|
|
custom annotation that itself is annotated with
|
|
<interfacename>@Component</interfacename>) are the only detected
|
|
candidate components. However it is simple to modify and extend this
|
|
behavior by applying custom filters. These can be added as either
|
|
<emphasis>include-filter</emphasis> or
|
|
<emphasis>exclude-filter</emphasis> sub-elements of the
|
|
'<literal>component-scan</literal>' element. Each filter element
|
|
requires the '<literal>type</literal>' and
|
|
'<literal>expression</literal>' attributes. Five filtering options exist
|
|
as described below.</para>
|
|
|
|
<table id="beans-scanning-filters-tbl">
|
|
<title>Filter Types</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec colname="c1" colwidth="1*" />
|
|
|
|
<colspec colname="c2" colwidth="3*" />
|
|
|
|
<colspec colname="c" colwidth="4*" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Filter Type</entry>
|
|
|
|
<entry>Example Expression</entry>
|
|
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>annotation</entry>
|
|
|
|
<entry><literal>org.example.SomeAnnotation</literal></entry>
|
|
|
|
<entry>An annotation to be present at the type level in target
|
|
components.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>assignable</entry>
|
|
|
|
<entry><literal>org.example.SomeClass</literal></entry>
|
|
|
|
<entry>A class (or interface) that the target components are
|
|
assignable to (extend/implement).</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>aspectj</entry>
|
|
|
|
<entry><literal>org.example..*Service+</literal></entry>
|
|
|
|
<entry>An AspectJ type expression to be matched by the target
|
|
components.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>regex</entry>
|
|
|
|
<entry><literal>org\.example\.Default.*</literal></entry>
|
|
|
|
<entry>A regex expression to be matched by the target
|
|
components' class names.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>custom</entry>
|
|
|
|
<entry><literal>org.example.MyCustomTypeFilter</literal></entry>
|
|
|
|
<entry>A custom implementation of the
|
|
<interfacename>org.springframework.core.type.TypeFilter</interfacename>
|
|
interface.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>Find below an example of the XML configuration for ignoring all
|
|
<interfacename>@Repository</interfacename> annotations and using "stub"
|
|
repositories instead.</para>
|
|
|
|
<programlisting language="xml"><beans ...>
|
|
|
|
<context:component-scan base-package="org.example">
|
|
<context:include-filter type="regex" expression=".*Stub.*Repository"/>
|
|
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
|
|
</context:component-scan>
|
|
|
|
</beans></programlisting>
|
|
|
|
<note>
|
|
<para>It is also possible to disable the default filters by providing
|
|
<emphasis>use-default-filters="false"</emphasis> as an attribute of
|
|
the <component-scan/> element. This will in effect disable
|
|
automatic detection of classes annotated with
|
|
<interfacename>@Component</interfacename>,
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, or
|
|
<interfacename>@Controller</interfacename>.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-configuration-annotation">
|
|
<title>Using the <interfacename>@Configuration</interfacename>
|
|
annotation</title>
|
|
|
|
<para>The central artifact in Spring's new Java-configuration support is
|
|
the <interfacename>@Configuration</interfacename>-annotated class. These
|
|
classes consist principally of
|
|
<interfacename>@Bean</interfacename>-annotated methods that define
|
|
instantiation, configuration, and initialization logic for objects that
|
|
will be managed by the Spring IoC container.</para>
|
|
|
|
<para>Annotating a class with the
|
|
<interfacename>@Configuration</interfacename> indicates that the class
|
|
may be used by the Spring IoC container as a source of bean definitions.
|
|
The simplest possible <interfacename>@Configuration</interfacename>
|
|
class would read as follows: <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
} </programlisting></para>
|
|
|
|
<para>An application may make use of one
|
|
<interfacename>@Configuration</interfacename>-annotated class, or many.
|
|
<interfacename>@Configuration</interfacename> is meta-annotated as a
|
|
<interfacename>@Component</interfacename>, therefore
|
|
Configuration-classes are candidates for component-scanning and may also
|
|
take advantage of <interfacename>@Autowired</interfacename> annotations
|
|
at the field and method level but not at the constructor level.
|
|
Configuration-classes must also have a default constructor. Externalized
|
|
values may be wired into Configuration-classes using the
|
|
<interfacename>@Value</interfacename> annotation.</para>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-bean-annotation">
|
|
<title>Using the <interfacename>@Bean</interfacename> annotation</title>
|
|
|
|
<para><interfacename>@Bean</interfacename> is a method-level annotation
|
|
and a direct analog of the XML <code><bean/></code> element. The
|
|
annotation supports some of the attributes offered by
|
|
<code><bean/></code>, such as: <code><link
|
|
linkend="beans-factory-lifecycle-initializingbean">init-method</link></code>,
|
|
<code><link
|
|
linkend="beans-factory-lifecycle-disposablebean">destroy-method</link></code>,
|
|
<code><link linkend="beans-factory-autowire">autowiring</link></code>
|
|
and <code><link
|
|
linkend="beans-factory-scopes">name</link></code>.</para>
|
|
|
|
<para>You can use the @Bean annotation in a Configuraton-class or in a
|
|
Component-class.</para>
|
|
|
|
<section id="beans-javaconfig-declaring-a-bean">
|
|
<title>Declaring a bean</title>
|
|
|
|
<para>To declare a bean, simply annotate a method with the
|
|
<interfacename>@Bean</interfacename> annotation. Such a method will be
|
|
used to register a bean definition within a <code>BeanFactory</code>
|
|
of the type specified as the methods return value. By default, the
|
|
bean name will be the same as the method name (see <link
|
|
linkend="bean-naming"> bean naming</link> for details on how to
|
|
customize this behavior). The following is a simple example of a
|
|
<interfacename>@Bean</interfacename> method declaration:
|
|
<programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
@Bean
|
|
public TransferService transferService() {
|
|
return new TransferServiceImpl();
|
|
}
|
|
|
|
} </programlisting></para>
|
|
|
|
<para>For comparison sake, the configuration above is exactly
|
|
equivalent to the following Spring XML: <programlisting
|
|
language="xml"><beans>
|
|
<bean name="transferService" class="com.acme.TransferServiceImpl"/>
|
|
</beans> </programlisting></para>
|
|
|
|
<para>Both will result in a bean named <code>transferService</code>
|
|
being available in the <code>BeanFactory</code> or
|
|
<code>ApplicationContext</code>, bound to an object instance of type
|
|
<code>TransferServiceImpl</code>: <programlisting>
|
|
transferService -> com.acme.TransferServiceImpl
|
|
</programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-injecting-dependencies">
|
|
<title>Injecting dependencies</title>
|
|
|
|
<para>When <interfacename>@Bean</interfacename>s have dependencies on
|
|
one another, expressing that dependency is as simple as having one
|
|
bean method call another: <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
@Bean
|
|
public Foo foo() {
|
|
return new Foo(bar());
|
|
}
|
|
|
|
@Bean
|
|
public Bar bar() {
|
|
return new Bar();
|
|
}
|
|
|
|
} </programlisting></para>
|
|
|
|
<para>In the example above, the <code>foo</code> bean recevies a
|
|
reference to <code> bar</code> via constructor injection.</para>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-lifecycle-callbacks">
|
|
<title>Receiving lifecycle callbacks</title>
|
|
|
|
<para>Beans created in a Configuration-class supports the regular
|
|
lifecycle callbacks. Any classes defined with the @Bean annotation can
|
|
use the @PostConstruct and @PreDestroy annotations from JSR-250, see
|
|
the section on <link
|
|
linkend="beans-factory-lifecycle-combined-effects">JSR-250
|
|
annotations</link> for further details.</para>
|
|
|
|
<para>The regular Spring <link
|
|
linkend="beans-factory-nature">lifecycle</link> callbacks are fully
|
|
supported as well. If a bean implements <code>InitializingBean</code>,
|
|
<code>DisposableBean</code>, or <code>Lifecycle</code>, their
|
|
respective methods will be called by the container.</para>
|
|
|
|
<para>The standard set of <code>*Aware</code> interfaces such as
|
|
<code><link
|
|
linkend="beans-factory-aware-beanfactoryaware">BeanFactoryAware</link></code>,
|
|
<code><link
|
|
linkend="beans-factory-aware-beannameaware">BeanNameAware</link></code>,
|
|
<code><link
|
|
linkend="context-functionality-messagesource">MessageSourceAware</link></code>,
|
|
<code><link
|
|
linkend="context-functionality-events">ApplicationContextAware</link></code>,
|
|
etc. are also fully supported.</para>
|
|
|
|
<para>The <interfacename>@Bean</interfacename> annotation supports
|
|
specifying arbitrary initialization and destruction callback methods,
|
|
much like Spring XML's <code>init-method</code> and
|
|
<code>destroy-method</code> attributes to the <code>bean</code>
|
|
element: <programlisting language="java">public class Foo {
|
|
public void init() {
|
|
// initialization logic
|
|
}
|
|
}
|
|
|
|
public class Bar {
|
|
public void cleanup() {
|
|
// destruction logic
|
|
}
|
|
}
|
|
|
|
@Configuration
|
|
public class AppConfig {
|
|
@Bean(initMethodName = "init")
|
|
public Foo foo() {
|
|
return new Foo();
|
|
}
|
|
@Bean(destroyMethodName="cleanup")
|
|
public Bar bar() {
|
|
return new Bar();
|
|
}
|
|
}
|
|
</programlisting></para>
|
|
|
|
<para>Of course, in the case of <code>Foo</code> above, it would be
|
|
equally as valid to call the <code>init()</code> method directly
|
|
during construction: <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
@Bean
|
|
public Foo foo() {
|
|
Foo foo = new Foo();
|
|
foo.init();
|
|
return foo;
|
|
}
|
|
|
|
// ...
|
|
} </programlisting></para>
|
|
|
|
<tip>
|
|
<para>Remember that because you are working directly in Java, you
|
|
can do anything you like with your objects, and do not always need
|
|
to rely on the container!</para>
|
|
</tip>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-specifying-bean-scope">
|
|
<title>Specifying bean scope</title>
|
|
|
|
<section id="beans-javaconfig-available-scopes">
|
|
<title>Using the <interfacename>@Scope</interfacename>
|
|
annotation</title>
|
|
|
|
<para>You can specify that your beans defined with the
|
|
<interfacename>@Bean</interfacename> annotation should have a
|
|
specific scope. You can use any of the standard scopes specified in
|
|
the <link linkend="beans-factory-scopes">Bean Scopes</link>
|
|
section.</para>
|
|
|
|
<para>The <code>StandardScopes</code> class provides string
|
|
constants for each of these four scopes. SINGLETON is the default,
|
|
and can be overridden by using the
|
|
<interfacename>@Scope</interfacename> annotation: <programlisting
|
|
language="java">@Configuration
|
|
public class MyConfiguration {
|
|
@Bean
|
|
@Scope(StandardScopes.PROTOTYPE)
|
|
public Encryptor encryptor() {
|
|
// ...
|
|
}
|
|
} </programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-scoped-proxy">
|
|
<title><code>@Scope and scoped-proxy</code></title>
|
|
|
|
<para>Spring offers a convenient way of working with scoped
|
|
dependencies through <link
|
|
linkend="beans-factory-scopes-other-injection">scoped
|
|
proxies</link>. The easiest way to create such a proxy when using
|
|
the XML configuration is the <code><aop:scoped-proxy/></code>
|
|
element. Configuring your beans in Java with a @Scope annotation
|
|
offers equivalent support with the proxyMode attribute. The default
|
|
is no proxy (<varname>ScopedProxyMode.NO</varname>) but you can
|
|
specify <classname>ScopedProxyMode.TARGET_CLASS</classname> or
|
|
<classname>ScopedProxyMode.INTERFACES</classname>.</para>
|
|
|
|
<para>If we were to port the the XML reference documentation scoped
|
|
proxy example (see link above) to our
|
|
<interfacename>@Bean</interfacename> using Java, it would look like
|
|
the following: <programlisting language="java">// a HTTP Session-scoped bean exposed as a proxy
|
|
@Bean
|
|
@Scope(value = StandardScopes.SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
|
|
public UserPreferences userPreferences() {
|
|
return new UserPreferences();
|
|
}
|
|
|
|
@Bean
|
|
public Service userService() {
|
|
UserService service = new SimpleUserService();
|
|
// a reference to the proxied 'userPreferences' bean
|
|
service.seUserPreferences(userPreferences());
|
|
return service;
|
|
} </programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-method-injection">
|
|
<title>Lookup method injection</title>
|
|
|
|
<para>As noted earlier, <link
|
|
linkend="beans-factory-method-injection">lookup method
|
|
injection</link> is an advanced feature that should be comparatively
|
|
rarely used. It is useful in cases where a singleton-scoped bean has
|
|
a dependency on a prototype-scoped bean. Using Java for this type of
|
|
configuration provides a natural means for implementing this
|
|
pattern. <programlisting language="java">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();
|
|
} </programlisting></para>
|
|
|
|
<para>Using Java-configuration support we can easily create a
|
|
subclass of <code>CommandManager</code> where the abstract
|
|
<code>createCommand()</code> is overridden in such a way that it
|
|
'looks up' a brand new (prototype) command object: <programlisting
|
|
language="java">@Bean
|
|
@Scope(StandardScopes.PROTOTYPE)
|
|
public AsyncCommand asyncCommand() {
|
|
AsyncCommand command = new AsyncCommand();
|
|
// inject dependencies here as required
|
|
return command;
|
|
}
|
|
|
|
@Bean
|
|
public CommandManager commandManager() {
|
|
// return new anonymous implementation of CommandManager with command() overridden
|
|
// to return a new prototype Command object
|
|
return new CommandManager() {
|
|
protected Command command() {
|
|
return asyncCommand();
|
|
}
|
|
}
|
|
} </programlisting></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-javaconfig-customizing-bean-naming">
|
|
<title>Customizing bean naming</title>
|
|
|
|
<para>By default, Configuration-classes uses a
|
|
<interfacename>@Bean</interfacename> method's name as the name of the
|
|
resulting bean. This functionality can be overridden, however, using
|
|
the <code>name</code> attribute. <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
@Bean(name = "bar")
|
|
public Foo foo() {
|
|
return new Foo();
|
|
}
|
|
|
|
} </programlisting></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factorybeans-annotations">
|
|
<title>Defining bean metadata within components</title>
|
|
|
|
<para>Spring components can also contribute bean definition metadata to
|
|
the container. This is done with the same <literal>@Bean</literal>
|
|
annotation used to define bean metadata within
|
|
<literal>@Configuration</literal> annotated classes. Here is a simple
|
|
example</para>
|
|
|
|
<programlisting>@Component
|
|
public class FactoryMethodComponent {
|
|
|
|
@Bean @Qualifier("public")
|
|
public TestBean publicInstance() {
|
|
return new TestBean("publicInstance");
|
|
}
|
|
|
|
public void DoWork()
|
|
{
|
|
// Component method implementation omitted
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>This class is a Spring component and has application specific code
|
|
contained in its <methodname>DoWork</methodname> method. However, it
|
|
also contributes a bean definition that has a factory method referring
|
|
to the method <methodname>publicInstance</methodname>. The
|
|
<literal>@Bean</literal> annotation identifies the factory method and
|
|
also other bean definition properties, such as a qualifier value via the
|
|
<classname>@Qualifier</classname> annotation. Other method level
|
|
annotations that can be specified are <literal>@Scope</literal>,
|
|
<literal>@Lazy</literal>, and custom qualifier annotations. Autowired
|
|
fields and methods are supported as before with the additional support
|
|
for autowiring of @Bean methods, as shown in the example below</para>
|
|
|
|
<programlisting language="java">@Component
|
|
public class FactoryMethodComponent {
|
|
|
|
private static int i;
|
|
|
|
@Bean @Qualifier("public")
|
|
public TestBean publicInstance() {
|
|
return new TestBean("publicInstance");
|
|
}
|
|
|
|
// use of a custom qualifier and autowiring of method parameters
|
|
|
|
@Bean @BeanAge(1)
|
|
protected TestBean protectedInstance(@Qualifier("public") TestBean spouse, @Value("#{privateInstance.age}") String country) {
|
|
TestBean tb = new TestBean("protectedInstance", 1);
|
|
tb.setSpouse(tb);
|
|
tb.setCountry(country);
|
|
return tb;
|
|
}
|
|
|
|
@Bean @Scope(StandardScopes.PROTOTYPE)
|
|
private TestBean privateInstance() {
|
|
return new TestBean("privateInstance", i++);
|
|
}
|
|
|
|
@Bean @Scope(value = StandardScopes.SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
|
|
public TestBean requestScopedInstance() {
|
|
return new TestBean("requestScopedInstance", 3);
|
|
}
|
|
}
|
|
</programlisting>
|
|
|
|
<para>Note the use of autowiring of the <classname>String</classname>
|
|
method parameter <literal>country</literal> to the value of the
|
|
<literal>Age</literal> property on another bean named
|
|
<literal>privateInstance</literal>. A Spring Expression Language element
|
|
is used to define the value of the property via the notation <literal>#{
|
|
<expression> }</literal>. For <literal>@Value</literal>
|
|
annotations, an expression resolver is preconfigured to look for bean
|
|
names when resolving expression text.</para>
|
|
|
|
<para>The <literal>@Bean</literal> methods in a Spring component are
|
|
processed differently than their counterparts inside a Spring
|
|
<literal>@Configuration</literal> class. The difference is that
|
|
<literal>@Component</literal> classes are not enhanced with CGLIB to
|
|
intercept the invocation of methods and fields. CGLIB proxying is the
|
|
means by which invoking methods or fields within
|
|
<literal>@Configuration</literal> classes' <literal>@Bean</literal>
|
|
methods create bean metadata references to collaborating objects and do
|
|
<emphasis>not</emphasis> invoke the method with normal Java semantics.
|
|
In contrast, calling a method or field within a
|
|
<literal>@Component</literal> classes' <literal>@Bean</literal> method
|
|
<emphasis>has</emphasis> standard Java semantics.</para>
|
|
</section>
|
|
|
|
<section id="beans-scanning-name-generator">
|
|
<title>Naming autodetected components</title>
|
|
|
|
<para>When a component is autodetected as part of the scanning process,
|
|
its bean name will be generated by the
|
|
<interfacename>BeanNameGenerator</interfacename> strategy known to that
|
|
scanner. By default, any Spring 'stereotype' annotation
|
|
(<interfacename>@Component</interfacename>,
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, and
|
|
<interfacename>@Controller</interfacename>) that contains a
|
|
<literal>name</literal> value will thereby provide that name to the
|
|
corresponding bean definition. If such an annotation contains no
|
|
<literal>name</literal> value or for any other detected component (such
|
|
as those discovered due to custom filters), the default bean name
|
|
generator will return the uncapitalized non-qualified class name. For
|
|
example, if the following two components were detected, the names would
|
|
be 'myMovieLister' and 'movieFinderImpl':</para>
|
|
|
|
<programlisting language="java">@Service("myMovieLister")
|
|
public class SimpleMovieLister {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@Repository
|
|
public class MovieFinderImpl implements MovieFinder {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>If you don't want to rely on the default bean-naming strategy,
|
|
you may provide a custom bean-naming strategy. First, implement the
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/support/BeanNameGenerator.html"><interfacename>BeanNameGenerator</interfacename></ulink>
|
|
interface, and be sure to include a default no-arg constructor. Then,
|
|
provide the fully-qualified class name when configuring the
|
|
scanner:</para>
|
|
</note>
|
|
|
|
<programlisting language="xml"><beans ...>
|
|
|
|
<context:component-scan base-package="org.example"
|
|
name-generator="org.example.MyNameGenerator" />
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>As a general rule, consider specifying the name with the
|
|
annotation whenever other components may be making explicit references
|
|
to it. On the other hand, the auto-generated names are adequate whenever
|
|
the container is responsible for wiring.</para>
|
|
</section>
|
|
|
|
<section id="beans-scanning-scope-resolver">
|
|
<title>Providing a scope for autodetected components</title>
|
|
|
|
<para>As with Spring-managed components in general, the default and by
|
|
far most common scope is 'singleton'. However, there are times when
|
|
other scopes are needed. Therefore Spring 2.5 introduces a new
|
|
<interfacename>@Scope</interfacename> annotation as well. Simply provide
|
|
the name of the scope within the annotation, such as:</para>
|
|
|
|
<programlisting language="java">@Scope(StandardScopes.PROTOTYPE)
|
|
@Repository
|
|
public class MovieFinderImpl implements MovieFinder {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>If you would like to provide a custom strategy for scope
|
|
resolution rather than relying on the annotation-based approach,
|
|
implement the <ulink
|
|
url="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/context/annotation/ScopeMetadataResolver.html"><interfacename>ScopeMetadataResolver</interfacename></ulink>
|
|
interface, and be sure to include a default no-arg constructor. Then,
|
|
provide the fully-qualified class name when configuring the
|
|
scanner:</para>
|
|
</note>
|
|
|
|
<programlisting language="xml"><beans ...>
|
|
|
|
<context:component-scan base-package="org.example"
|
|
scope-resolver="org.example.MyScopeResolver" />
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>When using certain non-singleton scopes, it may be necessary to
|
|
generate proxies for the scoped objects. The reasoning is described in
|
|
detail within the section entitled <xref
|
|
linkend="beans-factory-scopes-other-injection" />. For this purpose, a
|
|
<emphasis>scoped-proxy</emphasis> attribute is available on the
|
|
'component-scan' element. The three possible values are: 'no',
|
|
'interfaces', and 'targetClass'. For example, the following
|
|
configuration will result in standard JDK dynamic proxies:</para>
|
|
|
|
<programlisting language="xml"><beans ...>
|
|
|
|
<context:component-scan base-package="org.example"
|
|
scoped-proxy="interfaces" />
|
|
|
|
</beans></programlisting>
|
|
</section>
|
|
|
|
<section id="beans-scanning-qualifiers">
|
|
<title>Providing qualifier metadata with annotations</title>
|
|
|
|
<para>The <interfacename>@Qualifier</interfacename> annotation was
|
|
introduced in the section above entitled <xref
|
|
linkend="beans-autowired-annotation-qualifiers" />. The examples in that
|
|
section demonstrated use of the
|
|
<interfacename>@Qualifier</interfacename> annotation as well as custom
|
|
qualifier annotations to provide fine-grained control when resolving
|
|
autowire candidates. Since those examples were based on XML bean
|
|
definitions, the qualifier metadata was provided on the candidate bean
|
|
definitions using the '<literal>qualifier</literal>' or
|
|
'<literal>meta</literal>' sub-elements of the '<literal>bean</literal>'
|
|
element in the XML. When relying upon classpath scanning for
|
|
autodetection of components, then the qualifier metadata may be provided
|
|
with type-level annotations on the candidate class. The following three
|
|
examples demonstrate this technique.</para>
|
|
|
|
<programlisting language="java">@Component
|
|
<emphasis role="bold">@Qualifier("Action")</emphasis>
|
|
public class ActionMovieCatalog implements MovieCatalog {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@Component
|
|
<emphasis role="bold">@Genre("Action")</emphasis>
|
|
public class ActionMovieCatalog implements MovieCatalog {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<programlisting language="java">@Component
|
|
<emphasis role="bold">@Offline</emphasis>
|
|
public class CachingMovieCatalog implements MovieCatalog {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>As with most of the annotation-based alternatives, keep in mind
|
|
that the annotation metadata is bound to the class definition itself,
|
|
while the use of XML allows for multiple beans <emphasis>of the same
|
|
type</emphasis> to provide variations in their qualifier metadata
|
|
since that metadata is provided per-instance rather than
|
|
per-class.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="context-load-time-weaver">
|
|
<title>Registering a <interfacename>LoadTimeWeaver</interfacename></title>
|
|
|
|
<para>The <literal>context</literal> namespace introduced in Spring 2.5
|
|
provides a <literal>load-time-weaver</literal> element.</para>
|
|
|
|
<programlisting language="xml"><beans ...>
|
|
|
|
<context:load-time-weaver/>
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>Adding this element to an XML-based Spring configuration file
|
|
activates a Spring <interfacename>LoadTimeWeaver</interfacename> for the
|
|
<interfacename>ApplicationContext</interfacename>. Any bean within that
|
|
<interfacename>ApplicationContext</interfacename> may implement
|
|
<interfacename>LoadTimeWeaverAware</interfacename> thereby receiving a
|
|
reference to the load-time weaver instance. This is particularly useful in
|
|
combination with <link linkend="orm-jpa">Spring's JPA support</link> where
|
|
load-time weaving may be necessary for JPA class transformation. Consult
|
|
the <classname>LocalContainerEntityManagerFactoryBean</classname> Javadoc
|
|
for more detail. For more on AspectJ load-time weaving, see <xref
|
|
linkend="aop-aj-ltw" />.</para>
|
|
</section>
|
|
</chapter>
|