7320 lines
350 KiB
XML
7320 lines
350 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="beans">
|
|
<title>The IoC container</title>
|
|
|
|
<section id="beans-introduction">
|
|
<title>Introduction to the Spring IoC container and beans</title>
|
|
|
|
<para>This chapter covers the Spring Framework implementation of the
|
|
Inversion of Control (IoC) <footnote>
|
|
<para>See <xref linkend="background-ioc" /></para>
|
|
</footnote>principle. IoC is also known as <emphasis>dependency
|
|
injection</emphasis> (DI). It is a process whereby objects define their
|
|
dependencies, that is, the other objects they work with, only through
|
|
constructor arguments, arguments to a factory method, or properties that
|
|
are set on the object instance after it is constructed or returned from a
|
|
factory method. The container then <emphasis>injects</emphasis> those
|
|
dependencies when it creates the bean. This process is fundamentally the
|
|
inverse, hence the name <emphasis>Inversion of Control</emphasis> (IoC),
|
|
of the bean itself controlling the instantiation or location of its
|
|
dependencies by using direct construction of classes, or a mechanism such
|
|
as the <emphasis>Service Locator</emphasis> pattern.</para>
|
|
|
|
<!--I copied and pasted preceding from "Injecting Dependencies" to give background on IoC, since that's what chapter is about.
|
|
The footnote should x-ref to first section in that chapter but I can't find the file. The current xref doesn't work.-->
|
|
|
|
<para>The <literal>org.springframework.beans</literal> and
|
|
<literal>org.springframework.context</literal> packages are the basis for
|
|
Spring Framework's IoC container. The <interfacename><ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</ulink></interfacename>
|
|
interface provides an advanced configuration mechanism capable of managing
|
|
any type of object. <literal><ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</ulink></literal>
|
|
is a sub-interface of <interfacename>BeanFactory.</interfacename> It adds
|
|
easier integration with Spring's AOP features; message resource handling
|
|
(for use in internationalization), event publication; 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, and the
|
|
<interfacename>ApplicationContext</interfacename> adds more
|
|
enterprise-specific functionality. The
|
|
<interfacename>ApplicationContext</interfacename> is a complete superset
|
|
of the <interfacename>BeanFactory</interfacename>, and is used exclusively
|
|
in this chapter in descriptions of Spring's IoC container. <!--API spec says ApplicationContext is a subinterface of BeanFactory, so is it right to call it a superset?-->For
|
|
more information on using the <classname>BeanFactory</classname> instead
|
|
of the <classname>ApplicationContext,</classname> refer to <xref
|
|
linkend="beans-beanfactory" />.</para>
|
|
|
|
<para>In Spring, the objects that form the backbone of your application
|
|
and that are managed by the Spring IoC <firstterm>container</firstterm>
|
|
are called <firstterm>beans</firstterm>. A bean is an object that is
|
|
instantiated, assembled, and otherwise managed by a Spring IoC container.
|
|
Otherwise, a bean is simply one of many objects in your application.
|
|
Beans, and the <firstterm>dependencies</firstterm> among them, are
|
|
reflected in the <firstterm>configuration metadata</firstterm> used by a
|
|
container.</para>
|
|
</section>
|
|
|
|
<section id="beans-basics">
|
|
<title>Container overview</title>
|
|
|
|
<para>The interface
|
|
<classname>org.springframework.context.ApplicationContext</classname>
|
|
represents the Spring IoC container and is responsible for instantiating,
|
|
configuring, and assembling the aforementioned beans. The container gets
|
|
its instructions on what objects to instantiate, configure, and assemble
|
|
by reading configuration metadata. The configuration metadata is
|
|
represented in XML, Java annotations, or Java code. It allows you to
|
|
express the objects that compose your application and the rich
|
|
interdependencies between such objects.</para>
|
|
|
|
<para>Several implementations of the
|
|
<classname>ApplicationContext</classname> interface are supplied
|
|
out-of-the-box with Spring. In standalone applications it is common to
|
|
create an instance of <ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html"><classname>ClassPathXmlApplicationContext</classname></ulink>
|
|
or <ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html"><classname>FileSystemXmlApplicationContext</classname></ulink>.
|
|
<!-- MLP: Beverly to review --> While XML has been the traditional format
|
|
for defining configuration metadata you can instruct the container to use
|
|
Java annotations or code as the metadata format by providng a small amount
|
|
of XML configuration to declaratively enable support for these additional
|
|
metadata formats.</para>
|
|
|
|
<para>In most 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" />). If you are using the <ulink
|
|
url="http://www.springsource.com/produts/sts">SpringSource Tool
|
|
Suite</ulink> Eclipse-powered development environment or <ulink
|
|
url="http://www.springsource.org/roo">Spring Roo</ulink> this boilerplate
|
|
configuration can be easily created with few mouse clicks or
|
|
keystrokes.</para>
|
|
|
|
<para>The following diagram is a high-level view of how Spring works. Your
|
|
application classes are combined with configuration metadata so that after
|
|
the <classname>ApplicationContext</classname> is created and initialized,
|
|
you have a fully configured and executable system or application.</para>
|
|
|
|
<para><mediaobject>
|
|
<imageobject>
|
|
<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 the preceding diagram shows, the Spring IoC container consumes
|
|
a form of <emphasis>configuration metadata</emphasis>; this
|
|
configuration metadata represents how you as an application developer
|
|
tell the Spring container to instantiate, configure, and assemble the
|
|
objects in your application.</para>
|
|
|
|
<para>Configuration metadata is traditionally supplied in a simple and
|
|
intuitive XML format, which is what most of this chapter uses to convey
|
|
key concepts and features of the Spring IoC container.</para>
|
|
|
|
<note>
|
|
<para>XML-based metadata is <emphasis>not</emphasis> the only allowed
|
|
form of configuration metadata. The Spring IoC container itself is
|
|
<emphasis>totally</emphasis> decoupled from the format in which this
|
|
configuration metadata is actually written.</para>
|
|
</note>
|
|
|
|
<para>For information about using other forms of metadata with the
|
|
Spring container, see:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><link linkend="beans-annotation-config">Annotation-based
|
|
configuration</link>: Spring 2.5 introduced support for
|
|
annotation-based configuration metadata.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><link linkend="beans-java">Java-based
|
|
configuration</link>: Starting with Spring 3.0, many features
|
|
provided by the <ulink
|
|
url="http://www.springsource.org/javaconfig">Spring JavaConfig
|
|
project</ulink> became part of the core Spring Framework. Thus you
|
|
can define beans external to your application classes by using Java
|
|
rather than XML files. To use these new features, see the
|
|
<interfacename>@Configuration</interfacename>, <interfacename>@Bean,
|
|
@Import</interfacename> and
|
|
<interfacename>@DependsOn</interfacename> annotations.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Spring configuration consists of at least one and typically more
|
|
than one bean definition that the container must manage. XML-based
|
|
configuration metadata shows these beans 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 define service layer objects, 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 and
|
|
load domain objects. However, you can use Spring's integration with
|
|
AspectJ to configure objects that have been created outside the control
|
|
of an IoC container. See <link linkend="aop-atconfigurable">Using
|
|
AspectJ to dependency-inject domain objects with Spring</link>.</para>
|
|
|
|
<para>The following example shows 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>
|
|
|
|
<para>The <literal>id</literal> attribute is a string that you use to
|
|
identify the individual bean definition. The <literal>class</literal>
|
|
attribute defines the type of the bean and uses the fully qualified
|
|
classname. The value of the id attribute refers to collaborating
|
|
objects. The XML for referring to collaborating objects is not shown in
|
|
this example; see <link linkend="beans-dependencies">Dependencies</link>
|
|
for more information.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-instantiation">
|
|
<title>Instantiating a container</title>
|
|
|
|
<para>Instantiating a Spring IoC container is straightforward. 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>, and so on.</para>
|
|
|
|
<programlisting language="java">ApplicationContext context =
|
|
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});</programlisting>
|
|
|
|
<note>
|
|
<para>After you learn about Spring's IoC container, you may want to
|
|
know more about Spring's <interfacename>Resource</interfacename>
|
|
abstraction, as described in <xref linkend="resources" />, which
|
|
provides a convenient mechanism for reading an InputSream from
|
|
locations defined in a URI syntax. In particular,
|
|
<classname>Resource</classname> paths are used to construct
|
|
applications contexts as described in <xref
|
|
linkend="resources-app-ctx" />.</para>
|
|
</note>
|
|
|
|
<para>The following example shows the service layer objects
|
|
<literal>(services.xml)</literal> configuration file:</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">
|
|
|
|
<!-- services -->
|
|
|
|
<bean id="petStore"
|
|
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
|
|
<property name="accountDao" ref="accountDao"/>
|
|
<property name="itemDao" ref="itemDao"/>
|
|
<!-- additional collaborators and configuration for this bean go here -->
|
|
</bean>
|
|
|
|
<!-- more bean definitions for services go here -->
|
|
|
|
</beans>
|
|
</programlisting>
|
|
|
|
<para>The following example shows the data access objects
|
|
<literal>daos.xml</literal>) file:</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="accountDao"
|
|
class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
|
|
<!-- additional collaborators and configuration for this bean go here -->
|
|
</bean>
|
|
|
|
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao">
|
|
<!-- additional collaborators and configuration for this bean go here -->
|
|
</bean>
|
|
|
|
<!-- more bean definitions for data access objects go here -->
|
|
|
|
</beans></programlisting>
|
|
|
|
<para>In the preceding example, the service layer consists of the class
|
|
<classname>PetStoreServiceImpl</classname>, and two data access objects
|
|
of the type <classname>SqlMapAccountDao</classname> and SqlMapItemDao
|
|
are based on the <ulink url="http://ibatis.apache.org/">iBatis</ulink>
|
|
Object/Relational mapping framework. The <literal>property
|
|
name</literal> element refers to the name of the JavaBean property, and
|
|
the <literal>ref</literal> element refers to the name of another bean
|
|
definition. This linkage between id and ref elements expresses the
|
|
dependency between collaborating objects. For details of configuring an
|
|
object's dependencies, see <link
|
|
linkend="beans-dependencies">Dependencies</link>.</para>
|
|
|
|
<section id="beans-factory-xml-import">
|
|
<title>Composing XML-based configuration metadata</title>
|
|
|
|
<para>It can be useful to have bean definitions span multiple XML
|
|
files. Often each individual XML configuration file represents a
|
|
logical layer or module in your architecture.</para>
|
|
|
|
<para>You can use the application context constructor to load bean
|
|
definitions from all these XML fragments. This constructor takes
|
|
multiple <interfacename>Resource</interfacename> locations, as was
|
|
shown in the previous section. Alternatively, use one or more
|
|
occurrences of the <literal><import/></literal> element to load
|
|
bean definitions from another file or files. For example:</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 the preceding example, external bean definitions are loaded
|
|
from three files, <literal>services.xml</literal>,
|
|
<literal>messageSource.xml</literal>, and
|
|
<literal>themeSource.xml</literal>. All location paths are relative to
|
|
the definition file doing the importing, so
|
|
<literal>services.xml</literal> 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 ignored, but given
|
|
that these paths are relative, it is better form not to use the slash
|
|
at all. The contents of the files being imported, including the top
|
|
level <literal><beans/></literal> element, must be valid XML
|
|
bean definitions according to the Spring Schema or DTD.</para>
|
|
|
|
<note>
|
|
<para>It is possible, but not recommended, to reference files in
|
|
parent directories using a relative "../" path. Doing so creates a
|
|
dependency on a file that is outside the current application. In
|
|
particular, this reference is not recommended for "classpath:" URLs
|
|
(for example, "classpath:../services.xml"), where the runtime
|
|
resolution process chooses the "nearest" classpath root and then
|
|
looks into its parent directory. Classpath configuration changes may
|
|
lead to the choice of a different, incorrect directory.</para>
|
|
|
|
<para>You can always use fully qualified resource locations instead
|
|
of relative paths: for example, "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. It is generally preferable to keep an indirection for
|
|
such absolute locations, for example, through "${...}" placeholders
|
|
that are resolved against JVM system properties at runtime.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-client">
|
|
<title>Using the container</title>
|
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> is the
|
|
interface for an advanced factory capable of maintaining a registry of
|
|
different beans and their dependencies. Using the method <methodname>T
|
|
getBean(Stringname, Class<T> requiredType)</methodname> you can
|
|
retrieve instances of your beans.</para>
|
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> enables you
|
|
to read bean definitions and access them as follows:</para>
|
|
|
|
<programlisting language="java">// create and configure beans
|
|
ApplicationContext context =
|
|
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
|
|
|
|
// retrieve configured instance
|
|
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
|
|
|
|
// use configured instance
|
|
List userList service.getUsernameList();
|
|
</programlisting>
|
|
|
|
<para>You use <methodname>getBean</methodname> to retrieve instances of
|
|
your beans. The <interfacename>ApplicationContext</interfacename>
|
|
interface has a few other methods for retrieving beans, but ideally your
|
|
application code should never use them. Indeed, your application code
|
|
should have no calls to the <methodname>getBean</methodname> method at
|
|
all, and thus no dependency on Spring APIs at all. For example, Spring's
|
|
integration with web frameworks provides for dependency injection for
|
|
various web framework classes such as controllers and JSF-managed
|
|
beans.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-definition">
|
|
<title>Bean overview</title>
|
|
|
|
<para>A Spring IoC container manages one or more
|
|
<emphasis>beans</emphasis>. These beans are created with the configuration
|
|
metadata that you supply to the container, for example, 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
|
|
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 that 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,
|
|
for example, 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>This metadata translates to a set of properties that make up each
|
|
bean definition.</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>Property</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>In addition to bean definitions that contain information on how to
|
|
create a specific bean, the
|
|
<interfacename>ApplicationContext</interfacename> implementations also
|
|
permit the registration of existing objects that are created outside the
|
|
container, by users. This is done by accessing the ApplicationContext's
|
|
BeanFactory via the method <methodname>getBeanFactory</methodname> which
|
|
returns the BeanFactory implementation
|
|
<classname>DefaultListableBeanFactory</classname>.
|
|
<classname>DefaultListableBeanFactory</classname> supports this
|
|
registration through the methods
|
|
<methodname>registerSingleton(..)</methodname> and
|
|
<methodname>registerBeanDefinition(..)</methodname>. However, typical
|
|
applications work solely with beans defined through metadata bean
|
|
definitions.</para>
|
|
|
|
<section id="beans-beanname">
|
|
<title>Naming beans</title>
|
|
|
|
<para>Every bean has one or more identifiers. These identifiers must be
|
|
unique within the container that hosts the bean. A bean usually has only
|
|
one identifier, but if it requires more than one, the extra ones can be
|
|
considered aliases.</para>
|
|
|
|
<para>In XML-based configuration metadata, you use the
|
|
<literal>id</literal> and/or <literal>name</literal> attributes to
|
|
specify the bean identifier(s). The <literal>id</literal> attribute
|
|
allows you to specify exactly one id, and because it is a real XML
|
|
element ID attribute, the XML parser can do some extra validation when
|
|
other elements reference the id. As such, it is the preferred way to
|
|
specify a bean identifier. However, the XML specification does limit the
|
|
characters that are legal in XML ids. This is usually not a constraint,
|
|
but if you need to use one of these special XML characters, or want to
|
|
introduce other aliases to the bean, you can also specify them in the
|
|
<literal>name</literal> attribute, separated by a comma
|
|
(<literal>,</literal>), semicolon (<literal>;</literal>), or white
|
|
space.</para>
|
|
|
|
<para>You are not required to supply a name or id for a bean. If no name
|
|
or id is supplied explicitly, the container generates a unique name for
|
|
that bean. However, if you want to refer to that bean by name, through
|
|
the use of the <literal>ref</literal> element or <link lang=""
|
|
linkend="beans-servicelocation">Service Location</link> style lookup,
|
|
you must provide a name. Motivations for not supplying a name are
|
|
related to using <link linkend="beans-inner-beans">inner beans</link>
|
|
and <link linkend="beans-factory-autowire">autowiring
|
|
collaborators</link>.</para>
|
|
|
|
<sidebar>
|
|
<title>Bean naming conventions</title>
|
|
|
|
<para>The convention 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>Naming beans consistently makes your configuration easier to
|
|
read and understand, and if you are using Spring AOP it helps a lot
|
|
when applying advice to a set of beans related by name.</para>
|
|
</sidebar>
|
|
|
|
<section id="beans-beanname-alias">
|
|
<title>Aliasing a bean outside the bean definition</title>
|
|
|
|
<para>In a bean definition itself, you can supply more than one name
|
|
for the bean, by using a combination of up to one name specified by
|
|
the <literal>id</literal> attribute, and any number of other names in
|
|
the <literal>name</literal> attribute. These names can be equivalent
|
|
aliases to the same bean, and are useful for some situations, such as
|
|
allowing each component in an application to refer to a common
|
|
dependency by using a bean name that is specific to that component
|
|
itself.</para>
|
|
|
|
<para>Specifying all aliases where the bean is actually defined is not
|
|
always adequate, however. It is sometimes desirable to introduce an
|
|
alias for a bean that is defined elsewhere. This is commonly the case
|
|
in large systems where configuration is split amongst each subsystem,
|
|
each subsystem having its own set of object defintions. In XML-based
|
|
configuration metadata, you can use of the
|
|
<literal><alias/></literal> element to accomplish this.</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>
|
|
|
|
<!-- MLP: Beverly to review -->
|
|
|
|
<para>For example, the configuration metadata for subsystem A may
|
|
refer to a DataSource via the name 'subsystemA-dataSource. The
|
|
configuration metadata for subsystem B may refer to a DataSource via
|
|
the name 'subsystemB-dataSource'. When composing the main application
|
|
that uses both these subsystems the main application refers to the
|
|
DataSource via the name 'myApp-dataSource'. To have all three names
|
|
refer to the same object you add to the MyApp configuration metadata
|
|
the following aliases definitions:</para>
|
|
|
|
<programlisting language="xml"><alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/>
|
|
<alias name="subsystemA-dataSource" alias="myApp-dataSource" /></programlisting>
|
|
|
|
<para>Now each component and the main application can refer to the
|
|
dataSource through a name that is unique and guaranteed not to clash
|
|
with any other definition (effectively creating a namespace), yet they
|
|
refer to the same bean.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-class">
|
|
<title>Instantiating beans</title>
|
|
|
|
<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 use XML-based configuration metadata, you specify the type
|
|
(or class) of object that is to be instantiated in the
|
|
<literal>class</literal> attribute of the
|
|
<literal><bean/></literal> element. This <literal>class</literal>
|
|
attribute, which internally is a <classname>Class</classname> property
|
|
on a <interfacename>BeanDefinition</interfacename> instance, is usually
|
|
mandatory. (For exceptions, see <xref
|
|
linkend="beans-factory-class-instance-factory-method" /> and <xref
|
|
linkend="beans-child-bean-definitions" />.) You use the
|
|
<classname>Class</classname> property in one of two ways: <itemizedlist>
|
|
<listitem>
|
|
<para>Typically, to specify the bean class to be constructed in
|
|
the case where the container itself directly creates the bean by
|
|
calling its constructor reflectively, somewhat equivalent to Java
|
|
code using the <code>new</code> operator.</para>
|
|
</listitem>
|
|
</itemizedlist></para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>To specify the actual class containing the
|
|
<literal>static</literal> factory method that will be invoked to
|
|
create the object, 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 object type returned from
|
|
the invocation of the <literal>static</literal> factory method may
|
|
be the same class or another class entirely.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<sidebar>
|
|
<title>Inner class names</title>
|
|
|
|
<para>If you want to configure a bean definition for a
|
|
<literal>static</literal> nested 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>
|
|
|
|
<section id="beans-factory-class-ctor">
|
|
<title>Instantiation with a constructor</title>
|
|
|
|
<para>When you create a bean by the constructor approach, all normal
|
|
classes are usable by and compatible with Spring. That is, the class
|
|
being developed does not need to implement any specific interfaces or
|
|
to be coded in a specific fashion. Simply specifying the bean class
|
|
should suffice. However, depending on what type of IoC you use for
|
|
that specific bean, you may need a default (empty) constructor.</para>
|
|
|
|
<para>The Spring IoC container can manage virtually
|
|
<emphasis>any</emphasis> class you want it to manage; it is not
|
|
limited to managing true JavaBeans. Most Spring users prefer actual
|
|
JavaBeans with only a default (no-argument) constructor and
|
|
appropriate setters and getters modeled after the properties in the
|
|
container. You can also 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>With XML-based configuration metadata you can specify your bean
|
|
class as follows:</para>
|
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"/>
|
|
|
|
<bean name="anotherExample" class="examples.ExampleBeanTwo"/></programlisting>
|
|
|
|
<para>For details about the mechanism for supplying arguments to the
|
|
constructor (if required) and setting object instance properties after
|
|
the object is constructed, see <link
|
|
linkend="beans-factory-collaborators">Injecting
|
|
Dependencies</link>.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-class-static-factory-method">
|
|
<title>Instantiation with a static factory method</title>
|
|
|
|
<para>When defining a bean that you create with a static factory
|
|
method, you use the <literal>class</literal> attribute to specify the
|
|
class containing the <literal>static</literal> factory method and an
|
|
attribute named <literal>factory-method</literal> to specify the name
|
|
of the factory method itself. You should be able to call this method
|
|
(with optional arguments as described later) and return a live object,
|
|
which subsequently is treated as if it had been created through a
|
|
constructor. One use for such a bean definition is to call
|
|
<literal>static</literal> factories in legacy code.</para>
|
|
|
|
<para>The following bean definition specifies that the bean will be
|
|
created by calling a factory-method. 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>For details about the mechanism for supplying (optional)
|
|
arguments to the factory method and setting object instance properties
|
|
after the object is returned from the factory, see <link
|
|
linkend="beans-factory-properties-detailed">Dependencies and
|
|
configuration in detail</link>.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-class-instance-factory-method">
|
|
<title>Instantiation using an instance factory method</title>
|
|
|
|
<para>Similar to instantiation through a <link
|
|
linkend="beans-factory-class-static-factory-method">static factory
|
|
method</link>, instantiation with an instance factory method invokes a
|
|
non-static method of an existing bean from the container to create a
|
|
new bean. To use this mechanism, leave the <literal>class
|
|
</literal>attribute empty, and in the <literal>factory-bean</literal>
|
|
attribute, 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. Set the name of the factory method
|
|
itself with 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>This approach shows that the factory bean itself can be managed
|
|
and configured through dependency injection (DI). See <link
|
|
linkend="beans-factory-properties-detailed"><link
|
|
linkend="beans-factory-properties-detailed">Dependencies and
|
|
configuration in detail</link>.</link></para>
|
|
|
|
<note>
|
|
<para>In Spring documentation,<emphasis> factory bean</emphasis>
|
|
refers to a bean that is configured in the Spring container that
|
|
will create objects through an <link
|
|
linkend="beans-factory-class-instance-factory-method">instance</link>
|
|
or <link
|
|
linkend="beans-factory-class-static-factory-method">static</link>
|
|
factory method. By contrast,
|
|
<interfacename>FactoryBean</interfacename> (notice the
|
|
capitalization) refers to a Spring-specific <link
|
|
linkend="beans-factory-extension-factorybean">
|
|
<interfacename>FactoryBean</interfacename> </link>.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-dependencies">
|
|
<title>Dependencies</title>
|
|
|
|
<para>A typical enterprise application does not consist of a single object
|
|
(or bean in the Spring parlance). Even the simplest application has a few
|
|
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 to a fully realized application where
|
|
objects collaborate to achieve a goal.</para>
|
|
|
|
<section id="beans-factory-collaborators">
|
|
<title>Dependency injection</title>
|
|
|
|
<!-- MLP: Beverly review the following two paragraphs -->
|
|
|
|
<para><emphasis>Dependency injection</emphasis> (DI) is a process
|
|
whereby objects define their dependencies, that is, the other objects
|
|
they work with, only through constructor arguments, arguments to a
|
|
factory method, or properties that are set on the object instance after
|
|
it is constructed or returned from a factory method. The container then
|
|
<emphasis>injects</emphasis> those dependencies when it creates the
|
|
bean. This process is fundamentally the inverse, hence the name
|
|
<emphasis>Inversion of Control</emphasis> (IoC), of the bean itself
|
|
controlling the instantiation or location of its dependencies on its own
|
|
by using direct construction of classes, or the <emphasis>Service
|
|
Locator</emphasis> pattern.</para>
|
|
|
|
<para>Code is cleaner with the DI principle and decoupling is more
|
|
effective when objects are provided with their dependencies. The object
|
|
does not look up its dependencies, and does not know the location or
|
|
class of the dependencies. As such, your classes become easier to test,
|
|
in particular when the dependencies are on interfaces or abstract base
|
|
classes, which allow for stub or mock implementations to be used in unit
|
|
tests.</para>
|
|
|
|
<para>DI exists in two major variants, <link
|
|
linkend="beans-constructor-injection">Constructor-based dependency
|
|
injection</link> and <link linkend="beans-setter-injection">Setter-based
|
|
dependency injection</link>.</para>
|
|
|
|
<section id="beans-constructor-injection">
|
|
<title>Constructor-based dependency injection</title>
|
|
|
|
<para><emphasis>Constructor-based</emphasis> DI is accomplished by the
|
|
container invoking a constructor with a number of arguments, each
|
|
representing a dependency. Calling a <literal>static</literal> factory
|
|
method with specific arguments to construct the bean is nearly
|
|
equivalent, and this discussion treats arguments to a constructor and
|
|
to a <literal>static</literal> factory method similarly. The following
|
|
example shows a class that can only be dependency-injected with
|
|
constructor injection. Notice that there is nothing
|
|
<emphasis>special</emphasis> about this class, it is a POJO that has
|
|
no dependencies on container specific interfaces, base classes or
|
|
annotations.</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 no potential ambiguity exists 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 are supplied to the appropriate constructor
|
|
when the bean 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>No potential ambiguity exists, assuming that
|
|
<classname>Bar</classname> and <classname>Baz</classname> classes
|
|
are not related by inheritance. Thus the following configuration
|
|
works fine, and you do not need to specify the constructor argument
|
|
indexes and/or types explicitly in the
|
|
<literal><constructor-arg/></literal> element.</para>
|
|
|
|
<programlisting language="xml"><beans>
|
|
<bean id="foo" class="x.y.Foo">
|
|
<constructor-arg ref="bar"/>
|
|
<constructor-arg ref="baz"/>
|
|
</bean>
|
|
|
|
<bean id="bar" class="x.y.Bar"/>
|
|
<bean id="baz" class="x.y.Baz"/>
|
|
|
|
</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>In the preceding scenario, the container
|
|
<emphasis>can</emphasis> use type matching with simple types if
|
|
you explicitly specify 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>Use the <literal>index</literal> attribute to specify
|
|
explicitly the index of constructor arguments. 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>In addition to resolving the ambiguity of multiple simple
|
|
values, specifying an index resolves ambiguity where a constructor
|
|
has 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-based dependency injection</title>
|
|
|
|
<para><emphasis>Setter-based</emphasis> DI is accomplished by the
|
|
container 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>The <interfacename>ApplicationContext</interfacename> supports
|
|
constructor- and setter-based DI for the beans it manages. It also
|
|
supports setter-based DI after some dependencies are already injected
|
|
through the constructor approach.</para>
|
|
|
|
<para>The following example shows a class that can only be
|
|
dependency-injected using pure setter injection. This class is
|
|
conventional Java. It is a POJO that has no dependencies on container
|
|
specific interfaces, base classes or annotations.</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>
|
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> supports
|
|
constructor- and setter-based DI for the beans it manages. It also
|
|
supports setter-based DI after some dependencies are already injected
|
|
through the constructor approach. You configure the dependencies in
|
|
the form of a <interfacename>BeanDefinition</interfacename>, which you
|
|
use with <interfacename>PropertyEditor</interfacename> instances to
|
|
convert properties from one format to another. However, most Spring
|
|
users do not work with these classes directly (programmatically), but
|
|
rather with an XML definition file that is then converted internally
|
|
into instances of these classes, and used to load an entire Spring IoC
|
|
container instance.</para>
|
|
|
|
<sidebar>
|
|
<title>Constructor-based or setter-based DI?</title>
|
|
|
|
<para>Since you can mix both, Constructor- and Setter-based DI, it
|
|
is a good rule of thumb to use constructor arguments for mandatory
|
|
dependencies and setters for optional dependencies. Note that the
|
|
use of a <link linkend="beans-required-annotation">@Required</link>
|
|
annotation on a setter can be used to make setters required
|
|
dependencies.</para>
|
|
|
|
<para>The Spring team generally advocates setter injection, because
|
|
large numbers of constructor arguments can get unwieldy, especially
|
|
when properties are optional. Setter methods also make objects of
|
|
that class amenable to reconfiguration or re-injection later.
|
|
Management through <link linkend="jmx">JMX MBeans</link> is a
|
|
compelling use case.</para>
|
|
|
|
<para>Some purists favor constructor-based injection. Supplying all
|
|
object dependencies means that the object is always returned to
|
|
client (calling) code in a totally initialized state. The
|
|
disadvantage is that the object becomes less amenable to
|
|
reconfiguration and re-injection.</para>
|
|
|
|
<para>Use the DI that 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 is made for you. A legacy class may not
|
|
expose any setter methods, and so constructor injection is the only
|
|
available DI.</para>
|
|
</sidebar>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Dependency resolution process</title>
|
|
|
|
<para>The container performs bean dependency resolution as
|
|
follows:</para>
|
|
|
|
<!-- MLP: Beverly to review all list items-->
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>The <interfacename>ApplicationContext</interfacename> is
|
|
created an initialized with configuration metadata that describes
|
|
all the beans. Configuration metadata can be specified via XML,
|
|
Java code or annotations.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>For each bean, its dependencies are expressed in the form of
|
|
properties, constructor arguments, or arguments to the
|
|
static-factory method if you are using that instead of a normal
|
|
constructor. These dependencies are provided to the bean,
|
|
<emphasis>when the bean is actually created</emphasis>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each property or constructor argument an actual definition
|
|
of the value to set, or a reference to another bean in the
|
|
container.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Each property or constructor argument which is a value is
|
|
converted from its specified format 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 of whether bean
|
|
reference properties refer to valid beans. However, the bean
|
|
properties themselves are not set until the bean <emphasis>is actually
|
|
created</emphasis>. Beans that are singleton-scoped and set to be
|
|
pre-instantiated (the default) are created when the container is
|
|
created. Scopes are defined in <xref linkend="beans-factory-scopes" />
|
|
Otherwise, the bean is created only when it is requested. Creation of
|
|
a bean potentially causes a graph of beans to be created, as the
|
|
bean's dependencies and its dependencies' dependencies (and so on) are
|
|
created and assigned.</para>
|
|
|
|
<sidebar>
|
|
<title>Circular dependencies</title>
|
|
|
|
<para>If you use predominantly constructor injection, it is possible
|
|
to create an unresolvable circular dependency scenario.</para>
|
|
|
|
<para>For example: Class A requires an instance of class B through
|
|
constructor injection, and class B requires an instance of class A
|
|
through constructor injection. If you configure beans for classes A
|
|
and B to be injected into each other, the Spring IoC container
|
|
detects this circular reference at runtime, and throws a
|
|
<classname>BeanCurrentlyInCreationException</classname>.</para>
|
|
|
|
<para>One possible solution is to edit the source code of some
|
|
classes to be configured by setters rather than constructors.
|
|
Alternatively, avoid constructor injection and use setter injection
|
|
only. In other words, although it is not recommended, you can
|
|
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
|
|
forces 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 detects
|
|
configuration problems, such as references to non-existent beans and
|
|
circular dependencies, at container load-time. Spring sets properties
|
|
and resolves dependencies as late as possible, when the bean is
|
|
actually created. This means that a Spring container which has loaded
|
|
correctly can later generate an exception when you request an object
|
|
if there is a problem creating that object or one of its dependencies.
|
|
For example, the bean throws an exception as a result of a missing or
|
|
invalid property. 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 discover configuration issues when the
|
|
<interfacename>ApplicationContext</interfacename> is created, not
|
|
later. You can still override this default behavior so that singleton
|
|
beans will lazy-initialize, rather than be pre-instantiated.</para>
|
|
|
|
<para>If no circular dependencies exist, when one or more
|
|
collaborating beans are being injected into a dependent bean, each
|
|
collaborating bean is <emphasis>totally</emphasis> configured prior to
|
|
being injected into the dependent bean. This means that if bean A has
|
|
a dependency on bean B, the Spring IoC container completely configures
|
|
bean B prior to invoking the setter method on bean A. In other words,
|
|
the bean is instantiated (if not a pre-instantiated singleton), its
|
|
dependencies are 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>) are invoked.</para>
|
|
</section>
|
|
|
|
<section id="beans-some-examples">
|
|
<title>Examples of dependency injection</title>
|
|
|
|
<para>The following example uses XML-based configuration metadata for
|
|
setter-based DI. A small part of a Spring XML configuration file
|
|
specifies 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>In the preceding example, setters are declared to match against
|
|
the properties specified in the XML file. The following example uses
|
|
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>The constructor arguments specified in the bean definition will
|
|
be used as arguments to the constructor of the
|
|
<classname>ExampleBean</classname>.</para>
|
|
|
|
<para>Now consider a variant of this example, 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>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. The type
|
|
of the class being returned by the factory method does not have to be
|
|
of the same type as the class that 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, you can define bean
|
|
properties and constructor arguments as references to other managed
|
|
beans (collaborators), or as values defined inline. Spring's XML-based
|
|
configuration metadata supports sub-element types within its
|
|
<literal><property/></literal> and
|
|
<literal><constructor-arg/></literal> elements for this
|
|
purpose.</para>
|
|
|
|
<section id="beans-value-element">
|
|
<title>Straight values (primitives, <literal>Strings</literal>, and so
|
|
on)</title>
|
|
|
|
<para>The <literal>value</literal> attribute of the
|
|
<literal><property/></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"/>
|
|
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
|
|
<property name="username" value="root"/>
|
|
<property name="password" value="masterkaoli"/>
|
|
</bean></programlisting>
|
|
|
|
<para>The following example uses the <link
|
|
linkend="beans-p-namespace">p-namespace</link> for even more succinct
|
|
XML configuration.</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 id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
|
|
destroy-method="close"
|
|
p:driverClassName="com.mysql.jdbc.Driver"
|
|
p:url="jdbc:mysql://localhost:3306/mydb"
|
|
p:username="root"
|
|
p:password="masterkaoli"/>
|
|
|
|
</beans>
|
|
|
|
</programlisting>
|
|
|
|
<para>The preceding XML is more succinct; however, typos are
|
|
discovered at runtime rather than design time, unless you use an IDE
|
|
such as <ulink url="http://www.jetbrains.com/idea/">IntelliJ
|
|
IDEA</ulink> or the <ulink
|
|
url="http://www.springsource.com/products/sts">SpringSource Tool
|
|
Suite</ulink> (STS) that support automatic property completion when
|
|
you create bean definitions. Such IDE assistance is highly
|
|
recommended.</para>
|
|
|
|
<para>You can also configure a
|
|
<classname>java.util.Properties</classname> instance as:</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>The Spring container converts the text inside the
|
|
<literal><value/></literal> element into a
|
|
<classname>java.util.Properties</classname> instance by 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> (string value - not a
|
|
reference) 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 first form is preferable to the second, because 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. Typos are only 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 deployed.</para>
|
|
|
|
<para>Additionally, if the referenced bean is in the same XML unit,
|
|
and the bean name is the bean <emphasis>id</emphasis>, you can use
|
|
the <literal>local</literal> attribute, which allows the XML parser
|
|
itself to validate the bean id earlier, at XML document parse
|
|
time.</para>
|
|
|
|
<programlisting language="xml"><property name="targetName">
|
|
<lineannotation><!-- a bean with id '<literal>theTargetBean</literal>' must exist; otherwise an exception will be thrown --></lineannotation>
|
|
<idref local="theTargetBean"/>
|
|
</property></programlisting>
|
|
|
|
<para>A common place (at least in versions earlier than Spring 2.0)
|
|
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. Using
|
|
<idref/> elements when you specify the interceptor names
|
|
prevents you from 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 inside a
|
|
<literal><constructor-arg/></literal> or
|
|
<literal><property/></literal> definition element. Here you set
|
|
the value of the specified property of a bean to be a reference to
|
|
another bean (a collaborator) managed by the container. The referenced
|
|
bean is a dependency of the bean whose property will be set, and it is
|
|
initialized on demand as needed before the property is set. (If the
|
|
collaborator is a singleton bean, it may be initialized already by the
|
|
container.) All references are ultimately a reference to another
|
|
object. Scoping and validation depend on whether you specify the
|
|
id/name of the other object through the
|
|
<literal>bean,<literal>local,</literal></literal> or
|
|
<literal>parent</literal> attributes.</para>
|
|
|
|
<para>Specifying the target bean through the <literal>bean</literal>
|
|
attribute of the <literal><ref/></literal> tag is the most
|
|
general form, and allows creation of a reference to any bean in the
|
|
same container or parent container, regardless of whether it is in the
|
|
same XML file. The value of the <literal>bean</literal> attribute may
|
|
be the same as the <literal>id</literal> attribute of the target bean,
|
|
or as 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 through 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
|
|
issues 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 through the <literal>parent</literal>
|
|
attribute creates a reference to a bean that 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 of the current one. You use this
|
|
bean reference variant mainly when you have a hierarchy of containers
|
|
and you want to wrap an existing bean in a parent container with a
|
|
proxy that 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><-- bean name is the same as the parent bean --></lineannotation>
|
|
class="org.springframework.aop.framework.ProxyFactoryBean">
|
|
<property name="target">
|
|
<ref parent="accountService"/> <lineannotation><!-- notice how we refer to the parent bean --></lineannotation>
|
|
</property>
|
|
<lineannotation><!-- insert other configuration and dependencies as required 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 defines a
|
|
so-called <firstterm>inner bean</firstterm>.</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>An inner bean definition does not require a defined id or name;
|
|
the container ignores these values. It also ignores the
|
|
<literal>scope</literal> flag. Inner beans are
|
|
<emphasis>always</emphasis> anonymous and they are
|
|
<emphasis>always</emphasis> scoped as <link
|
|
linkend="beans-factory-scopes-prototype">prototypes</link>. It is
|
|
<emphasis>not</emphasis> possible to inject inner beans into
|
|
collaborating beans other than into the enclosing bean.</para>
|
|
</section>
|
|
|
|
<section id="beans-collection-elements">
|
|
<title>Collections</title>
|
|
|
|
<para>In the <literal><list/></literal>,
|
|
<literal><set/></literal>, <literal><map/></literal>, and
|
|
<literal><props/></literal> elements, you set the properties and
|
|
arguments of the Java <interfacename>Collection</interfacename> types
|
|
<interfacename>List</interfacename>,
|
|
<interfacename>Set</interfacename>,
|
|
<interfacename>Map</interfacename>, and
|
|
<interfacename>Properties</interfacename>, respectively.</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="an entry" value="just some string"/>
|
|
<entry key ="a ref" value-ref="myDataSource"/>
|
|
</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>
|
|
|
|
<para><emphasis>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 supports the
|
|
<emphasis>merging</emphasis> of collections. An application
|
|
developer can 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, the child collection's
|
|
values are the result of merging the elements of the parent and
|
|
child collections, with the child's collection elements overriding
|
|
values specified in the parent collection.</para>
|
|
|
|
<para><emphasis>This section on merging discusses the parent-child
|
|
bean mechanism. Readers unfamiliar with parent and child bean
|
|
definitions may wish to read the <link
|
|
linkend="beans-child-bean-definitions">relevant section</link>
|
|
before continuing.</emphasis></para>
|
|
|
|
<para>The following example demonstrates collection merging:</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 resolved and instantiated by the
|
|
container, the resulting instance has 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>The child <classname>Properties</classname> collection's value
|
|
set inherits all property elements from the parent
|
|
<literal><props/></literal>, and 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 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, no
|
|
ordering exists. 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 that
|
|
the container uses internally.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Limitations of collection merging</title>
|
|
|
|
<para>You cannot merge different collection types (such as a
|
|
<interfacename>Map</interfacename> and a
|
|
<interfacename>List</interfacename>), and if you do attempt to do so
|
|
an appropriate <classname>Exception</classname> is thrown. The
|
|
<literal>merge</literal> attribute must be specified on the lower,
|
|
inherited, child definition; specifying the <literal>merge</literal>
|
|
attribute on a parent collection definition is redundant and will
|
|
not result in the desired merging. The merging feature is available
|
|
only in Spring 2.0 and later.</para>
|
|
</section>
|
|
|
|
<section id="beans-collection-elements-strongly-typed">
|
|
<title>Strongly-typed collection (Java 5+ only)</title>
|
|
|
|
<para>In Java 5 and later, you can use 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 are 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 prepared for injection, the generics
|
|
information about the element type of the strongly-typed
|
|
<classname>Map<String, Float></classname> is available by
|
|
reflection. Thus Spring's type conversion infrastructure recognizes
|
|
the various value elements as being of type
|
|
<classname>Float</classname>, and the string values <literal>9.99,
|
|
2.75</literal>, and <literal>3.99</literal> are converted into an
|
|
actual <classname>Float</classname> type.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-null-element">
|
|
<title>Null and empty string values</title>
|
|
|
|
<para><!--Clarify difference between null value and empty string value?-->Spring
|
|
treats empty arguments for properties and the like as empty
|
|
<literal>Strings</literal>. The following XML-based configuration
|
|
metadata snippet sets the email property to the empty
|
|
<classname>String</classname> value ("")</para>
|
|
|
|
<programlisting language="xml"><bean class="ExampleBean">
|
|
<property name="email" value=""/>
|
|
</bean></programlisting>
|
|
|
|
<para>The preceding example is equivalent to the following Java code:
|
|
<methodname>exampleBean.setEmail("")</methodname>. The
|
|
<literal><null/></literal> element handles
|
|
<literal>null</literal> values. 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="beans-p-namespace">
|
|
<title>XML shortcut with the p-namespace</title>
|
|
|
|
<para>The p-namespace enables you to use the <literal>bean</literal>
|
|
element's attributes, instead of nested
|
|
<literal><property/></literal> elements, to describe your
|
|
property values and/or collaborating beans.</para>
|
|
|
|
<para>Spring 2.0 and later supports extensible configuration formats
|
|
<link linkend="xsd-config">with namespaces</link>, which are based on
|
|
an XML Schema definition. The <literal>beans</literal> configuration
|
|
format discussed in this chapter is defined in an XML Schema document.
|
|
However, the p-namespace is not defined in an XSD file and exists only
|
|
in the core of Spring.</para>
|
|
|
|
<para>The following example shows two XML snippets that resolve to the
|
|
same result: The first uses standard XML format and the second uses
|
|
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>The example shows an attribute in the p-namespace called email
|
|
in the bean definition. This tells Spring to include a property
|
|
declaration. As previously mentioned, the p-namespace not have a
|
|
schema definition, so you can set the name of the attribute to the
|
|
property name.</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 includes not only 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>The p-namespace is not as flexible as the standard XML format.
|
|
For example, the format for declaring property references clashes
|
|
with properties that end in <literal>Ref</literal>, whereas the
|
|
standard XML format does not. We recommend that you choose your
|
|
approach carefully and communicate this to your team members, to
|
|
avoid producing XML documents that use all three approaches at the
|
|
same time.<!--Clarify ref to all three approaches.I see two, XML and namespace.--></para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-compound-property-names">
|
|
<title>Compound property names</title>
|
|
|
|
<para>You can use compound or nested property names when you set 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> after the bean is constructed, or a
|
|
<exceptionname>NullPointerException</exceptionname> is thrown.</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-dependson">
|
|
<title>Using <literal>depends-on</literal></title>
|
|
|
|
<para>If a bean is a dependency of another that usually means that one
|
|
bean is set as a property of another. Typically you accomplish this with
|
|
the <link linkend="beans-ref-element"><literal><ref/></literal>
|
|
element</link> in XML-based configuration metadata. However, sometimes
|
|
dependencies between beans are less direct; for example, a static
|
|
initializer in a class needs to be triggered, such as database driver
|
|
registration. The <literal>depends-on</literal> attribute can explicitly
|
|
force one or more beans to be initialized before the bean using this
|
|
element is initialized. The following example uses 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>To express a dependency on multiple beans, supply a list of bean
|
|
names as the value of the <literal>depends-on</literal> attribute, with
|
|
commas, whitespace and semicolons, used as valid delimiters:</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 in the bean
|
|
definition can specify both an initialization time dependency and, in
|
|
the case of <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link> beans only,
|
|
a corresponding destroy time dependency. Dependent beans that define a
|
|
<literal>depends-on</literal> relationship with a given bean are
|
|
destroyed first, prior to the given bean itself being destroyed. Thus
|
|
<literal>depends-on</literal> can also control shutdown order.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-factory-lazy-init">
|
|
<title>Lazy-initialized beans<!--Changed to lazy-initialized from lazily instantiated because attribute is lazy-init, and there was a lot of inconsistency. --></title>
|
|
|
|
<para>By default,<interfacename> ApplicationContext</interfacename>
|
|
implementations eagerly create and configure all <link
|
|
linkend="beans-factory-scopes-singleton">singleton</link> beans as part
|
|
of the initialization process. Generally, this pre-instantiation is
|
|
desirable, because errors in the configuration or surrounding
|
|
environment are discovered immediately, as opposed to hours or even days
|
|
later. When this behavior is <emphasis>not</emphasis> desirable, you can
|
|
prevent pre-instantiation of a singleton bean by marking the bean
|
|
definition as lazy-initialized. A lazy-initialized bean tells the IoC
|
|
container to create a bean instance when it is first requested, rather
|
|
than at startup.<!--Above, clarify what you mean by eagerly. Note, I've trimmed this section for conciseness, but info is still here.--></para>
|
|
|
|
<para>In XML, this behavior 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 preceding configuration is consumed by an
|
|
<interfacename>ApplicationContext</interfacename>, the bean named
|
|
<literal>lazy</literal> is not eagerly pre-instantiated when the
|
|
<interfacename>ApplicationContext</interfacename> is starting up,
|
|
whereas the <literal>not.lazy</literal> bean is eagerly
|
|
pre-instantiated.</para>
|
|
|
|
<para>However, when a lazy-initialized bean is a dependency of a
|
|
singleton bean that is <emphasis>not</emphasis> lazy-initialized, the
|
|
<interfacename>ApplicationContext</interfacename> creates the
|
|
lazy-initialized bean at startup, because it must satisfy the
|
|
singleton's dependencies. The lazy-initialized bean is injected into a
|
|
singleton bean elsewhere that is not lazy-initialized.</para>
|
|
|
|
<para>You can also 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>
|
|
|
|
<!--I've moved around info and done a lot of editing/reformatting in this section, but nothing is missing.-->
|
|
|
|
<para>The Spring container can <emphasis>autowire</emphasis>
|
|
relationships between collaborating beans. You can allow Spring to
|
|
resolve collaborators (other beans) automatically for your bean by
|
|
inspecting the contents of the
|
|
<interfacename>ApplicationContext</interfacename>. Autowiring has the
|
|
following advantages:</para>
|
|
|
|
<para><itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring can significantly reduce the need to specify
|
|
properties or constructor arguments. (Other mechanisms such as 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 update a configuration as your objects
|
|
evolve. For example, if you need to add a dependency to a class,
|
|
that dependency can be satisfied automatically your needing to
|
|
modify the configuration. Thus autowiring can be especially useful
|
|
during development, without negating the option of switching to
|
|
explicit wiring when the code base becomes more stable.</para>
|
|
</listitem>
|
|
</itemizedlist><footnote>
|
|
<para>See <xref linkend="beans-factory-collaborators" /></para>
|
|
</footnote> When using XML-based configuration metadata, you specify
|
|
autowire mode for a bean definition with the <literal>autowire</literal>
|
|
attribute of the <literal><bean/></literal> element. The
|
|
autowiring functionality has five modes. You specify autowiring
|
|
<emphasis>per</emphasis> bean and thus can choose which ones to
|
|
autowire.</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>(Default) No autowiring. Bean references must be
|
|
defined via a <literal>ref</literal> element. Changing the
|
|
default setting is not recommended for larger deployments,
|
|
because specifying collaborators explicitly gives greater
|
|
control and clarity. To some extent, it documents the structure
|
|
of a system.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byName</entry>
|
|
|
|
<entry><para>Autowiring by property name. Spring looks for a
|
|
bean with the same name as the property that needs to be
|
|
autowired. For example, if a bean definition is set to autowire
|
|
by name, and it contains a <emphasis>master</emphasis> property
|
|
(that is, it has a <emphasis>setMaster(..)</emphasis> method),
|
|
Spring looks for a bean definition named
|
|
<literal>master</literal>, and uses it to set the
|
|
property.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>byType</entry>
|
|
|
|
<entry><para>Allows a property to be autowired if exactly one
|
|
bean of the property type exists in the container. If more than
|
|
one exists, a fatal exception is thrown, which 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>Analogous to <emphasis>byType</emphasis>, but
|
|
applies to constructor arguments. If there is not 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 is applied.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>With <emphasis>byType</emphasis> or
|
|
<emphasis>constructor</emphasis> autowiring mode, you can wire arrays
|
|
and typed-collections. In such cases <emphasis>all</emphasis> autowire
|
|
candidates within the container that match the expected type are
|
|
provided to satisfy the dependency. You can autowire strongly-typed Maps
|
|
if the expected key type is <classname>String</classname>. An autowired
|
|
Maps values will consist of all bean instances that match the expected
|
|
type, and the Maps keys will contain the corresponding bean
|
|
names.</para>
|
|
|
|
<para>You can combine autowire behavior with dependency checking, which
|
|
is performed after autowiring completes.</para>
|
|
|
|
<section id="beans-autowired-exceptions">
|
|
<title>Limitations and disadvantages of autowiring</title>
|
|
|
|
<para>Autowiring works best when it is used consistently across a
|
|
project. If autowiring is not used in general, it might be confusing
|
|
to developers to use it to wire only one or two bean
|
|
definitions.</para>
|
|
|
|
<para>Consider the limitations and disadvantages of autowiring:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Explicit dependencies in <literal>property</literal> and
|
|
<literal>constructor-arg</literal> settings always override
|
|
autowiring. You cannot autowire so-called
|
|
<emphasis>simple</emphasis> properties such as primitives,
|
|
<classname>Strings</classname>, and <classname>Classes</classname>
|
|
(and arrays of such simple properties). This limitation is
|
|
by-design.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Autowiring is less exact than explicit wiring. Although, as
|
|
noted in the above table, Spring is careful to avoid guessing in
|
|
case of ambiguity that 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>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>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 is not arbitrarily resolved. If no
|
|
unique bean definition is available, an exception is
|
|
thrown.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>In the latter scenario, you have several options:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Abandon autowiring in favor of explicit wiring.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Avoid autowiring for a bean definition by setting its
|
|
<literal>autowire-candidate</literal> attributes to
|
|
<literal>false</literal> as described in the next section.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>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>.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If you are using Java 5 or later, implement the more
|
|
fine-grained control available with annotation-based
|
|
configuration, as described in <xref
|
|
linkend="beans-annotation-config" />.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
|
|
<section id="beans-factory-autowire-candidate">
|
|
<title>Excluding a bean from autowiring</title>
|
|
|
|
<para>On a per-bean basis, you can exclude a bean from autowiring. In
|
|
Spring's XML format, set the <literal>autowire-candidate</literal>
|
|
attribute of the <literal><bean/></literal> element to
|
|
<literal>false</literal>; the container makes that specific bean
|
|
definition unavailable to the autowiring infrastructure.</para>
|
|
|
|
<para>You can also 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. An
|
|
explicit value of <literal>true</literal> or <literal>false</literal>
|
|
for a bean definitions <literal>autowire-candidate</literal> attribute
|
|
always takes precedence, and for such beans, the pattern matching
|
|
rules do not apply.</para>
|
|
|
|
<para>These techniques are useful for beans that you never want to be
|
|
injected into other beans by autowiring. It does not mean that an
|
|
excluded bean cannot itself be configured using autowiring. Rather,
|
|
the bean itself is not a candidate for autowiring other beans.</para>
|
|
|
|
<!--Last paragraph unclear to me. Is my edit ok? Revise as necessary.-->
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-dependencies">
|
|
<title>Checking for dependencies</title>
|
|
|
|
<!-- MLP: Beverly to review paragraph -->
|
|
|
|
<para>The Spring IoC container can check for unresolved dependencies of
|
|
a bean deployed into the container. When enabling checking for
|
|
unresolved dependencies all JavaBean properties of the bean must have
|
|
explicit values set for them in the bean definition or have their values
|
|
set via autowiring.<!--Please revise preceding sentence, wording doesn't track.--></para>
|
|
|
|
<para>This feature is useful when you want to ensure that all properties
|
|
(or all properties of a certain type) are set on a bean. A bean class
|
|
often has default values for many properties, or some properties do not
|
|
apply to all usage scenarios, so this feature is of limited use. You can
|
|
enable dependency checking per bean, just as with the autowiring
|
|
functionality. The default is to <emphasis>not</emphasis> check
|
|
dependencies. In XML-based configuration metadata, you specify
|
|
dependency checking via the <literal>dependency-check</literal>
|
|
attribute in a bean definition, which can 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>(Default) No dependency checking. Properties of the
|
|
bean that have no value specified for them are not
|
|
set.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>simple</entry>
|
|
|
|
<entry><para>Dependency checking for primitive types and
|
|
collections (everything except collaborators).</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>object</entry>
|
|
|
|
<entry><para>Dependency checking for collaborators
|
|
only.</para></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>all</entry>
|
|
|
|
<entry><para>Dependency checking for collaborators, primitive
|
|
types, and collections.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>If you use Java 5 and thus have access to source-level
|
|
annotations, you may find <literal><xref
|
|
linkend="metadata-annotations-required" /></literal> to be of
|
|
interest.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-method-injection">
|
|
<title>Method injection</title>
|
|
|
|
<para>In most application scenarios, most beans in the container are
|
|
<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,
|
|
you typically handle the dependency by defining one bean as a property
|
|
of the other. A problem arises when the bean lifecycles are different.
|
|
Suppose singleton bean A needs to use non-singleton (prototype) bean B,
|
|
perhaps on each method invocation on A. The container only creates the
|
|
singleton bean A once, and thus only gets one opportunity to set the
|
|
properties. The container cannot provide bean A with a new instance of
|
|
bean B every time one is needed.</para>
|
|
|
|
<para>A solution is to forego some inversion of control. You can <link
|
|
linkend="beans-factory-aware-beanfactoryaware">make bean A aware of the
|
|
container</link> by implementing the
|
|
<interfacename>ApplicationContextAware</interfacename> interface, and by
|
|
<link linkend="beans-factory-client">making a getBean("B") call to the
|
|
container</link> ask for (a typically new) bean B instance every time
|
|
bean A needs it. The following is an 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>// Spring-API imports</lineannotation>
|
|
import org.springframework.beans.BeansException;
|
|
import org.springframework.context.Applicationcontext;
|
|
import org.springframework.context.ApplicationContextAware;
|
|
|
|
public class CommandManager implements ApplicationContextAware {
|
|
|
|
private ApplicationContext applicationContext;
|
|
|
|
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();
|
|
}
|
|
|
|
protected Command createCommand() {
|
|
<lineannotation>// notice the Spring API dependency!</lineannotation>
|
|
return this.applicationContext.getBean("command", Command.class);
|
|
}
|
|
|
|
public void setApplicationContext(ApplicationContext applicationContext)
|
|
throws BeansException {
|
|
this.applicationContext = applicationContext;
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>The preceding is not desirable, because the business code is 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.<!--Why give an example that is not desirable? Unclear whether this is an illustration of true method injection.--></para>
|
|
|
|
<sidebar>
|
|
<para>You can read more about the motivation for Method Injection in
|
|
<ulink url="http://blog.springsource.com/2004/08/06/method-injection/">this blog
|
|
entry</ulink>.</para>
|
|
</sidebar>
|
|
|
|
<section id="beans-factory-lookup-method-injection">
|
|
<title>Lookup method injection</title>
|
|
|
|
<!--Deleted a box here that doesn't seem to have much info; I moved the blog entry link above. -->
|
|
|
|
<para>Lookup method injection is the ability of the container to
|
|
override methods on <emphasis>container managed beans</emphasis>, to
|
|
return the lookup result for another named bean in the container. The
|
|
lookup typically involves a prototype bean as in the scenario
|
|
described in the preceding section. The Spring Framework implements
|
|
this method injection by using bytecode generation from the CGLIB
|
|
library to generate dynamically a subclass that overrides the
|
|
method.<!--Note was plain text; I made it a note and moved it up.--></para>
|
|
|
|
<note>
|
|
<para>For this dynamic subclassing to work, you must have the CGLIB
|
|
jar(s) in your classpath. The class that the Spring container will
|
|
subclass cannot be <literal>final</literal>, and the method to be
|
|
overridden cannot be <literal>final</literal> either. Also, testing
|
|
a class that has an <literal>abstract</literal> method requires you
|
|
to subclass the class yourself and to supply a stub implementation
|
|
of the <literal>abstract</literal> method. Finally, objects that
|
|
have been the target of method injection cannot be
|
|
serialized.</para>
|
|
</note>
|
|
|
|
<para>Looking at the <classname>CommandManager</classname> class in
|
|
the previous code snippet, you see that the Spring container will
|
|
dynamically override the implementation of the
|
|
<methodname>createCommand()</methodname> method. Your
|
|
<classname>CommandManager</classname> class will not have any Spring
|
|
dependencies, as can be seen in the reworked example:</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 to be
|
|
injected requires 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 implements the method. Otherwise, the
|
|
dynamically-generated subclass overrides the concrete method defined
|
|
in the original class. For 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> calls
|
|
its own method <methodname>createCommand()</methodname> whenever it
|
|
needs a new instance of the <emphasis>command</emphasis> bean. You
|
|
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 is returned each
|
|
time.</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 used in ServiceLocatorFactoryBean is
|
|
similar to that of another utility class,
|
|
<classname>ObjectFactoryCreatingFactoryBean</classname>, but it
|
|
allows you to specify your own lookup interface as opposed to a
|
|
Spring-specific lookup interface. Consult the JavaDocs for these
|
|
classes as well as this <ulink
|
|
url="http://blog.arendsen.net/index.php/2006/10/05/on-the-servicelocatorfactorybean-dlas-and-the-sustainability-of-code-and-design/">blog
|
|
entry</ulink> for additional information
|
|
ServiceLocatorFactoryBean.</para>
|
|
</tip>
|
|
</section>
|
|
|
|
<section id="beans-factory-arbitrary-method-replacement">
|
|
<title>Arbitrary method replacement</title>
|
|
|
|
<para>A less 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 until the functionality is actually needed.<!--Delete this section? See preceding sentence.--></para>
|
|
|
|
<para>With XML-based configuration metadata, you can use the
|
|
<literal>replaced-method</literal> element 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>You can use one or more contained
|
|
<literal><arg-type/></literal> elements within the
|
|
<literal><replaced-method/></literal> element to indicate the
|
|
method signature of the method being overridden. The signature for the
|
|
arguments is necessary only if the method is overloaded and multiple
|
|
variants exist within the class. For convenience, the type string for
|
|
an argument may be a substring of the fully qualified type name. For
|
|
example, the following all match
|
|
<classname>java.lang.String</classname>:</para>
|
|
|
|
<programlisting language="java"> java.lang.String
|
|
String
|
|
Str</programlisting>
|
|
|
|
<para>Because 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 only 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, you create 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, as with a class, you can
|
|
create many object instances 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
|
|
powerful and flexible in that you can <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 five scopes, three of which are available only
|
|
if you use a web-aware
|
|
<interfacename>ApplicationContext</interfacename>.</para>
|
|
|
|
<para>The following scopes are supported out of the box. You can also
|
|
create <link linkend="beans-factory-scopes-custom">a custom
|
|
scope.</link></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 HTTP request has 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-session">session</link>
|
|
</para></entry>
|
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of
|
|
an 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>
|
|
|
|
<note>
|
|
<title>Thread-scoped beans</title>
|
|
|
|
<para>As of Spring 3.0, a <emphasis>thread scope</emphasis> is
|
|
available, but is not registered by default. For more information, see
|
|
the documentation for <ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/SimpleThreadScope.html">SimpleThreadScope</ulink>.
|
|
For instructions on how to register this or any other custom scope, see
|
|
<xref linkend="beans-factory-scopes-custom-using" />.</para>
|
|
</note>
|
|
|
|
<section id="beans-factory-scopes-singleton">
|
|
<title>The singleton scope</title>
|
|
|
|
<para>Only one <emphasis>shared</emphasis> instance of a singleton bean
|
|
is managed, and all requests for beans with an id or ids matching that
|
|
bean definition 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, the Spring IoC container creates
|
|
<emphasis>exactly one</emphasis> instance of the object defined by that
|
|
bean definition. This single instance is stored in a cache of such
|
|
singleton beans, and <emphasis>all subsequent requests and
|
|
references</emphasis> for that named bean return the cached
|
|
object.</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>Spring's concept of a singleton bean differs from the Singleton
|
|
pattern as defined in the 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 is 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 creates
|
|
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, for example:</para>
|
|
|
|
<programlisting language="xml"><bean id="accountService" class="com.foo.DefaultAccountService"/>
|
|
|
|
<lineannotation><!-- the following is equivalent, though redundant (singleton scope is the default) --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/></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, the bean is injected
|
|
into another bean or you request it through a
|
|
<literal>getBean()</literal> method call on the container. As a rule,
|
|
use the prototype scope for all stateful beans and the singleton scope
|
|
for stateless beans.</para>
|
|
|
|
<para>The following diagram illustrates the Spring prototype scope.
|
|
<emphasis>A data access object (DAO) is not typically configured as a
|
|
prototype, because a typical DAO does not hold any conversational state;
|
|
it was just easier for this author to reuse the core of the singleton
|
|
diagram.</emphasis><!--First it says diagram illustrates scope, but then says it's not typical of a prototype scope. Why not use realistic one? --></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>The following example defines a bean as a prototype in XML:</para>
|
|
|
|
<programlisting language="xml"><lineannotation><!-- using <literal>spring-beans-2.0.dtd</literal> --></lineannotation>
|
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/></programlisting>
|
|
|
|
<para>In contrast to the other scopes, Spring does not manage the
|
|
complete lifecycle of a prototype bean: the container instantiates,
|
|
configures, and otherwise assembles a prototype object, and hands it to
|
|
the client, with no further record of that prototype instance. Thus,
|
|
although <emphasis>initialization</emphasis> lifecycle callback methods
|
|
are called on all objects regardless of scope, in the case of
|
|
prototypes, configured <emphasis>destruction</emphasis> lifecycle
|
|
callbacks are <emphasis>not</emphasis> called. The client code must
|
|
clean up prototype-scoped objects and release expensive resources that
|
|
the prototype bean(s) are holding. To get the Spring container to
|
|
release resources held by prototype-scoped beans, try using a custom
|
|
<link linkend="beans-factory-extension-bpp">bean post-processor</link>,
|
|
which holds a reference to beans that need to be cleaned up.</para>
|
|
|
|
<para>In some respects, the Spring container's role in regard to a
|
|
prototype-scoped bean is a replacement for the Java
|
|
<literal>new</literal> operator. All lifecycle management past that
|
|
point must be handled by the client. (For details on the lifecycle of a
|
|
bean in the Spring container, see <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 you use singleton-scoped beans with dependencies on prototype
|
|
beans, be aware that <emphasis>dependencies are resolved at
|
|
instantiation time</emphasis>. Thus if you dependency-inject a
|
|
prototype-scoped bean into a singleton-scoped bean, a new prototype bean
|
|
is instantiated and then dependency-injected into the singleton bean.
|
|
The prototype instance is the sole instance that is ever supplied to the
|
|
singleton-scoped bean.</para>
|
|
|
|
<para>However, suppose you want the singleton-scoped bean to acquire a
|
|
new instance of the prototype-scoped bean repeatedly at runtime. You
|
|
cannot dependency-inject a prototype-scoped bean into your singleton
|
|
bean, because that injection occurs only <emphasis>once</emphasis>, when
|
|
the Spring container is instantiating the singleton bean and resolving
|
|
and injecting its dependencies. If you need a new instance of a
|
|
prototype bean at runtime more than once, see <xref
|
|
linkend="beans-factory-method-injection" /></para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-other">
|
|
<title>Request, session, and global session scopes</title>
|
|
|
|
<para>The <literal>request</literal>, <literal>session</literal>, and
|
|
<literal>global session</literal> scopes are <emphasis>only</emphasis>
|
|
available if you use a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename> implementation (such
|
|
as <classname>XmlWebApplicationContext</classname>). If you use these
|
|
scopes with regular Spring IoC containers such as the
|
|
<classname>ClassPathXmlApplicationContext</classname>, you get an
|
|
<classname>IllegalStateException</classname> complaining about an
|
|
unknown bean scope.</para>
|
|
|
|
<section id="beans-factory-scopes-other-web-configuration">
|
|
<title>Initial web configuration</title>
|
|
|
|
<para>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 define your beans.
|
|
(This initial setup is <emphasis>not</emphasis> required for the
|
|
standard scopes, singleton and prototype.)</para>
|
|
|
|
<para>How you accomplish this initial setup depends on your particular
|
|
Servlet environment..</para>
|
|
|
|
<para>If you access scoped beans within Spring Web MVC, in effect,
|
|
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>If you use a Servlet 2.4+ web container, with requests processed
|
|
outside of Spring's DispatcherServlet (for example, when using JSF or
|
|
Struts), you need to add the following
|
|
<interfacename>javax.servlet.ServletRequestListener</interfacename> to
|
|
the declarations in your web applications <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 use an older web container (Servlet 2.3), use the
|
|
provided <interfacename>javax.servlet.Filter</interfacename>
|
|
implementation. The following snippet of XML configuration must be
|
|
included in the <literal>web.xml</literal> file of your web
|
|
application if you want to access 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, so
|
|
you must 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><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>Request scope</title>
|
|
|
|
<para>Consider the following bean definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="loginAction" class="com.foo.LoginAction" scope="request"/></programlisting>
|
|
|
|
<para>The Spring container creates a new instance of the
|
|
<classname>LoginAction</classname> bean by using the
|
|
<literal>loginAction</literal> bean definition for each and every HTTP
|
|
request. That is, the <literal>loginAction</literal> bean is scoped at
|
|
the HTTP request level. You can change the internal state of the
|
|
instance that is created as much as you want, because other instances
|
|
created from the same <literal>loginAction</literal> bean definition
|
|
will not see these changes in state; they are particular to an
|
|
individual request. When the request completes processing, the bean
|
|
that is scoped to the request is discarded.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-session">
|
|
<title>Session scope</title>
|
|
|
|
<para>Consider the following bean definition:</para>
|
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/></programlisting>
|
|
|
|
<para>The Spring container creates a new instance of the
|
|
<classname>UserPreferences</classname> bean by 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 is effectively scoped at
|
|
the HTTP <interfacename>Session</interfacename> level. As with
|
|
<literal>request-scoped</literal> beans, you can change the internal
|
|
state of the instance that is created as much as you want, knowing
|
|
that other HTTP <interfacename>Session</interfacename> instances that
|
|
are also using instances created from the same
|
|
<literal>userPreferences</literal> bean definition do not see these
|
|
changes in state, because 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> is also discarded.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-global-session">
|
|
<title>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 above</link>), and
|
|
applies only in the context of portlet-based web applications. The
|
|
portlet specification defines the notion of a global
|
|
<interfacename>Session</interfacename> that is shared among all
|
|
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>If you write 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
|
|
is used, and no error is raised.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-other-injection">
|
|
<title>Scoped beans as dependencies</title>
|
|
|
|
<para>The Spring IoC container manages not only the instantiation of
|
|
your objects (beans), but also the wiring up of collaborators (or
|
|
dependencies). If you want to inject (for example) an HTTP request
|
|
scoped bean into another bean, you must 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 can
|
|
also retrieve the real, target object from the relevant scope (for
|
|
example, an 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>. If you try to create a scoped proxy
|
|
for a singleton bean, the
|
|
<exceptionname>BeanCreationException</exceptionname> is
|
|
raised.</para>
|
|
</note>
|
|
|
|
<para>The configuration in the following example is only one line, but
|
|
it is important to understand the <quote>why</quote> as well as the
|
|
<quote>how</quote> behind it.</para>
|
|
|
|
<!--What is this example supposed to show?-->
|
|
|
|
<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><!-- an 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 insert a child
|
|
<literal><aop:scoped-proxy/></literal> element into a scoped
|
|
bean definition. <!--To create what such proxy? Is the proxy created above? Also, below added an x-ref that seems relevant.-->(If
|
|
you choose class-based proxying, you also need the CGLIB library in
|
|
your classpath. See <xref
|
|
linkend="beans-factory-scopes-other-injection-proxies" /> and <xref
|
|
linkend="xsd-config" />.) Why do definitions of beans scoped at the
|
|
<literal>request</literal>, <literal>session</literal>,
|
|
<literal>globalSession</literal> and custom-scope levels require the
|
|
<literal><aop:scoped-proxy/></literal> element ? Let's examine
|
|
the following singleton bean definition and contrast it with what you
|
|
need to define for the aforementioned scopes. (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>In the preceding example, the singleton bean
|
|
<literal>userManager</literal> is 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) are also injected only once.
|
|
This means that the <literal>userManager</literal> bean will only
|
|
operate on the exact same <literal>userPreferences</literal> object,
|
|
that is, the one that it was originally injected with.</para>
|
|
|
|
<!-- MLP: Beverly to review paragraph -->
|
|
|
|
<para>This is <emphasis>not</emphasis> the behavior you want when
|
|
injecting a shorter-lived scoped bean into a longer-lived scoped bean,
|
|
for example injecting an HTTP
|
|
<interfacename>Session</interfacename>-scoped collaborating bean as a
|
|
dependency into singleton bean. Rather, you need a single
|
|
<literal>userManager</literal> object, and for the lifetime of an HTTP
|
|
<interfacename>Session</interfacename>, you need a
|
|
<literal>userPreferences</literal> object that is specific to said
|
|
HTTP <interfacename>Session</interfacename>. Thus the container
|
|
creates an 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) which can fetch the real
|
|
<classname>UserPreferences</classname> object from the scoping
|
|
mechanism (HTTP request, <interfacename>Session</interfacename>,
|
|
etc.). The container injects this proxy object into the
|
|
<literal>userManager</literal> bean, which is unaware that this
|
|
<classname>UserPreferences</classname> reference is a proxy. In this
|
|
example, when a <interfacename>UserManager</interfacename> instance
|
|
invokes a method on the dependency-injected
|
|
<classname>UserPreferences</classname> object, it actually is invoking
|
|
a method on the proxy. The proxy then fetches the real
|
|
<classname>UserPreferences</classname> object from (in this case) the
|
|
HTTP <interfacename>Session</interfacename>, and delegates the method
|
|
invocation onto the retrieved real
|
|
<classname>UserPreferences</classname> object.</para>
|
|
|
|
<para>Thus 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 to create</title>
|
|
|
|
<para>By default, when the Spring container creates a proxy for a
|
|
bean that is marked up with the
|
|
<literal><aop:scoped-proxy/></literal> element, <emphasis>a
|
|
CGLIB-based class proxy is created</emphasis>. This means that you
|
|
need to have the CGLIB library in the classpath of your
|
|
application.</para>
|
|
|
|
<para><emphasis>Note: CGLIB proxies 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>Alternatively, you can configure the Spring container to
|
|
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 means that you do not need additional
|
|
libraries in your application classpath to effect such proxying.
|
|
However, it also means that the class of the scoped bean must
|
|
implement at least one interface, and <emphasis>that all</emphasis>
|
|
collaborators into which the scoped bean is injected must reference
|
|
the bean through 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>For more detailed information about choosing class-based or
|
|
interface-based proxying, see <xref
|
|
linkend="aop-proxying" />.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-factory-scopes-custom">
|
|
<title>Custom scopes</title>
|
|
|
|
<para>As of Spring 2.0, the bean scoping mechanism is extensible. You
|
|
can define your own scopes, or even redefine existing scopes, although
|
|
the latter is considered bad practice and 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 a custom scope</title>
|
|
|
|
<para>To integrate your custom scope(s) into the Spring container, you
|
|
need to implement the
|
|
<interfacename>org.springframework.beans.factory.config.Scope</interfacename>
|
|
interface, which is described in this section. For an idea of how to
|
|
implement your own scopes, see the
|
|
<interfacename>Scope</interfacename> implementations that are supplied
|
|
with the Spring Framework itself and the <ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Scope.html">Scope
|
|
Javadoc</ulink>, which explains the methods you need to implement in
|
|
more detail.</para>
|
|
|
|
<para>The <literal>Scope</literal> interface has four methods to get
|
|
objects from the scope, remove them from the scope, and allow them to
|
|
be destroyed.</para>
|
|
|
|
<para>The following method returns the object from the underlying
|
|
scope. The session scope implementation, for example, returns the
|
|
session-scoped bean (and if it does not exist, the method returns a
|
|
new instance of the bean, after having bound it to the session for
|
|
future reference).<!--How can it return a a new instance of a bean that doesn't exist? Revise to clarify.--></para>
|
|
|
|
<programlisting language="java">Object get(String name, ObjectFactory objectFactory)</programlisting>
|
|
|
|
<para>The following method removes 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, but you can return null if the object with the specified
|
|
name is not found.</para>
|
|
|
|
<programlisting language="java">Object remove(String name)</programlisting>
|
|
|
|
<para>The following method registers the callbacks the scope should
|
|
execute when it is destroyed or when the specified object in the scope
|
|
is destroyed. 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 following method obtains the conversation identifier for the
|
|
underlying scope. This identifier is different for each scope. For a
|
|
session scoped implementation, this identifier 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 write and test one or more custom
|
|
<interfacename>Scope</interfacename> implementations, you 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.</para>
|
|
|
|
<programlisting language="java">void registerScope(String scopeName, Scope scope);</programlisting>
|
|
|
|
<para>This method is declared on the
|
|
<interfacename>ConfigurableBeanFactory</interfacename> interface,
|
|
which is available on most of the concrete
|
|
<interfacename>ApplicationContext</interfacename> implementations that
|
|
ship with Spring via the BeanFactory property.</para>
|
|
|
|
<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>Suppose that you write your custom
|
|
<interfacename>Scope</interfacename> implementation, and then register
|
|
it as below.</para>
|
|
|
|
<note>
|
|
<para>The example below uses <literal>SimpleThreadScope</literal>
|
|
which is included with Spring, but not registered by default. The
|
|
instructions would be the same for your own custom
|
|
<literal>Scope</literal> implementations.</para>
|
|
</note>
|
|
|
|
<programlisting language="java">
|
|
Scope threadScope = new SimpleThreadScope();
|
|
beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope);</programlisting>
|
|
|
|
<para>You then create bean definitions that adhere to the scoping
|
|
rules of your custom <interfacename>Scope</interfacename>:</para>
|
|
|
|
<programlisting language="xml"><bean id="..." class="..." scope="thread"></programlisting>
|
|
|
|
<para>With a custom <interfacename>Scope</interfacename>
|
|
implementation, you are not limited to programmatic registration of
|
|
the scope. You can also do the <interfacename>Scope</interfacename>
|
|
registration declaratively, using the
|
|
<classname>CustomScopeConfigurer</classname> 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: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="org.springframework.context.support.SimpleThreadScope"/>
|
|
</entry></emphasis>
|
|
</map>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="bar" class="x.y.Bar" scope="thread">
|
|
<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>When you place <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>
|
|
|
|
<!-- MLP Beverly to review: Old Text: The Spring Framework provides several callback interfaces to
|
|
change the behavior of your bean in the container; they include -->
|
|
|
|
<para>To interact with the container's management of the bean lifecycle,
|
|
you can implement the Spring
|
|
<interfacename>InitializingBean</interfacename> and
|
|
<interfacename>DisposableBean</interfacename> interfaces. The container
|
|
calls <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 of your
|
|
beans. You can also achieve the same integration with the container
|
|
without coupling your classes to Spring interfaces though the use of
|
|
init-method and destroy method object definition metadata.</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
|
|
does not offer out-of-the-box, you can implement a
|
|
<interfacename>BeanPostProcessor</interfacename> yourself. For more
|
|
information, see <xref linkend="beans-factory-extension" />.</para>
|
|
|
|
<para>In addition to the initialization and destruction callbacks,
|
|
Spring-managed objects may also implement the
|
|
<interfacename>Lifecycle</interfacename> interface so that those
|
|
objects can participate in the startup and shutdown process as
|
|
driven by the container's own lifecycle.</para>
|
|
|
|
<para>The lifecycle callback interfaces are described in this
|
|
section.</para>
|
|
|
|
<section id="beans-factory-lifecycle-initializingbean">
|
|
<title>Initialization callbacks</title>
|
|
|
|
<para>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 a
|
|
single method:</para>
|
|
|
|
<programlisting language="java">void afterPropertiesSet() throws Exception;</programlisting>
|
|
|
|
<para>It is recommended that you do not use the
|
|
<interfacename>InitializingBean</interfacename> interface because it
|
|
unnecessarily couples the code to Spring. Alternatively, specify a
|
|
POJO initialization method. In the case of XML-based configuration
|
|
metadata, you use the <literal>init-method</literal> attribute to
|
|
specify the name of the method that has a void no-argument signature.
|
|
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>It is recommended that you do not use the
|
|
<interfacename>DisposableBean</interfacename> callback interface
|
|
because it unnecessarily couples the code to Spring. Alternatively,
|
|
specify a generic method that is supported by bean definitions. With
|
|
XML-based configuration metadata, you use 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 and destroy methods</title>
|
|
|
|
<para>When you write initialization and destroy method callbacks that
|
|
do not use the Spring-specific
|
|
<interfacename>InitializingBean</interfacename> and
|
|
<interfacename>DisposableBean</interfacename> callback interfaces, you
|
|
typically write methods with names such as <literal>init()</literal>,
|
|
<literal>initialize()</literal>, <literal>dispose()</literal>, and so
|
|
on. Ideally, the names of such lifecycle callback methods are
|
|
standardized across a project so that all developers use the same
|
|
method names and ensure consistency.</para>
|
|
|
|
<para>You can configure the Spring container 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 write your application classes and
|
|
use an initialization callback called <literal>init()</literal>,
|
|
without having to configure an <literal>init-method="init"</literal>
|
|
attribute with each bean definition. The Spring IoC container calls
|
|
that method when the bean is created (and in accordance with the
|
|
standard lifecycle callback contract described previously). This
|
|
feature also enforces a consistent naming convention for
|
|
initialization and destroy method callbacks.</para>
|
|
|
|
<para>Suppose that your initialization callback methods are named
|
|
<literal>init()</literal> and destroy callback methods are named
|
|
<literal>destroy()</literal>. Your class will resemble the class in
|
|
the following example.</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>The presence of the <literal>default-init-method</literal>
|
|
attribute on the top-level <literal><beans/></literal> element
|
|
attribute causes the Spring IoC container to recognize a method called
|
|
<literal>init</literal> on beans as the initialization method
|
|
callback. When a bean is created and assembled, if the beans class has
|
|
such a method, it is invoked at the appropriate time.</para>
|
|
|
|
<para>You configure destroy method callbacks similarly (in XML, that
|
|
is) by using the <literal>default-destroy-method</literal> attribute
|
|
on the top-level <literal><beans/></literal> element.</para>
|
|
|
|
<para>Where existing bean classes already have callback methods that
|
|
are named at variance with the convention, you can override the
|
|
default by specifying (in XML, that is) the method name using the
|
|
<literal>init-method</literal> and <literal>destroy-method</literal>
|
|
attributes of the <bean/> itself.</para>
|
|
|
|
<para>The Spring container guarantees that a configured initialization
|
|
callback is called immediately after a bean is supplied with all
|
|
dependencies. Thus the initialization callback is called on the raw
|
|
bean reference, which means that AOP interceptors and so forth are not
|
|
yet applied to the bean. A target bean is fully created
|
|
<emphasis>first</emphasis>, <emphasis>then</emphasis> an AOP proxy
|
|
(for example) with its interceptor chain is applied. 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
|
|
inconsistent to apply the interceptors to the init method, because
|
|
doing so would couple the lifecycle of the target bean with its
|
|
proxy/interceptors and leave strange semantics when your code
|
|
interacts directly to the raw target bean.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-lifecycle-combined-effects">
|
|
<title>Combining lifecycle mechanisms</title>
|
|
|
|
<para>As of Spring 2.5, you have 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>. You
|
|
can combine these mechanisms to control a given bean.</para>
|
|
|
|
<note>
|
|
<para>If multiple lifecycle mechanisms are configured for a bean,
|
|
and each mechanism is configured with a different method name, then
|
|
each configured method is executed in the order listed below.
|
|
However, if the same method name is configured - for example,
|
|
<literal>init()</literal> for an initialization method - for more
|
|
than one of these lifecycle mechanisms, that method is executed
|
|
once, as explained in the preceding section.</para>
|
|
</note>
|
|
|
|
<para>Multiple lifecycle mechanisms configured for the same bean, with
|
|
different initialization methods, are called as follows:</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>
|
|
</section>
|
|
|
|
<section id="beans-factory-lifecycle-processor">
|
|
<title>Startup and shutdown callbacks</title>
|
|
|
|
<para>The <interfacename>Lifecycle</interfacename> interface defines
|
|
the essential methods for any object that has its own lifecycle
|
|
requirements (e.g. starts and stops some background process):</para>
|
|
|
|
<programlisting language="java">public interface Lifecycle {
|
|
|
|
void start();
|
|
|
|
void stop();
|
|
|
|
boolean isRunning();
|
|
|
|
}</programlisting>
|
|
|
|
<para>Any Spring-managed object may implement that interface. Then,
|
|
when the ApplicationContext itself starts and stops, it will cascade
|
|
those calls to all Lifecycle implementations defined within that context.
|
|
It does this by delegating to a <interfacename>LifecycleProcessor</interfacename>:
|
|
</para>
|
|
|
|
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle {
|
|
|
|
void onRefresh();
|
|
|
|
void onClose();
|
|
|
|
}</programlisting>
|
|
|
|
<para>Notice that the <interfacename>LifecycleProcessor</interfacename>
|
|
is itself an extension of the <interfacename>Lifecycle</interfacename>
|
|
interface. It also adds two other methods for reacting to the context
|
|
being refreshed and closed.</para>
|
|
|
|
<para>The order of startup and shutdown invocations can be important.
|
|
If a "depends-on" relationship exists between any two objects, the
|
|
dependent side will start <emphasis>after</emphasis> its dependency,
|
|
and it will stop <emphasis>before</emphasis> its dependency. However,
|
|
at times the direct dependencies are unknown. You may only know that
|
|
objects of a certain type should start prior to objects of another
|
|
type. In those cases, the <interfacename>SmartLifecycle</interfacename>
|
|
interface defines another option, namely the <methodname>getPhase()</methodname>
|
|
method as defined on its super-interface, <interfacename>Phased</interfacename>.
|
|
</para>
|
|
|
|
<programlisting language="java">public interface Phased {
|
|
|
|
int getPhase();
|
|
|
|
}
|
|
|
|
|
|
public interface SmartLifecycle extends Lifecycle, Phased {
|
|
|
|
boolean isAutoStartup();
|
|
|
|
void stop(Runnable callback);
|
|
|
|
}</programlisting>
|
|
|
|
<para>When starting, the objects with the lowest phase start first, and
|
|
when stopping, the reverse order is followed. Therefore, an object that
|
|
implements <interfacename>SmartLifecycle</interfacename> and whose getPhase()
|
|
method returns <literal>Integer.MIN_VALUE</literal> would be among the first
|
|
to start and the last to stop. At the other end of the spectrum, a phase
|
|
value of <literal>Integer.MAX_VALUE</literal> would indicate that the
|
|
object should be started last and stopped first (likely because it
|
|
depends on other processes to be running). When considering the phase value,
|
|
it's also important to know that the default phase for any "normal"
|
|
<interfacename>Lifecycle</interfacename> object that does not implement
|
|
<interfacename>SmartLifecycle</interfacename> would be 0. Therefore, any
|
|
negative phase value would indicate that an object should start before
|
|
those standard components (and stop after them), and vice versa for any
|
|
positive phase value.</para>
|
|
|
|
<para>As you can see the stop method defined by <interfacename>SmartLifecycle</interfacename>
|
|
accepts a callback. Any implementation <emphasis>must</emphasis> invoke that
|
|
callback's run() method after that implementation's shutdown process is complete.
|
|
That enables asynchronous shutdown where necessary since the default
|
|
implementation of the <interfacename>LifecycleProcessor</interfacename>
|
|
interface, <classname>DefaultLifecycleProcessor</classname>, will wait
|
|
up to its timeout value for the group of objects within each phase to
|
|
invoke that callback. The default per-phase timeout is 30 seconds. You
|
|
can override the default lifecycle processor instance by defining a bean
|
|
named "lifecycleProcessor" within the context. If you only want to modify
|
|
the timeout, then defining the following would be sufficient:</para>
|
|
|
|
<programlisting language="xml"><![CDATA[<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
|
|
<!-- timeout value in milliseconds -->
|
|
<property name="timeoutPerShutdownPhase" value="10000"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename> interface
|
|
defines callback methods for the refreshing and closing of the context as well. The
|
|
latter will simply drive the shutdown process as if stop() had been called explicitly,
|
|
but it will happen when the context is closing. The 'refresh' callback on the other
|
|
hand enables another feature of <interfacename>SmartLifecycle</interfacename> beans.
|
|
When the context is refreshed (after all objects have been instantiated and initialized),
|
|
that callback will be invoked, and at that point the default lifecycle processor will
|
|
check the boolean value returned by each <interfacename>SmartLifecycle</interfacename>
|
|
object's <methodname>isAutoStartup()</methodname> method. If "true", then that object
|
|
will be started at that point rather than waiting for an explicit invocation of the
|
|
context's or its own start() method (unlike the context refresh, the context start does
|
|
not happen automatically for a standard context implementation). The "phase" value as
|
|
well as any "depends-on" relationships will determine the startup order in the same way
|
|
as described above.</para>
|
|
</section>
|
|
|
|
<section id="beans-factory-shutdown">
|
|
<title>Shutting down the Spring IoC container gracefully in non-web
|
|
applications</title>
|
|
|
|
<note>
|
|
<para>This section applies only to non-web applications. Spring's
|
|
web-based <interfacename>ApplicationContext</interfacename>
|
|
implementations already have code in place to shut down the Spring
|
|
IoC container gracefully when the relevant web application is shut
|
|
down.</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; you
|
|
register a shutdown hook with the JVM. Doing so ensures a graceful
|
|
shutdown and calls the relevant destroy methods on your singleton
|
|
beans so that all resources are released. Of course, you must still
|
|
configure and implement these destroy callbacks correctly.</para>
|
|
|
|
<para>To register a shutdown hook, you call the
|
|
<methodname>registerShutdownHook()</methodname> method that is
|
|
declared on the <classname>AbstractApplicationContext</classname>
|
|
class:</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><interfacename>ApplicationContextAware</interfacename> and
|
|
<interfacename>BeanNameAware</interfacename></title>
|
|
|
|
<para>When an <interfacename>ApplicationContext</interfacename> creates
|
|
a class that implements the
|
|
<interfacename>org.springframework.contxt.ApplicationContextAware</interfacename>
|
|
interface, the class is provided with a reference to that
|
|
<interfacename>ApplicationContext</interfacename>.</para>
|
|
|
|
<programlisting language="java">public interface ApplicationContextAware {
|
|
|
|
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
|
|
}</programlisting>
|
|
|
|
<para>Thus beans can manipulate programmatically the
|
|
<interfacename>ApplicationContext</interfacename> that created them,
|
|
through the <interfacename>ApplicationContext</interfacename> interface,
|
|
or by casting the reference to a known subclass of this interface, such
|
|
as <classname>ConfigurableApplicationContext</classname>, which exposes
|
|
additional functionality. One use would be the programmatic retrieval of
|
|
other beans. Sometimes this capability is useful; however, in general
|
|
you should avoid it, because it couples the code to Spring and does not
|
|
follow the Inversion of Control style, where collaborators are provided
|
|
to beans as properties. Other methods of the ApplicationContext provide
|
|
access to file resources, publishing application events, and accessing a
|
|
MessageSource. These additional features are described in <xref
|
|
linkend="context-introduction" /></para>
|
|
|
|
<para>As of Spring 2.5, autowiring is another alternative to obtain
|
|
reference to the <interfacename>ApplicationContext</interfacename>. The
|
|
"traditional" <literal>constructor</literal> and
|
|
<literal>byType</literal> autowiring modes (as described in <xref
|
|
linkend="beans-factory-autowire" />) can provide a dependency of type
|
|
<interfacename>ApplicationContext</interfacename> for a constructor
|
|
argument or setter method parameter, respectively. For more flexibility,
|
|
including the ability to autowire fields and multiple parameter methods,
|
|
use the new annotation-based autowiring features. If you do, the
|
|
<interfacename>ApplicationFactory</interfacename> is autowired into a
|
|
field, constructor argument, or method parameter that is expecting the
|
|
<interfacename>BeanFactory</interfacename> type if the field,
|
|
constructor, or method in question carries the
|
|
<interfacename>@Autowired</interfacename> annotation. For more
|
|
information, see <xref linkend="beans-autowired-annotation" />.</para>
|
|
|
|
<para>When an ApplicationContext creates a class that implements the
|
|
<interfacename>org.springframework.beans.factory.BeanNameAware</interfacename>
|
|
interface, the class is provided with a reference to the name defined in
|
|
its associated object definition.</para>
|
|
|
|
<programlisting language="java">public interface BeanNameAware {
|
|
|
|
void setBeanName(string name) throws BeansException;
|
|
}</programlisting>
|
|
|
|
<para>The callback is invoked after population of normal bean properties
|
|
but before an initialization callback such as
|
|
<interfacename>InitializingBean</interfacename>s
|
|
<emphasis>afterPropertiesSet</emphasis> or a custom init-method.</para>
|
|
</section>
|
|
|
|
<section id="aware-list">
|
|
<title>Other <interfacename>Aware</interfacename> interfaces</title>
|
|
|
|
<para>Besides <interfacename>ApplicationContextAware</interfacename> and
|
|
<interfacename>BeanNameAware</interfacename> discussed above, Spring offers a range
|
|
of <emphasis><interfacename>Aware</interfacename></emphasis> interfaces that allow beans
|
|
to indicate to the container that they require a certain <emphasis>infrastructure</emphasis> dependency.
|
|
The most important <interfacename>Aware</interfacename> interfaces are summarized below - as a general rule,
|
|
the name is a good indication of the dependency type:</para>
|
|
|
|
<table id="beans-factory-nature-aware-list" pgwide="1">
|
|
<title><interfacename>Aware</interfacename> interfaces</title>
|
|
|
|
<tgroup cols="3">
|
|
<colspec align="left" />
|
|
|
|
<thead>
|
|
<row>
|
|
<entry>Name</entry>
|
|
<entry>Injected Dependency</entry>
|
|
<entry>Explained in...</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><para><classname>ApplicationContextAware</classname></para></entry>
|
|
<entry><para>Declaring <interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>ApplicationEventPublisherAware</classname></para></entry>
|
|
<entry><para>Event publisher of the enclosing <interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="context-introduction"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>BeanClassLoaderAware</classname></para></entry>
|
|
<entry><para>Class loader used to load the bean classes.</para></entry>
|
|
<entry><para><xref linkend="beans-factory-class"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>BeanFactoryAware</classname></para></entry>
|
|
<entry><para>Declaring <interfacename>BeanFactory</interfacename></para></entry>
|
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>BeanNameAware</classname></para></entry>
|
|
<entry><para>Name of the declaring bean</para></entry>
|
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>BootstrapContextAware</classname></para></entry>
|
|
<entry><para>Resource adapter <interfacename>BootstrapContext</interfacename> the container runs in. Typically available only
|
|
in JCA aware <interfacename>ApplicationContext</interfacename>s</para></entry>
|
|
<entry><para><xref linkend="cci"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>LoadTimeWeaverAware</classname></para></entry>
|
|
<entry><para>Defined <emphasis>weaver</emphasis> for processing class definition at load time</para></entry>
|
|
<entry><para><xref linkend="aop-aj-ltw"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>MessageSourceAware</classname></para></entry>
|
|
<entry><para>Configured strategy for resolving messages (with support for parametrization and internationalization)</para></entry>
|
|
<entry><para><xref linkend="context-introduction"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>NotificationPublisherAware</classname></para></entry>
|
|
<entry><para>Spring JMX notification publisher</para></entry>
|
|
<entry><para><xref linkend="jmx-notifications"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>PortletConfigAware</classname></para></entry>
|
|
<entry><para>Current <interfacename>PortletConfig</interfacename> the container runs in. Valid only in a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="portlet"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>PortletContextAware</classname></para></entry>
|
|
<entry><para>Current <interfacename>PortletContext</interfacename> the container runs in. Valid only in a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="portlet"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>ResourceLoaderAware</classname></para></entry>
|
|
<entry><para>Configured loader for low-level access to resources</para></entry>
|
|
<entry><para><xref linkend="resources"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>ServletConfigAware</classname></para></entry>
|
|
<entry><para>Current <interfacename>ServletConfig</interfacename> the container runs in. Valid only in a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="mvc"/></para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para><classname>ServletContextAware</classname></para></entry>
|
|
<entry><para>Current <interfacename>ServletContext</interfacename> the container runs in. Valid only in a web-aware Spring
|
|
<interfacename>ApplicationContext</interfacename></para></entry>
|
|
<entry><para><xref linkend="mvc"/></para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>Note again that usage of these interfaces ties your code to the Spring API and does not follow the Inversion of Control
|
|
style. As such, they are recommended for infrastructure beans that require programmatic access to the container.</para>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-child-bean-definitions">
|
|
<title>Bean definition inheritance</title>
|
|
|
|
<para>A bean definition can contain a lot of configuration information,
|
|
including constructor arguments, property values, and container-specific
|
|
information such as initialization method, static factory method name, and
|
|
so on. A child bean definition inherits configuration data from a parent
|
|
definition. The child definition can override some values, or add others,
|
|
as needed. Using parent and child bean definitions can save a lot of
|
|
typing. Effectively, this is a form of templating.</para>
|
|
|
|
<para>If you work with an
|
|
<interfacename>ApplicationContext</interfacename> interface
|
|
programmatically, child bean definitions are represented by the
|
|
<classname>ChildBeanDefinition</classname> class. Most users do not work
|
|
with them on this level, instead configuring bean definitions
|
|
declaratively in something like the
|
|
<classname>ClassPathXmlApplicationContext</classname>. When you use
|
|
XML-based configuration metadata, you indicate a child bean definition 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 uses 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 inherits constructor argument values,
|
|
property values, and method overrides from the parent, with the option to
|
|
add new values. Any initialization method, destroy method, and/or
|
|
<literal>static</literal> factory method settings that you specify will
|
|
override the corresponding parent settings.</para>
|
|
|
|
<para>The remaining settings are <emphasis>always</emphasis> 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>The preceding example explicitly marks the parent bean definition as
|
|
abstract by using the <literal>abstract</literal> attribute. If the parent
|
|
definition does not specify a class, explicitly marking the parent bean
|
|
definition as <literal>abstract</literal> is required, as follows:</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 be instantiated on its own because it is
|
|
incomplete, and it is also explicitly marked as
|
|
<literal>abstract</literal>. When a definition is
|
|
<literal>abstract</literal> like this, it is usable only as a pure
|
|
template bean definition that serves 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, returns an error. Similarly, the container's internal
|
|
<methodname>preInstantiateSingletons()</methodname> method ignores bean
|
|
definitions that are defined as abstract.</para>
|
|
|
|
<note>
|
|
<para><literal>ApplicationContext</literal> pre-instantiates all
|
|
singletons by default. 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>Typically, an application developer does not need to subclass any
|
|
<interfacename>ApplicationContext</interfacename> implementation classes.
|
|
You can extend The Spring IoC container infinitely by plugging in
|
|
implementations of special integration interfaces. The next few sections
|
|
describe these integration interfaces.</para>
|
|
|
|
<section id="beans-factory-extension-bpp">
|
|
<title>Customizing beans using the
|
|
<interfacename>BeanPostProcessor</interfacename> Interface <literal>
|
|
</literal></title>
|
|
|
|
<para>The <interfacename>BeanPostProcessor</interfacename> interface
|
|
defines <firstterm>callback methods</firstterm> that you can implement
|
|
to provide your own (or override the container's default) instantiation
|
|
logic, dependency-resolution logic, and so forth. If you want to
|
|
implement some custom logic after the Spring container finishes
|
|
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>BeanPostProcessor</literal>
|
|
interfaces. You can control the order in which these
|
|
<literal>BeanPostProcessor</literal> interfaces execute by setting the
|
|
<literal>order</literal> property. You can set this property only 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.
|
|
For more details, consult the Javadoc for the
|
|
<interfacename>BeanPostProcessor</interfacename> and
|
|
<interfacename>Ordered</interfacename> interfaces.</para>
|
|
|
|
<note>
|
|
<para><literal>BeanPostProcessor</literal>s operate on bean (or
|
|
object) <emphasis>instances</emphasis>; that is to say, the Spring IoC
|
|
container instantiates a bean instance and <emphasis>then</emphasis>
|
|
<literal>BeanPostProcessor</literal> interfaces do their work.</para>
|
|
|
|
<para><literal>BeanPostProcessor</literal> interfaces 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 work on the beans in that
|
|
container. Beans that are defined in one container are not
|
|
post-processed by a <literal>BeanPostProcessor</literal> in another
|
|
container, even if both containers are part of the same
|
|
hierarchy.</para>
|
|
|
|
<para>To change the actual bean definition (that is, the recipe that
|
|
defines the bean), you instead need to use a
|
|
<interfacename>BeanFactoryPostProcessor</interfacename>, described
|
|
below in <xref
|
|
linkend="beans-factory-extension-factory-postprocessors" />.</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, for each bean
|
|
instance that is created by the container, the post-processor gets a
|
|
callback from the container both <emphasis>before</emphasis> container
|
|
initialization methods (such as <emphasis>afterPropertiesSet</emphasis>
|
|
and any declared init method) are called, and also afterwards. The
|
|
post-processor can take any action with the bean instance, including
|
|
ignoring the callback completely. A bean post-processor typically checks
|
|
for callback interfaces, or may wrap a bean with a proxy. Some Spring
|
|
AOP infrastructure classes are implemented as bean post-processors and
|
|
they do this proxy-wrapping logic.</para>
|
|
|
|
<para>An <interfacename>ApplicationContext</interfacename>
|
|
<emphasis>automatically detects</emphasis> any beans that are defined in
|
|
the configuration metadata it receives that implement the
|
|
<interfacename>BeanPostProcessor</interfacename> interface. The
|
|
<interfacename>ApplicationContext</interfacename> registers these beans
|
|
as post-processors, to be then called appropriately by the container
|
|
upon bean creation. You can then deploy the post-processors as you would
|
|
any bean.</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> are
|
|
instantiated on startup, as part of the special startup phase of the
|
|
<interfacename>ApplicationContext</interfacename>. Next, all those
|
|
<interfacename>BeanPostProcessors</interfacename> are registered in a
|
|
sorted fashion - and applied to all further beans. Because 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 do 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
|
|
BeanPostProcessor interfaces (for example: not eligible for
|
|
auto-proxying)</quote>.</emphasis></para>
|
|
</note>
|
|
|
|
<para>The following examples show 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 illustrates basic usage. The example shows a
|
|
custom <interfacename>BeanPostProcessor</interfacename> implementation
|
|
that 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.</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 does not even have a name, and because it is a bean it can
|
|
be dependency-injected just like any other bean. (The preceding
|
|
configuration also defines 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>The following small driver script executes the preceding 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 the preceding execution resembles the
|
|
following:</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. An example is
|
|
shown in <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
|
|
<interfacename>BeanFactoryPostProcessor</interfacename>
|
|
interface</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>BeanFactoryPostProcessor</literal>s operate on the
|
|
<emphasis>bean configuration metadata</emphasis>; that is, the Spring
|
|
IoC container allows <literal>BeanFactoryPostProcessors</literal> to
|
|
read the configuration metadata and potentially change it
|
|
<emphasis>before</emphasis> the container instantiates any beans other
|
|
than <literal>BeanFactoryPostProcessors</literal>.</para>
|
|
|
|
<para>You can configure multiple
|
|
<literal>BeanFactoryPostProcessors</literal>. You can control the order
|
|
in which these <literal>BeanFactoryPostProcessors</literal> execute by
|
|
setting the <literal>order</literal> property. However, 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 instead need to use a
|
|
<interfacename>BeanPostProcessor</interfacename> (described above in
|
|
<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 automatically when it is
|
|
declared inside of an <interfacename>ApplicationContext,</interfacename>
|
|
in order to apply changes 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>A custom
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> can also be
|
|
used, for example, to register custom property editors.</para>
|
|
|
|
<anchor id="beans-factory-autodetect-beanfactorypostprocessors" />
|
|
|
|
<para>An <interfacename>ApplicationContext</interfacename> detects any
|
|
beans that are deployed into it and that implement the
|
|
<interfacename>BeanFactoryPostProcessor</interfacename> interface. It
|
|
automatically uses these beans as bean factory post-processors, at the
|
|
appropriate time. You can then deploy these post-processor beans as you
|
|
would any other bean.</para>
|
|
|
|
<note>
|
|
<para>As with <literal>BeanPostProcessors</literal>, you typically do
|
|
not want <literal>BeanFactoryPostProcessors</literal> marked as
|
|
lazy-initialized. If they are marked as such, the Spring container
|
|
never instantiates them, and thus they cannot apply their custom
|
|
logic. If you use 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>You use the
|
|
<interfacename>PropertyPlaceholderConfigurer</interfacename> to
|
|
externalize property values from a bean definition into another
|
|
separate file in the standard Java <classname>Properties</classname>
|
|
format. Doing so enables the person deploying an application to
|
|
customize environment-specific properties such as database URLs and
|
|
passwords, without the complexity or risk of modifying the main XML
|
|
definition file or files for the container.</para>
|
|
|
|
<!-- MLP: Beverly to review following 2 paragraphs -->
|
|
|
|
<para>Consider the following XML-based configuration metadata
|
|
fragment, where a <interfacename>DataSource</interfacename> with
|
|
placeholder values is defined. The example shows properties configured
|
|
from an external <classname>Properties</classname> file. At runtime, a
|
|
<classname>PropertyPlaceholderConfigurer</classname> is applied to the
|
|
metadata that will replace some properties of the DataSource. The
|
|
values to replace are specified as 'placeholders' of the form
|
|
${property-name} which follows the Ant / Log4J / JSP EL style.</para>
|
|
|
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
|
|
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
|
|
</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>Therefore, the string ${jdbc.username} is replaced at runtime
|
|
with the value 'sa' and similarly for other placeholder values that
|
|
match to keys in the property file. The PropertyPlaceholderConfigurer
|
|
checks for placeholders in most locations of a bean definition and the
|
|
placeholder prefix and suffix can be customized.</para>
|
|
|
|
<para>With the <literal>context</literal> namespace introduced in
|
|
Spring 2.5, it is possible to configure property placeholders with a
|
|
dedicated configuration element. You can provide multiple locations as
|
|
a comma-separated list in the <literal>location</literal>
|
|
attribute.</para>
|
|
|
|
<programlisting language="xml"><context:property-placeholder location="classpath:com/foo/jdbc.properties"/></programlisting>
|
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> does
|
|
not look for properties only 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. You can customize this behavior by setting the
|
|
<literal>systemPropertiesMode</literal> property of the configurer. It
|
|
has three values that specify configurer behavior: always override,
|
|
<emphasis>never</emphasis> override, and override only if the property
|
|
is not found in the properties file specified. <!--What property is it overriding and what will replace the overridden value?-->
|
|
<!--MLP: override a value in the Properties with one from the 'systemProperties' -->
|
|
Consult the Javadoc for the
|
|
<classname>PropertyPlaceholderConfigurer</classname> for more
|
|
information.</para>
|
|
|
|
<tip>
|
|
<title>Class name substitution</title>
|
|
|
|
<para>You can use the
|
|
<classname>PropertyPlaceholderConfigurer</classname> 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 cannot be resolved at runtime to a valid class,
|
|
resolution of the bean fails when 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, resembles the
|
|
<interfacename>PropertyPlaceholderConfigurer</interfacename>, but
|
|
unlike 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 definition is <emphasis>not</emphasis> aware
|
|
of being overridden, so it is not immediately obvious from the XML
|
|
definition file that the override configurer is used. In case of
|
|
multiple <classname>PropertyOverrideConfigurer</classname> instances
|
|
that define different values for the same bean property, the last one
|
|
wins, due to the overriding mechanism.</para>
|
|
|
|
<para>Properties file configuration lines take this format:</para>
|
|
|
|
<programlisting language="java">beanName.property=value</programlisting>
|
|
|
|
<para>For example:</para>
|
|
|
|
<programlisting language="java">dataSource.driverClassName=com.mysql.jdbc.Driver
|
|
dataSource.url=jdbc:mysql:mydb</programlisting>
|
|
|
|
<para>This example file is usable against a container definition that
|
|
contains a bean called <emphasis>dataSource</emphasis>, which has
|
|
<emphasis>driver</emphasis> and <emphasis>url</emphasis>
|
|
properties.</para>
|
|
|
|
<para>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 set to the scalar value
|
|
<literal>123</literal>.</para>
|
|
|
|
<para><note>
|
|
<para>Specified override values are always
|
|
<emphasis>literal</emphasis> values; they are not translated into
|
|
bean references. This convention also applies when the original
|
|
value in the XML bean definition specifies a bean
|
|
reference.</para>
|
|
</note></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 with the
|
|
<interfacename>FactoryBean</interfacename> Interface <literal>
|
|
</literal></title>
|
|
|
|
<para>You implement the
|
|
<interfacename>org.springframework.beans.factory.FactoryBean</interfacename>
|
|
interface for objects that <emphasis>are themselves
|
|
factories</emphasis>.</para>
|
|
|
|
<para>The <interfacename>FactoryBean</interfacename> interface is a
|
|
point of pluggability into the Spring IoC container's instantiation
|
|
logic. If you have 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>: returns 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>: returns
|
|
<literal>true</literal> if this
|
|
<interfacename>FactoryBean</interfacename> returns singletons,
|
|
<literal>false</literal> otherwise.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><methodname>Class getObjectType()</methodname>: returns the
|
|
object type returned by the <methodname>getObject()</methodname>
|
|
method or <literal>null</literal> if the type is not 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;
|
|
more than 50 implementations of the
|
|
<interfacename>FactoryBean</interfacename> interface ship with Spring
|
|
itself.</para>
|
|
|
|
<para>When you need to ask a container for an actual
|
|
<interfacename>FactoryBean</interfacename> instance itself, not the bean
|
|
it produces, you preface the bean id with the ampersand symbol
|
|
<literal>&</literal> (without quotes) when calling the
|
|
<methodname>getBean</methodname> method of the
|
|
<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 returns the product of the
|
|
<interfacename>FactoryBean</interfacename>, and invoking
|
|
<literal>getBean("&myBean")</literal> returns the
|
|
<interfacename>FactoryBean</interfacename> instance itself.<!--Moved ApplicationContext section to almost the end of the doc, right before BeanFactory and renamed it Additional Capabilities of.--></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-annotation-config">
|
|
<title>Annotation-based container configuration</title>
|
|
|
|
<para>As mentioned in <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>. Spring 3.0 adds support for
|
|
JSR-330 (Dependency Injection for Java) annotations contained in the
|
|
javax.inject package such as <classname>@Inject</classname>,
|
|
<literal>@Qualifier, @Named, and @Provider</literal> if the JSR330 jar is
|
|
present on the classpath. Use of these annotations also requires that
|
|
certain <interfacename>BeanPostProcessors</interfacename> be registered
|
|
within the Spring container. As always, you can register them 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/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"><classname>AutowiredAnnotationBeanPostProcessor</classname></ulink>,
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"><classname>CommonAnnotationBeanPostProcessor</classname></ulink>,
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-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/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"><classname>RequiredAnnotationBeanPostProcessor</classname></ulink>.)</para>
|
|
|
|
<note>
|
|
<para><literal><context:annotation-config/></literal> only looks
|
|
for annotations on beans in the same application context in which it is
|
|
defined. 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, through an explicit property
|
|
value in a bean definition or through autowiring. The container throws
|
|
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. It is
|
|
still recommended that you put assertions into the bean class itself,
|
|
for example, into an init method. Doing so enforces those required
|
|
references and values even when you use the class outside of a
|
|
container.</para>
|
|
</section>
|
|
|
|
<section id="beans-autowired-annotation">
|
|
<title><interfacename>@Autowired and @Inject</interfacename></title>
|
|
|
|
<para>As expected, you can apply the
|
|
<interfacename>@Autowired</interfacename> annotation to "traditional"
|
|
setter methods:</para>
|
|
|
|
<note>
|
|
<para>JSR 330's @Inject annotation can be used in place of Spring's
|
|
<interfacename>@Autowired</interfacename> in the examples below.
|
|
<interfacename>@Inject</interfacename> does not have a required
|
|
property unlike Spring's <interfacename>@Autowire</interfacename>
|
|
annotation which has a <literal>required</literal> property to
|
|
indicate if the value being injected is optional. This behavior is
|
|
enabled automatically if you have the JSR 330 JAR on the
|
|
classpath.</para>
|
|
</note>
|
|
|
|
<programlisting language="java">public class SimpleMovieLister {
|
|
|
|
private MovieFinder movieFinder;
|
|
|
|
@Autowired
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<para>You can also apply the annotation 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>You can apply <interfacename>@Autowired</interfacename> to
|
|
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 can 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 fails 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>
|
|
can be marked as <emphasis>required</emphasis>, but multiple
|
|
non-required constructors can be annotated. In that case, each is
|
|
considered among the candidates and Spring uses the
|
|
<emphasis>greediest</emphasis> constructor whose dependencies can be
|
|
satisfied, that is the constructor that has the largest number of
|
|
arguments.</para>
|
|
|
|
<para><interfacename>@Autowired</interfacename>'s
|
|
<emphasis>required</emphasis> attribute is recommended over the
|
|
<interfacename>@Required</interfacename> annotation. The
|
|
<emphasis>required</emphasis> attribute indicates that the property is
|
|
not required for autowiring purposes, the property is ignored if it
|
|
cannot be autowired. <interfacename>@Required</interfacename>, on the
|
|
other hand, is stronger in that it enforces the property that was set
|
|
by any means supported by the container. If no value is injected, a
|
|
corresponding exception is raised.</para>
|
|
</note>
|
|
|
|
<para>You can also use <interfacename>@Autowired</interfacename> for
|
|
interfaces that are well-known resolvable dependencies:
|
|
<interfacename>BeanFactory</interfacename>,
|
|
<interfacename>ApplicationContext</interfacename>,
|
|
<interfacename>ResourceLoader</interfacename>,
|
|
<interfacename>ApplicationEventPublisher</interfacename>, and
|
|
<interfacename>MessageSource</interfacename>. These interfaces and their
|
|
extended interfaces, such as
|
|
<interfacename>ConfigurableApplicationContext</interfacename> or
|
|
<interfacename>ResourcePatternResolver</interfacename>, are
|
|
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>Because 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. You can associate
|
|
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>
|
|
|
|
<note>
|
|
<para>JSR 330's <interfacename>@Qualifier</interfacename> annotation
|
|
can only be applied as a meta-annotation unlike Spring's @Qualifier
|
|
which takes a string property to discriminate among multiple injection
|
|
candidates and can be placed on annotations as well as types, fields,
|
|
methods, constructors, and parameters.</para>
|
|
</note>
|
|
|
|
<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 appear as follows. The bean
|
|
with qualifier value "main" is wired with the constructor argument that
|
|
is 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 a default
|
|
qualifier value. Thus you can define the bean with an id "main" instead
|
|
of the nested qualifier element, leading to the same matching result.
|
|
However, although you can use this convention 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 with 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 are "main" or "EMEA" or "persistent", expressing characteristics
|
|
of a specific component that are independent from the bean id, which may
|
|
be auto-generated in case of an anonymous bean definition like the one
|
|
in the preceding example.</para>
|
|
|
|
<para>Qualifiers also apply to typed collections, as discussed above,
|
|
for example, to <literal>Set<MovieCatalog></literal>. In this
|
|
case, all matching beans according to the declared qualifiers are
|
|
injected as a collection. This implies that qualifiers do not have to be
|
|
unique; they rather simply constitute filtering criteria. For example,
|
|
you can define multiple <classname>MovieCatalog</classname> beans 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, use 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
|
|
that are themselves defined as a collection or map type cannot be
|
|
injected through <interfacename>@Autowired</interfacename>, because
|
|
type matching is not properly applicable to them. Use
|
|
<interfacename>@Resource</interfacename> for such beans, referring to
|
|
the specific collection or map bean by unique name.</para>
|
|
|
|
<para><interfacename>@Autowired</interfacename> applies to fields,
|
|
constructors, and multi-argument methods, allowing for narrowing
|
|
through qualifier annotations at the parameter level. By contrast,
|
|
<interfacename>@Resource</interfacename> is supported only 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 can create your own custom qualifier annotations. Simply
|
|
define an annotation and provide the
|
|
<interfacename>@Qualifier</interfacename> annotation within your
|
|
definition:</para>
|
|
|
|
<note>
|
|
<para>You can use JSR 330's <interfacename>@Qualifier
|
|
</interfacename>annotation in the manner described below in place of
|
|
Spring's <interfacename>@Qualifier</interfacename> annotation. This
|
|
behavior is enabled automatically if you have the JSR 330 jar on the
|
|
classpath.</para>
|
|
</note>
|
|
|
|
<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>Next, provide the information for 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 is matched against the
|
|
fully-qualified class name of the annotation. Or, as a convenience if no
|
|
risk of conflicting names exists, you can use the short class name. Both
|
|
approaches 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 <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 can 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>You can also 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 take
|
|
precedence, but the autowiring mechanism falls back on the values
|
|
provided within the <literal><meta/></literal> tags if no such
|
|
qualifier is present, as in the last two bean definitions 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">
|
|
<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/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"><classname>CustomAutowireConfigurer</classname></ulink>
|
|
is a <interfacename>BeanFactoryPostProcessor</interfacename> that
|
|
enables you to register your own custom qualifier annotation types even
|
|
if they are not 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>The particular implementation of
|
|
<interfacename>AutowireCandidateResolver</interfacename> that is
|
|
activated for the application context depends on the Java version. In
|
|
versions earlier 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 by any <literal>default-autowire-candidates</literal>
|
|
pattern(s) available on the <literal><beans/></literal> element.
|
|
In Java 5 or later, the presence of
|
|
<interfacename>@Qualifier</interfacename> annotations and any custom
|
|
annotations registered with the
|
|
<classname>CustomAutowireConfigurer</classname> will also play a
|
|
role.</para>
|
|
|
|
<para>Regardless of the Java version, when multiple beans qualify as
|
|
autowire candidates, the determination of a "primary" candidate 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 in Java EE 5 and Java
|
|
6, for example, in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring
|
|
supports this pattern for Spring-managed objects as well.</para>
|
|
|
|
<para><interfacename>@Resource</interfacename> takes a name attribute,
|
|
and by default Spring interprets 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, the default name is derived
|
|
from the field name or setter method. In case of a field, it takes the
|
|
field name; in case of a setter method, it takes 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 is resolved as a bean name
|
|
by the <interfacename>ApplicationContext</interfacename> of which the
|
|
<classname>CommonAnnotationBeanPostProcessor</classname> is aware. The
|
|
names can be resolved through JNDI if you configure Spring's <ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"><classname>SimpleJndiBeanFactory</classname></ulink>
|
|
explicitly. However, it is recommended that you rely on the default
|
|
behavior and simply use Spring's JNDI lookup capabilities to preserve
|
|
the level of indirection.</para>
|
|
</note>
|
|
|
|
<para>In the exclusive case of <interfacename>@Resource</interfacename>
|
|
usage with no explicit name specified, and similar to
|
|
<interfacename>@Autowired</interfacename>,
|
|
<interfacename>@Resource</interfacename> finds a primary type match
|
|
instead of a specific named bean and resolves well-known resolvable
|
|
dependencies: the
|
|
<interfacename>BeanFactory</interfacename><interfacename>,
|
|
ApplicationContext,</interfacename><interfacename> ResourceLoader,
|
|
ApplicationEventPublisher</interfacename>, and
|
|
<interfacename>MessageSource</interfacename> interfaces.</para>
|
|
|
|
<para>Thus in the following example, the
|
|
<literal>customerPreferenceDao</literal> field first looks for a bean
|
|
named customerPreferenceDao, then falls back to a primary type match for
|
|
the type <classname>CustomerPreferenceDao</classname>. The "context"
|
|
field is 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 <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 is invoked at the same point in
|
|
the lifecycle as the corresponding Spring lifecycle interface 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 about 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 and managed components</title>
|
|
|
|
<!-- MLP: Beverly to review paragraph -->
|
|
|
|
<para>Most examples in this chapter use XML to specify the configuration
|
|
metadata that produces each <interfacename>BeanDefinition</interfacename>
|
|
within the Spring container. The previous section (<xref
|
|
linkend="beans-annotation-config" />) demonstrates how to provide a lot of
|
|
the configuration metadata through source-level annotations. Even in those
|
|
examples, however, the "base" bean definitions are explicitly defined in
|
|
the XML file, while the annotations only drive the dependency injection.
|
|
This section describes an option for implicitly detecting the
|
|
<emphasis>candidate components</emphasis> by scanning the classpath.
|
|
Candidate components are classes that match against a filter criteria and
|
|
have a corresponding bean definition registered with the container. This
|
|
removes the need to use XML to perform bean registration, instead you can
|
|
use annotations (for example @Component), AspectJ type expressions, or
|
|
your own custom filter criteria to select which classes will have bean
|
|
definitions registered with the container.</para>
|
|
|
|
<note>
|
|
<para>Starting with Spring 3.0, many features provided by the <ulink
|
|
url="http://www.springsource.org/javaconfig">Spring JavaConfig
|
|
project</ulink> are part of 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</interfacename>,
|
|
<interfacename>@Import</interfacename>, and
|
|
<interfacename>@DependsOn</interfacename> annotations for examples of
|
|
how to use these new features.</para>
|
|
</note>
|
|
|
|
<section id="beans-stereotype-annotations">
|
|
<title><interfacename>@Component</interfacename> and further stereotype
|
|
annotations</title>
|
|
|
|
<para>In Spring 2.0 and later, the
|
|
<interfacename>@Repository</interfacename> annotation is a marker for
|
|
any class that fulfills the role or <emphasis>stereotype</emphasis>
|
|
(also known as Data Access Object or DAO) of a repository. Among the
|
|
uses of this marker is the automatic translation of exceptions as
|
|
described in <xref linkend="orm-exception-translation" />.</para>
|
|
|
|
<para>Spring 2.5 introduces further stereotype annotations:
|
|
<interfacename>@Component</interfacename>,
|
|
<interfacename>@Service</interfacename>, and
|
|
<interfacename>@Controller</interfacename>.
|
|
<interfacename>@Component</interfacename> is a generic stereotype for
|
|
any Spring-managed component.
|
|
<interfacename>@Repository</interfacename>,
|
|
<interfacename>@Service</interfacename>, and
|
|
<interfacename>@Controller</interfacename> are specializations of
|
|
<interfacename>@Component</interfacename> for more specific use cases,
|
|
for example, in the persistence, service, and presentation layers,
|
|
respectively. Therefore, 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. 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
|
|
choosing 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>Automatically detecting classes and registering bean
|
|
definitions</title>
|
|
|
|
<para>Spring can automatically detect stereotyped classes and register
|
|
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,
|
|
you need to include the following element in XML, where the base-package
|
|
element is a common parent package for the two classes. (Alternatively,
|
|
you can specify a comma-separated list that includes 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>The scanning of classpath packages requires the presence of
|
|
corresponding directory entries in the classpath. When you build JARs
|
|
with Ant, make sure that you do <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 you use 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>You can disable the registration of
|
|
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename>
|
|
and <interfacename>CommonAnnotationBeanPostProcessor</interfacename>
|
|
by including the <emphasis>annotation-config</emphasis> attribute with
|
|
a value of false.</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>In Spring 3.0 RC1 you can use JSR 330's
|
|
<interfacename>@Named</interfacename> annotation in place of
|
|
stereotpye annotations and they will be automatically detected during
|
|
component-scanning. The value of the
|
|
<interfacename>@Named</interfacename> property will be used as the
|
|
Bean Name. At this time Spring defaults for bean scope will be applied
|
|
when using @Named. This behavior as well as mapping of JSR 330 and JSR
|
|
299 scopes is planned for Spring 3.0 GA assuming the JSRs are stable
|
|
at that time.</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>,
|
|
<interfacename>@Controller</interfacename>, or a custom annotation that
|
|
itself is annotated with <interfacename>@Component</interfacename> are
|
|
the only detected candidate components. However, you can modify and
|
|
extend this behavior simply by applying custom filters. Add them as
|
|
<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. The following table describes the filtering options.</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.MyTypeFilter</literal></entry>
|
|
|
|
<entry>A custom implementation of the
|
|
<interfacename>org.springframework.core.type
|
|
.TypeFilter</interfacename> interface.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>The following example shows the XML configuration 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>You can also 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-factorybeans-annotations">
|
|
<title>Defining bean metadata within components</title>
|
|
|
|
<para>Spring components can also contribute bean definition metadata to
|
|
the container. You do this 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 language="java">@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 that 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
|
|
other bean definition properties, such as a qualifier value through 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 previously discussed, with
|
|
additional support for autowiring of <literal>@Bean</literal>
|
|
methods:</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(BeanDefinition.SCOPE_SINGLETON)
|
|
private TestBean privateInstance() {
|
|
return new TestBean("privateInstance", i++);
|
|
}
|
|
|
|
@Bean @Scope(value = WebApplicationContext.SCOPE_SESSION,
|
|
proxyMode = ScopedProxyMode.TARGET_CLASS)
|
|
public TestBean requestScopedInstance() {
|
|
return new TestBean("requestScopedInstance", 3);
|
|
}
|
|
}
|
|
</programlisting>
|
|
|
|
<para>The example autowires 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
|
|
defines the value of the property through 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.
|
|
Methods are <emphasis>not</emphasis> invoked 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 is 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.</para>
|
|
|
|
<note>
|
|
<para>JSR 330's @Named annotation can be used as a means to both
|
|
detect components and to provide them with a name. This behavior is
|
|
enabled automatically if you have the JSR 330 JAR on the
|
|
classpath.</para>
|
|
</note>
|
|
|
|
<para>If such an annotation contains no <literal>name</literal> value or
|
|
for any other detected component (such as those discovered by custom
|
|
filters), the default bean name generator returns 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 do not want to rely on the default bean-naming strategy,
|
|
you can provide a custom bean-naming strategy. First, implement the
|
|
<ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-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 most
|
|
common scope for autodetected components is singleton. However,
|
|
sometimes you need other scopes, which Spring 2.5 provides with a new
|
|
<interfacename>@Scope</interfacename> annotation. Simply provide the
|
|
name of the scope within the annotation:</para>
|
|
|
|
<programlisting language="java">@Scope(StandardScopes.PROTOTYPE)
|
|
@Repository
|
|
public class MovieFinderImpl implements MovieFinder {
|
|
<lineannotation>// ...</lineannotation>
|
|
}</programlisting>
|
|
|
|
<note>
|
|
<para>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/3.0.x/javadoc-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
|
|
<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 is
|
|
discussed in <xref linkend="beans-autowired-annotation-qualifiers" />.
|
|
The examples in that section demonstrate the use of the
|
|
<interfacename>@Qualifier</interfacename> annotation and custom
|
|
qualifier annotations to provide fine-grained control when you resolve
|
|
autowire candidates. Because 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, you provide the qualifier metadata 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 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,
|
|
because that metadata is provided per-instance rather than
|
|
per-class.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java">
|
|
<title>Java-based container configuration</title>
|
|
|
|
<section id="beans-java-basic-concepts">
|
|
<title>Basic concepts: <literal>@Configuration</literal> and <literal>@Bean</literal></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 to
|
|
be managed by the Spring IoC container.</para>
|
|
|
|
<para>Annotating a class with the
|
|
<interfacename>@Configuration</interfacename> indicates that the class
|
|
can 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 {
|
|
@Bean
|
|
public MyService myService() {
|
|
return new MyServiceImpl();
|
|
}
|
|
}</programlisting></para>
|
|
|
|
<para>For those more familiar with Spring <literal><beans/></literal>
|
|
XML, the <literal>AppConfig</literal> class above would be equivalent to:
|
|
|
|
<programlisting language="xml"><beans>
|
|
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
|
|
</beans></programlisting>
|
|
|
|
As you can see, the <literal>@Bean</literal> annotation plays the same role
|
|
as the <literal><bean/></literal> element. The <literal>@Bean</literal>
|
|
annotation will be discussed in depth in the sections below. First, however,
|
|
we'll cover the various ways of creating a spring container using Java-based
|
|
configuration.</para>
|
|
</section>
|
|
|
|
<section id="beans-java-instantiating-container">
|
|
<title>Instantiating the Spring container using
|
|
<literal>AnnotationConfigApplicationContext</literal></title>
|
|
|
|
<para>The sections below document Spring's
|
|
<literal>AnnotationConfigApplicationContext</literal>, new in Spring 3.0.
|
|
This versatile <literal>ApplicationContext</literal> implementation is
|
|
capable of accepting not only <literal>@Configuration</literal> classes
|
|
as input, but also plain <literal>@Component</literal> classes and classes
|
|
annotated with JSR-330 metadata.</para>
|
|
|
|
<para>When <literal>@Configuration</literal> classes are provided as input,
|
|
the <literal>@Configuration</literal> class itself is registered as a bean
|
|
definition, and all declared <literal>@Bean</literal> methods within the
|
|
class are also registered as bean definitions.</para>
|
|
|
|
<para>When <literal>@Component</literal> and JSR-330 classes are provided,
|
|
they are registered as bean definitions, and it is assumed that DI metadata
|
|
such as <literal>@Autowired</literal> or <literal>@Inject</literal> are used
|
|
within those classes where necessary.</para>
|
|
|
|
<section id="beans-java-instantiating-container-contstructor">
|
|
<title>Simple construction</title>
|
|
<para>In much the same way that Spring XML files are used as input when
|
|
instantiating a <literal>ClassPathXmlApplicationContext</literal>,
|
|
<literal>@Configuration</literal> classes may be used as input when
|
|
instantiating an <literal>AnnotationConfigApplicationContext</literal>.
|
|
This allows for completely XML-free usage of the Spring container:
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
|
|
MyService myService = ctx.getBean(MyService.class);
|
|
myService.doStuff();
|
|
}</programlisting>
|
|
|
|
As mentioned above, <literal>AnnotationConfigApplicationContext</literal>
|
|
is not limited to working only with <literal>@Configuration</literal>
|
|
classes. Any <literal>@Component</literal> or JSR-330 annotated class may
|
|
be supplied as input to the constructor. For example:
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
|
|
MyService myService = ctx.getBean(MyService.class);
|
|
myService.doStuff();
|
|
}</programlisting>
|
|
|
|
The above assumes that <literal>MyServiceImpl</literal>, <literal>Dependency1</literal> and <literal>Dependency2</literal> use Spring dependency injection annotations such as <literal>@Autowired</literal>.</para>
|
|
</section>
|
|
|
|
<section id="beans-java-instantiating-container-register">
|
|
<title>Building the container programmatically using <literal>register(Class<?>...)</literal></title>
|
|
<para>An <literal>AnnotationConfigApplicationContext</literal> may be
|
|
instantiated using a no-arg constructor and then configured using the
|
|
<literal>register()</literal> method. This approach is particularly
|
|
useful when programmatically building an
|
|
<literal>AnnotationConfigApplicationContext</literal>.
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
|
ctx.register(AppConfig.class, OtherConfig.class);
|
|
ctx.register(AdditionalConfig.class);
|
|
ctx.refresh();
|
|
MyService myService = ctx.getBean(MyService.class);
|
|
myService.doStuff();
|
|
}</programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-java-instantiating-container-scan">
|
|
<title>Enabling component scanning with <literal>scan(String...)</literal></title>
|
|
<para>Experienced Spring users will be familiar with the following
|
|
commonly-used XML declaration from Spring's <literal>context:</literal> namespace
|
|
<programlisting language="xml"><beans>
|
|
<context:component-scan base-package="com.acme"/>
|
|
</beans></programlisting>
|
|
|
|
In the example above, the <literal>com.acme</literal> package will
|
|
be scanned, looking for any <literal>@Component</literal>-annotated
|
|
classes, and those classes will be registered as Spring bean
|
|
definitions within the container.
|
|
|
|
<literal>AnnotationConfigApplicationContext</literal> exposes the
|
|
<literal>scan(String...)</literal> method to allow for the same
|
|
component-scanning functionality:<programlisting language="java">public static void main(String[] args) {
|
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
|
ctx.scan("com.acme");
|
|
ctx.refresh();
|
|
MyService myService = ctx.getBean(MyService.class);
|
|
}</programlisting></para>
|
|
<note>
|
|
<para>Remember that <literal>@Configuration</literal> classes are
|
|
meta-annotated with <literal>@Component</literal>, so they are
|
|
candidates for component-scanning! In the example above, assuming
|
|
that <literal>AppConfig</literal> is declared within the
|
|
<literal>com.acme</literal> package (or any package underneath),
|
|
it will be picked up during the call to <literal>scan()</literal>,
|
|
and upon <literal>refresh()</literal> all its <literal>@Bean</literal>
|
|
methods will be processed and registered as bean definitions within
|
|
the container.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-java-instantiating-container-web">
|
|
<title>Support for web applications with <literal>AnnotationConfigWebApplicationContext</literal></title>
|
|
<para>A <literal>WebApplicationContext</literal> variant of <literal>AnnotationConfigApplicationContext</literal> is available with <literal>AnnotationConfigWebApplicationContext</literal>. This implementation may be used when configuring the Spring <literal>ContextLoaderListener</literal> servlet listener, Spring MVC <literal>DispatcherServlet</literal>, etc. What follows is a <literal>web.xml</literal> snippet that configures a typical Spring MVC web application. Note the use of the <literal>contextClass</literal> context-param and init-param:
|
|
<programlisting language="xml"><![CDATA[
|
|
<web-app>
|
|
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
|
|
instead of the default XmlWebApplicationContext -->
|
|
<context-param>
|
|
<param-name>contextClass</param-name>
|
|
<param-value>
|
|
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
|
</param-value>
|
|
</context-param>
|
|
|
|
<!-- Configuration locations must consist of one or more comma- or space-delimited
|
|
fully-qualified @Configuration classes -->
|
|
<context-param>
|
|
<param-name>contextConfigLocation</param-name>
|
|
<param-value>com.acme.AppConfig</param-value>
|
|
</context-param>
|
|
|
|
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
|
|
<listener>
|
|
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
|
</listener>
|
|
|
|
<!-- Declare a Spring MVC DispatcherServlet as usual -->
|
|
<servlet>
|
|
<servlet-name>dispatcher</servlet-name>
|
|
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
|
<!-- Configure DispatcherServlet to use JavaConfigWebApplicationContext
|
|
instead of the default XmlWebApplicationContext -->
|
|
<init-param>
|
|
<param-name>contextClass</param-name>
|
|
<param-value>
|
|
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
|
|
</param-value>
|
|
</init-param>
|
|
<!-- Again, config locations must consist of one or more comma- or space-delimited
|
|
and fully-qualified @Configuration classes -->
|
|
<init-param>
|
|
<param-name>contextConfigLocation</param-name>
|
|
<param-value>com.acme.web.MvcConfig</param-value>
|
|
</init-param>
|
|
</servlet>
|
|
|
|
<!-- map all requests for /main/* to the dispatcher servlet -->
|
|
<servlet-mapping>
|
|
<servlet-name>dispatcher</servlet-name>
|
|
<url-pattern>/main/*</url-pattern>
|
|
</servlet-mapping>
|
|
</web-app>]]></programlisting></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java-composing-configuration-classes">
|
|
<title>Composing Java-based configurations</title>
|
|
<section id="beans-java-using-import">
|
|
<title>Using the <literal>@Import</literal> annotation</title>
|
|
<para>Much as the <literal><import/></literal> element is used within
|
|
Spring XML files to aid in modularizing configurations, the
|
|
<literal>@Import</literal> annotation allows for loading <literal>@Bean</literal>
|
|
definitions from another configuration class:<programlisting language="java">@Configuration
|
|
public class ConfigA {
|
|
public @Bean A a() { return new A(); }
|
|
}
|
|
|
|
@Configuration
|
|
@Import(ConfigA.class)
|
|
public class ConfigB {
|
|
public @Bean B b() { return new B(); }
|
|
}</programlisting>
|
|
|
|
Now, rather than needing to specify both <literal>ConfigA.class</literal> and
|
|
<literal>ConfigB.class</literal> when instantiating the context, only
|
|
<literal>ConfigB</literal> needs to be supplied explicitly:<programlisting language="java">public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
|
|
|
|
// now both beans A and B will be available...
|
|
A a = ctx.getBean(A.class);
|
|
B b = ctx.getBean(B.class);
|
|
}</programlisting>
|
|
|
|
This approach simplifies container instantiation, as only one class needs to be dealt
|
|
with, rather than requiring the developer to remember a potentially large number of
|
|
<literal>@Configuration</literal> classes during construction.
|
|
</para>
|
|
|
|
<section id="beans-java-injecting-imported-beans">
|
|
<title>Injecting dependencies on imported <literal>@Bean</literal> definitions</title>
|
|
<para>The example above works, but is simplistic. In most practical scenarios, beans
|
|
will have dependencies on one another across configuration classes. When using XML,
|
|
this is not an issue, per se, because there is no compiler involved, and one can
|
|
simply declare <literal>ref="someBean"</literal> and trust that Spring will work
|
|
it out during container initialization. Of course, when using
|
|
<literal>@Configuration</literal> classes, the Java compiler places constraints on
|
|
the configuration model, in that references to other beans must be valid Java syntax.</para>
|
|
|
|
<para>Fortunately, solving this problem is simple. Remember that
|
|
<literal>@Configuration</literal> classes are ultimately just another bean in the container
|
|
- this means that they can take advantage of <literal>@Autowired</literal> injection
|
|
metadata just like any other bean!</para>
|
|
|
|
<para>Let's consider a more real-world scenario with several <literal>@Configuration</literal>
|
|
classes, each depending on beans declared in the others:<programlisting language="java">@Configuration
|
|
public class ServiceConfig {
|
|
private @Autowired AccountRepository accountRepository;
|
|
|
|
public @Bean TransferService transferService() {
|
|
return new TransferServiceImpl(accountRepository);
|
|
}
|
|
}
|
|
|
|
@Configuration
|
|
public class RepositoryConfig {
|
|
private @Autowired DataSource dataSource;
|
|
|
|
public @Bean AccountRepository accountRepository() {
|
|
return new JdbcAccountRepository(dataSource);
|
|
}
|
|
}
|
|
|
|
@Configuration
|
|
@Import({ServiceConfig.class, RepositoryConfig.class})
|
|
public class SystemTestConfig {
|
|
public @Bean DataSource dataSource() { /* return new DataSource */ }
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
|
|
// everything wires up across configuration classes...
|
|
TransferService transferService = ctx.getBean(TransferService.class);
|
|
transferService.transfer(100.00, "A123", "C456");
|
|
}</programlisting></para>
|
|
|
|
<section id="beans-java-injecting-imported-beans-fq">
|
|
<title>Fully-qualifying imported beans for ease of navigation</title>
|
|
<para>In the scenario above, using <literal>@Autowired</literal> works
|
|
well and provides the desired modularity, but determining exactly where
|
|
the autowired bean definitions are declared is still somewhat ambiguous.
|
|
For example, as a developer looking at <literal>ServiceConfig</literal>,
|
|
how do you know exactly where the <literal>@Autowired AccountRepository</literal>
|
|
bean is declared? It's not explicit in the code, and this may be just fine.
|
|
Remember that the <ulink url="http://www.springsource.com/products/sts">SpringSource
|
|
Tool Suite</ulink> provides tooling that can render graphs showing how everything
|
|
is wired up - that may be all you need. Also, your Java IDE can easily find all
|
|
declarations and uses of the <literal>AccountRepository</literal> type, and will
|
|
quickly show you the location of <literal>@Bean</literal> methods that return that
|
|
type.</para>
|
|
|
|
<para>In cases where this ambiguity is not acceptable and you wish to have
|
|
direct navigation from within your IDE from one <literal>@Configuration</literal>
|
|
class to another, consider autowiring the configuration classes themselves:
|
|
<programlisting language="java">@Configuration
|
|
public class ServiceConfig {
|
|
private @Autowired RepositoryConfig repositoryConfig;
|
|
|
|
public @Bean TransferService transferService() {
|
|
// navigate 'through' the config class to the @Bean method!
|
|
return new TransferServiceImpl(repositoryConfig.accountRepository());
|
|
}
|
|
}</programlisting>
|
|
|
|
In the situation above, it is completely explicit where
|
|
<literal>AccountRepository</literal> is defined. However,
|
|
<literal>ServiceConfig</literal> is now tightly coupled to
|
|
<literal>RepositoryConfig</literal>; that's the tradeoff. This tight
|
|
coupling can be somewhat mitigated by using interface-based or abstract
|
|
class-based <literal>@Configuration</literal> classes. Consider the following:
|
|
<programlisting language="java">@Configuration
|
|
public class ServiceConfig {
|
|
private @Autowired RepositoryConfig repositoryConfig;
|
|
|
|
public @Bean TransferService transferService() {
|
|
return new TransferServiceImpl(repositoryConfig.accountRepository());
|
|
}
|
|
}
|
|
|
|
@Configuration
|
|
public interface RepositoryConfig {
|
|
@Bean AccountRepository accountRepository();
|
|
}
|
|
|
|
@Configuration
|
|
public class DefaultRepositoryConfig implements RepositoryConfig {
|
|
public @Bean AccountRepository accountRepository() {
|
|
return new JdbcAccountRepository(...);
|
|
}
|
|
}
|
|
|
|
@Configuration
|
|
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
|
|
public class SystemTestConfig {
|
|
public @Bean DataSource dataSource() { /* return DataSource */ }
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
|
|
TransferService transferService = ctx.getBean(TransferService.class);
|
|
transferService.transfer(100.00, "A123", "C456");
|
|
}</programlisting>
|
|
|
|
Now <literal>ServiceConfig</literal> is loosely coupled with respect
|
|
to the concrete <literal>DefaultRepositoryConfig</literal>, and built-in IDE
|
|
tooling is still useful: it will be easy for the developer to get a type hierarchy
|
|
of <literal>RepositoryConfig</literal> implementations. In this way, navigating
|
|
<literal>@Configuration</literal> classes and their dependencies becomes no
|
|
different than the usual process of navigating interface-based code.</para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java-combining">
|
|
<title>Combining Java and XML configuration</title>
|
|
<para>Spring's <literal>@Configuration</literal> class support does not aim to be a 100%
|
|
complete replacement for Spring XML. Some facilities such as Spring XML namespaces remain
|
|
an ideal way to configure the container. In cases where XML is convenient or necessary,
|
|
you have a choice: either instantiate the container in an "XML-centric" way using, for
|
|
example, <literal>ClassPathXmlApplicationContext</literal>, or in a "Java-centric" fashion
|
|
using <literal>AnnotationConfigApplicationContext</literal> and the
|
|
<literal>@ImportResource</literal> annotation to import XML as needed.</para>
|
|
|
|
<section id="beans-java-combining-xml-centric">
|
|
<title>XML-centric use of <literal>@Configuration</literal> classes</title>
|
|
<para>It may be preferable to bootstrap the Spring container from XML and
|
|
include <literal>@Configuration</literal> classes in an ad-hoc fashion.
|
|
For example, in a large existing codebase that uses Spring XML, it will be
|
|
easier to create <literal>@Configuration</literal> classes on an as-needed
|
|
basis and include them from the existing XML files. Below you'll find the
|
|
options for using <literal>@Configuration</literal> classes in this kind
|
|
of "XML-centric" situation.</para>
|
|
|
|
<section id="beans-java-combining-xml-centric-declare-as-bean">
|
|
<title>Declaring <literal>@Configuration</literal> classes as plain Spring
|
|
<literal><bean/></literal> elements</title>
|
|
<para>Remember that <literal>@Configuration</literal> classes are ultimately
|
|
just bean definitions in the container. In this example, we create a
|
|
<literal>@Configuration</literal> class named <literal>AppConfig</literal>
|
|
and include it within <literal>system-test-config.xml</literal> as a
|
|
<literal><bean/></literal>definition. Because
|
|
<literal><context:annotation-config/></literal> is switched on, the
|
|
container will recognize the <literal>@Configuration</literal> annotation,
|
|
and process the <literal>@Bean</literal> methods declared in
|
|
<literal>AppConfig</literal> properly.<programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
private @Autowired DataSource dataSource;
|
|
|
|
public @Bean AccountRepository accountRepository() {
|
|
return new JdbcAccountRepository(dataSource);
|
|
}
|
|
|
|
public @Bean TransferService transferService() {
|
|
return new TransferService(accountRepository());
|
|
}
|
|
}</programlisting>
|
|
<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
|
|
<beans>
|
|
<!-- enable processing of annotations such as @Autowired and @Configuration -->
|
|
<context:annotation-config/>
|
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
|
|
|
|
<bean class="com.acme.AppConfig"/>
|
|
|
|
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
|
<property name="url" value="${jdbc.url}"/>
|
|
<property name="username" value="${jdbc.username}"/>
|
|
<property name="password" value="${jdbc.password}"/>
|
|
</bean>
|
|
</beans></programlisting>
|
|
|
|
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
|
|
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
|
|
jdbc.username=sa
|
|
jdbc.password=</programlisting>
|
|
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
|
|
TransferService transferService = ctx.getBean(TransferService.class);
|
|
// ...
|
|
}</programlisting></para>
|
|
|
|
<note>
|
|
<para>In <literal>system-test-config.xml</literal> above, the
|
|
<literal>AppConfig<bean/></literal> does not declare an
|
|
<literal>id</literal> element. While it would be acceptable to do
|
|
so, it is unnecessary given that no other bean will ever refer to it,
|
|
and it is unlikely that it will be explicitly fetched from the container
|
|
by name. Likewise with the <literal>DataSource</literal> bean - it is
|
|
only ever autowired by type, so an explicit bean id is not strictly
|
|
required.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="beans-java-combining-xml-centric-component-scan">
|
|
<title>Using <literal><context:component-scan/></literal> to pick up
|
|
<literal>@Configuration</literal> classes</title>
|
|
<para>Because <literal>@Configuration</literal> is meta-annotated with
|
|
<literal>@Component</literal>, <literal>@Configuration</literal>-annotated
|
|
classes are automatically candidates for component scanning. Using the same
|
|
scenario as above, we can redefine <literal>system-test-config.xml</literal>
|
|
to take advantage of component-scanning. Note that in this case, we don't
|
|
need to explicitly declare <literal><context:annotation-config/></literal>,
|
|
because <literal><context:component-scan/></literal> enables all the same
|
|
functionality.<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
|
|
<beans>
|
|
<!-- picks up and registers AppConfig as a bean definition -->
|
|
<context:component-scan base-package="com.acme"/>
|
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
|
|
|
|
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
|
<property name="url" value="${jdbc.url}"/>
|
|
<property name="username" value="${jdbc.username}"/>
|
|
<property name="password" value="${jdbc.password}"/>
|
|
</bean>
|
|
</beans></programlisting>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java-combining-java-centric">
|
|
<title><literal>@Configuration</literal> class-centric use of XML with
|
|
<literal>@ImportResource</literal></title>
|
|
<para>In applications where <literal>@Configuration</literal> classes are
|
|
the primary mechanism for configuring the container, it will still
|
|
likely be necessary to use at least some XML. In these scenarios,
|
|
simply use <literal>@ImportResource</literal> and define only as much
|
|
XML as is needed. Doing so achieves a "Java-centric" approach to
|
|
configuring the container and keeps XML to a bare minimum.
|
|
<programlisting language="java">@Configuration
|
|
@ImportResource("classpath:/com/acme/properties-config.xml")
|
|
public class AppConfig {
|
|
private @Value("${jdbcProperties.url}") String url;
|
|
private @Value("${jdbcProperties.username}") String username;
|
|
private @Value("${jdbcProperties.password}") String password;
|
|
|
|
public @Bean DataSource dataSource() {
|
|
return new DriverManagerDataSource(url, username, password);
|
|
}
|
|
}</programlisting>
|
|
|
|
<programlisting language="xml"><lineannotation role="listingtitle">properties-config.xml</lineannotation>
|
|
<beans>
|
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
|
|
</beans></programlisting>
|
|
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
|
|
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
|
|
jdbc.username=sa
|
|
jdbc.password=</programlisting>
|
|
<programlisting language="java">public static void main(String[] args) {
|
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
|
|
TransferService transferService = ctx.getBean(TransferService.class);
|
|
// ...
|
|
}</programlisting></para>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java-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>name</code>.</para>
|
|
|
|
<para>You can use the <interfacename>@Bean</interfacename> annotation in
|
|
a <interfacename>@Configuration</interfacename>-annotated or in a
|
|
<interfacename>@Component</interfacename>-annotated class.</para>
|
|
|
|
<section id="beans-java-declaring-a-bean">
|
|
<title>Declaring a bean</title>
|
|
|
|
<para>To declare a bean, simply annotate a method with the
|
|
<interfacename>@Bean</interfacename> annotation. You use this method
|
|
to register a bean definition within an
|
|
<code>ApplicationContext</code> of the type specified as the method's
|
|
return value. By default, the bean name will be the same as the method
|
|
name. 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>The preceding configuration is exactly equivalent to the
|
|
following Spring XML: <programlisting language="xml"><beans>
|
|
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
|
|
</beans> </programlisting></para>
|
|
|
|
<para>Both declarations make a bean named <code>transferService</code>
|
|
available in the <code>ApplicationContext</code>, bound to an object
|
|
instance of type <code>TransferServiceImpl</code>: <programlisting>
|
|
transferService -> com.acme.TransferServiceImpl
|
|
</programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-java-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 receives a
|
|
reference to <code> bar</code> via constructor injection.</para>
|
|
</section>
|
|
|
|
<section id="beans-java-lifecycle-callbacks">
|
|
<title>Receiving lifecycle callbacks</title>
|
|
|
|
<para>Beans declared in a
|
|
<interfacename>@Configuration</interfacename>-annotated class support
|
|
the regular lifecycle callbacks. Any classes defined with the
|
|
<literal>@Bean</literal> annotation can use the
|
|
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal>
|
|
annotations from JSR-250, see <link
|
|
linkend="beans-postconstruct-and-predestroy-annotations">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 are called by the container.</para>
|
|
|
|
<para>The standard set of <code>*Aware</code> interfaces such as
|
|
<code><link
|
|
linkend="beans-beanfactory">BeanFactoryAware</link></code>,
|
|
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>,
|
|
<code><link
|
|
linkend="context-functionality-messagesource">MessageSourceAware</link></code>,
|
|
<code><link
|
|
linkend="beans-factory-aware">ApplicationContextAware</link></code>,
|
|
and so on 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 on 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(initMethod = "init")
|
|
public Foo foo() {
|
|
return new Foo();
|
|
}
|
|
@Bean(destroyMethod = "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>When you work directly in Java, you can do anything you like
|
|
with your objects and do not always need to rely on the
|
|
container lifecycle!</para>
|
|
</tip>
|
|
</section>
|
|
|
|
<section id="beans-java-specifying-bean-scope">
|
|
<title>Specifying bean scope</title>
|
|
|
|
<section id="beans-java-available-scopes">
|
|
<title>Using the <interfacename>@Scope</interfacename>
|
|
annotation</title>
|
|
|
|
<!-- MLP: Beverly, did not apply your edit as it changed meaning -->
|
|
|
|
<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 default scope is <literal>singleton</literal>, but you can
|
|
override this with the <interfacename>@Scope</interfacename>
|
|
annotation: <programlisting language="java">@Configuration
|
|
public class MyConfiguration {
|
|
@Bean
|
|
<emphasis role="bold">@Scope("prototype")</emphasis>
|
|
public Encryptor encryptor() {
|
|
// ...
|
|
}
|
|
}</programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-java-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 you port the scoped proxy example from the XML reference
|
|
documentation (see preceding link) to our
|
|
<interfacename>@Bean</interfacename> using Java, it would look like
|
|
the following: <programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy
|
|
@Bean
|
|
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis>
|
|
public UserPreferences userPreferences() {
|
|
return new UserPreferences();
|
|
}
|
|
|
|
@Bean
|
|
public Service userService() {
|
|
UserService service = new SimpleUserService();
|
|
// a reference to the proxied userPreferences bean
|
|
service.setUserPreferences(userPreferences());
|
|
return service;
|
|
} </programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-java-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 you should use rarely.
|
|
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 , you can create a subclass
|
|
of <code>CommandManager</code> where the abstract
|
|
<code>createCommand()</code> method is overridden in such a way that
|
|
it looks up a new (prototype) command object: <programlisting
|
|
language="java">@Bean
|
|
@Scope("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 createCommand() {
|
|
return asyncCommand();
|
|
}
|
|
}
|
|
} </programlisting></para>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-java-customizing-bean-naming">
|
|
<title>Customizing bean naming</title>
|
|
|
|
<para>By default, configuration classes use a
|
|
<interfacename>@Bean</interfacename> method's name as the name of the
|
|
resulting bean. This functionality can be overridden, however, with
|
|
the <code>name</code> attribute. <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
@Bean(name = "myFoo")
|
|
public Foo foo() {
|
|
return new Foo();
|
|
}
|
|
|
|
} </programlisting></para>
|
|
</section>
|
|
|
|
<section id="beans-java-bean-aliasing">
|
|
<title>Bean aliasing</title>
|
|
|
|
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes desirable
|
|
to give a single bean multiple names, otherwise known as <emphasis>bean aliasing</emphasis>.
|
|
The <literal>name</literal> attribute of the <literal>@Bean</literal> annotation accepts
|
|
a String array for this purpose. <programlisting language="java">@Configuration
|
|
public class AppConfig {
|
|
|
|
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
|
|
public DataSource dataSource() {
|
|
// instantiate, configure and return DataSource bean...
|
|
}
|
|
|
|
} </programlisting></para>
|
|
</section>
|
|
</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.<!--Need to explain purpose of LoadTimeWeaver? Is this section ok here? --></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>
|
|
|
|
<section id="context-introduction">
|
|
<title>Additional Capabilities of the
|
|
<interfacename>ApplicationContext</interfacename></title>
|
|
|
|
<!-- MLP: Beverly to review paragraph and list -->
|
|
|
|
<para>As was discussed in the chapter introduction, the
|
|
<literal>org.springframework.beans.factory</literal> package provides
|
|
basic functionality for managing and manipulating beans, including in a
|
|
programmatic way. The <literal>org.springframework.context</literal>
|
|
package adds the <ulink
|
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html"><interfacename>ApplicationContext</interfacename></ulink>
|
|
interface, which implements the <interfacename>BeanFactory</interfacename>
|
|
interface, in addition to extending other interfaces to provide additional
|
|
functionality in a more <emphasis>application framework-oriented
|
|
style</emphasis>. Many people use the
|
|
<interfacename>ApplicationContext</interfacename> in a completely
|
|
declarative fashion, not even creating it programmatically, 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 application.</para>
|
|
|
|
<para>To enhance <interfacename>BeanFactory</interfacename> functionality
|
|
in a more framework-oriented style the context package also provides the
|
|
following functionality:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis>Access to messages in i18n-style</emphasis>, through
|
|
the <interfacename>MessageSource</interfacename> interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Access to resources</emphasis>, such as URLs and
|
|
files, through the <interfacename>ResourceLoader</interfacename>
|
|
interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Event publication</emphasis> to beans implementing the
|
|
<interfacename>ApplicationListener</interfacename> interface, through
|
|
the use of the
|
|
<interfacename>ApplicationEventPublisher</interfacename>
|
|
interface.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><emphasis>Loading of multiple (hierarchical)
|
|
contexts</emphasis>, allowing each to be focused on one particular
|
|
layer, such as the web layer of an application, through the
|
|
<interfacename>HierarchicalBeanFactory</interfacename>
|
|
interface.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<section id="context-functionality-messagesource">
|
|
<title>Internationalization using
|
|
<interfacename>MessageSource</interfacename></title>
|
|
|
|
<!-- MLP: Beverly to review this paragraph -->
|
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> interface
|
|
extends an interface called
|
|
<interfacename>MessageSource</interfacename>, and therefore provides
|
|
internationalization (i18n) functionality. Spring also provides the
|
|
interface <classname>HierarchicalMessageSource</classname>, which can
|
|
resolve messages hierarchically. Together these interfaces provide the
|
|
foundation upon which Spring effects message resolution. The methods
|
|
defined on these interfaces include:</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 become 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
|
|
preceding methods are also wrapped in a class named
|
|
<interfacename>MessageSourceResolvable</interfacename>, which you
|
|
can use with this method.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>When an <interfacename>ApplicationContext</interfacename> is
|
|
loaded, it automatically searches for a
|
|
<interfacename>MessageSource</interfacename> bean defined in the
|
|
context. The bean must have the name <literal>messageSource</literal>.
|
|
If such a bean is found, all calls to the preceding methods are
|
|
delegated to the message source. If no message source is found, the
|
|
<interfacename>ApplicationContext</interfacename> attempts to find a
|
|
parent containing a bean with the same name. If it does, it uses that
|
|
bean as the <interfacename>MessageSource</interfacename>. If the
|
|
<interfacename>ApplicationContext</interfacename> cannot find any source
|
|
for messages, an empty <classname>DelegatingMessageSource</classname> is
|
|
instantiated in order to be able to accept calls to the methods defined
|
|
above.</para>
|
|
|
|
<para>Spring provides two <interfacename>MessageSource</interfacename>
|
|
implementations, <classname>ResourceBundleMessageSource</classname> and
|
|
<classname>StaticMessageSource</classname>. Both implement
|
|
<interfacename>HierarchicalMessageSource</interfacename> in order to do
|
|
nested messaging. The <classname>StaticMessageSource</classname> is
|
|
rarely used but provides programmatic ways to add messages to the
|
|
source. The <classname>ResourceBundleMessageSource</classname> is shown
|
|
in the following example:</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>In the example it is assumed you have three resource bundles
|
|
defined in your classpath called <literal>format</literal>,
|
|
<literal>exceptions</literal> and <literal>windows</literal>. Any
|
|
request to resolve a message will be handled in the JDK standard way of
|
|
resolving messages through ResourceBundles. For the purposes of the
|
|
example, 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>A program to execute the <classname>MessageSource</classname>
|
|
functionality is shown in the next example. 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>, which exists at
|
|
the root of your classpath. The <literal>messageSource</literal> bean
|
|
definition refers to a number of resource bundles through 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>The next example shows arguments passed to the message lookup;
|
|
these arguments will be converted into Strings and inserted into
|
|
placeholders in the lookup message.</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><!-- lets 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>Typically, locale resolution is managed by the surrounding
|
|
environment of the application. In this example, the locale against
|
|
which (British) messages will be resolved is specified manually.</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>You can also use the <classname>MessageSourceAware</classname>
|
|
interface 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 is
|
|
injected with the application context's
|
|
<classname>MessageSource</classname> when the bean is created and
|
|
configured.</para>
|
|
|
|
<note>
|
|
<para><emphasis>As an alternative to
|
|
<classname>ResourceBundleMessageSource</classname>, Spring 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>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="context-functionality-events">
|
|
<title>Standard and Custom 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
|
|
that 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 is
|
|
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, for example, 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. As long as the context has not been closed, a
|
|
refresh can be triggered multiple times, provided that the
|
|
chosen <interfacename>ApplicationContext</interfacename>
|
|
actually supports such "hot" refreshes. For example,
|
|
<classname>XmlWebApplicationContext</classname> supports hot
|
|
refreshes, but <classname>GenericApplicationContext</classname>
|
|
does not.</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 receive an
|
|
explicit start signal. Typically this signal is used to restart
|
|
beans after an explicit stop, but it may also be used to start
|
|
components that have not been configured for autostart , for
|
|
example, components that have not already started on
|
|
initialization.</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 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 reaches 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 event is published
|
|
<emphasis>after</emphasis> the request is complete. This event
|
|
is only applicable to web applications using Spring's
|
|
<classname>DispatcherServlet</classname>.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>You can also implement custom events. Simply call the
|
|
<methodname>publishEvent()</methodname> method on the
|
|
<interfacename>ApplicationContext</interfacename>, specifying a
|
|
parameter that is an instance of your custom event class that implements
|
|
<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 through
|
|
an <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.<!--Explain what is showing in the first and second examples?--></para>
|
|
|
|
<para>This example shows the bean definitions used to configure an
|
|
<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>This example shows the implementation of the classes refered to in
|
|
the previous bean definitions:</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>
|
|
|
|
<!-- MLP: Beverly to review paragraph -->
|
|
|
|
<para>When the sendEmail method is called, if there are any emails that
|
|
should be blacklisted, a custom event of the type BlackListEvent is
|
|
published to the application context. The BlackListNotifier class which
|
|
implements the interface ApplicationListener is registered as a
|
|
subscriber to the application context and will receive the
|
|
BlackListEvent. In order to access properties specific to
|
|
BlackListEvent, the listener must perform a downcast.</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 <xref linkend="resources" />.</para>
|
|
|
|
<para>An application context is a
|
|
<interfacename>ResourceLoader</interfacename>, which can be used to load
|
|
<interfacename>Resource</interfacename>s. A
|
|
<interfacename>Resource</interfacename> is essentially a more feature
|
|
rich version of the JDK class <literal>java.net.URL</literal>, in fact,
|
|
the implementations of the <interfacename>Resource</interfacename> wrap
|
|
an instance of <literal>java.net.URL</literal> where appropriate. A
|
|
<interfacename>Resource</interfacename> can 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>You can configure a bean deployed into the application context to
|
|
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>. You can
|
|
also expose properties of type <interfacename>Resource</interfacename>,
|
|
to be used to access static resources; they will be injected into it
|
|
like any other properties. You can 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 when the bean is
|
|
deployed.</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. You can also use location paths
|
|
(resource strings) 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>You can create <interfacename>ApplicationContext</interfacename>
|
|
instances declaratively by using, for example, a
|
|
<classname>ContextLoader</classname>. Of course you can also create
|
|
<interfacename>ApplicationContext</interfacename> instances
|
|
programmatically by using one of the
|
|
<interfacename>ApplicationContext</interfacename>
|
|
implementations.</para>
|
|
|
|
<para>The <classname>ContextLoader</classname> mechanism comes in two
|
|
flavors: the <classname>ContextLoaderListener</classname> and the
|
|
<classname>ContextLoaderServlet</classname>. They have the same
|
|
functionality but differ in that the listener version is not reliable in
|
|
Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet
|
|
context listeners must execute immediately after the Servlet context for
|
|
the web application is 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>. 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 uses
|
|
<literal>/WEB-INF/applicationContext.xml</literal> as a default. When
|
|
the parameter <emphasis>does</emphasis> exist, the listener separates
|
|
the String by using predefined delimiters (comma, semicolon and
|
|
whitespace) and uses the values as locations where application contexts
|
|
will be searched. Ant-style path patterns are supported as well.
|
|
Examples are <literal>/WEB-INF/*Context.xml</literal> for all files with
|
|
names ending with "Context.xml", residing in the "WEB-INF" directory,
|
|
and <literal>/WEB-INF/**/*Context.xml</literal>, for all such files in
|
|
any subdirectory of "WEB-INF".</para>
|
|
|
|
<para>You can use <classname>ContextLoaderServlet</classname> instead of
|
|
<classname>ContextLoaderListener</classname>. The Servlet uses the
|
|
<literal>contextConfigLocation</literal> parameter just as the listener
|
|
does.</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Deploying a Spring ApplicationContext as a J2EE RAR file</title>
|
|
|
|
<para>In Spring 2.5 and later, 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 servers facilities. RAR deployment is a more natural
|
|
alternative to scenario of deploying a headless WAR file, in effect, a
|
|
WAR file without any HTTP entry points that is used only for
|
|
bootstrapping a Spring ApplicationContext in a J2EE environment.</para>
|
|
|
|
<para>RAR deployment is ideal for application contexts that do not need
|
|
HTTP entry points but rather consist only of message endpoints and
|
|
scheduled jobs. Beans in such a context can 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 can also interact with the application server's 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/3.0.x/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html">SpringContextResourceAdapter</ulink>
|
|
class for the configuration details involved in RAR deployment.</para>
|
|
|
|
<para><emphasis>For a simple deployment of a Spring ApplicationContext
|
|
as a J2EE RAR file:</emphasis> package all application classes into a
|
|
RAR file, which is 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) and 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>
|
|
|
|
<note>
|
|
<para>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 occurs 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 needs to allow 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.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="beans-beanfactory">
|
|
<title>The BeanFactory</title>
|
|
|
|
<para>The <classname>BeanFactory</classname> provides the underlying basis
|
|
for Spring's IoC functionality but it is only used directly in integration
|
|
with other third-party frameworks and is now largely historical in nature
|
|
for most users of Spring. The <classname>BeanFactory</classname> and
|
|
related interfaces, such as <classname>BeanFactoryAware</classname>,
|
|
<classname>InitializingBean</classname>,
|
|
<classname>DisposableBean</classname>, are still present in Spring for the
|
|
purposes of backward compatibility with the large number of third-party
|
|
frameworks that integrate with Spring. Often third-party components that
|
|
can not use more modern equivalents such as <code>@PostConstruct</code> or
|
|
<code>@PreDestroy</code> in order to remain compatible with JDK 1.4 or to
|
|
avoid a dependency on JSR-250.</para>
|
|
|
|
<para>This section provides additional background into the differences
|
|
between the <interfacename>BeanFactory</interfacename> and
|
|
<interfacename>ApplicationContext</interfacename> and how one might access
|
|
the IoC container directly through a classic singleton lookup.</para>
|
|
|
|
<section id="context-introduction-ctx-vs-beanfactory">
|
|
<title><interfacename>BeanFactory</interfacename> or
|
|
<interfacename>ApplicationContext</interfacename>?</title>
|
|
|
|
<para>Use an <interfacename>ApplicationContext</interfacename> unless
|
|
you have a good reason for not doing so.</para>
|
|
|
|
<para>Because the <interfacename>ApplicationContext</interfacename>
|
|
includes all functionality of the
|
|
<interfacename>BeanFactory</interfacename>, it is generally recommended
|
|
over the <interfacename>BeanFactory</interfacename>, except for a few
|
|
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. Spring 2.0 and later makes
|
|
<emphasis>heavy</emphasis> use of the <link
|
|
linkend="beans-factory-extension-bpp"><interfacename>BeanPostProcessor</interfacename>
|
|
extension point</link> (to effect proxying and so on). If you use only a
|
|
plain <interfacename>BeanFactory</interfacename>, a fair amount of
|
|
support such as transactions and AOP will not take effect, at least not
|
|
without some extra steps on your part. This situation could be confusing
|
|
because nothing is actually wrong with the configuration.</para>
|
|
|
|
<para>The following table lists features provided by the
|
|
<interfacename>BeanFactory</interfacename> and
|
|
<interfacename>ApplicationContext</interfacename> interfaces and
|
|
implementations.</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>
|
|
|
|
<para>To explicitly register a bean post-processor with a
|
|
<interfacename>BeanFactory</interfacename> implementation, you must
|
|
write 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>To explicitly register a
|
|
<classname>BeanFactoryPostProcessor</classname> when using a
|
|
<interfacename>BeanFactory</interfacename> implementation, you must
|
|
write code like 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>In both cases, the explicit registration step is inconvenient,
|
|
which is one reason 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> and
|
|
<classname>BeanPostProcessors</classname>. These mechanisms implement
|
|
important functionality such as property placeholder replacement and
|
|
AOP.</para>
|
|
</section>
|
|
|
|
<section id="beans-servicelocator">
|
|
<title>Glue code and the evil singleton</title>
|
|
|
|
<para>It is best to write most application code in a
|
|
dependency-injection (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, you sometimes need a 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 get these objects out of a Spring IoC
|
|
container. <!--Can you reword the phrase singleton style access, above and next parragraph? Seems awkward.-->If
|
|
the object constructed by the third-party code is 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, retrieved from 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>Looking up the application context in a service locator style is
|
|
sometimes the only option for accessing shared Spring-managed
|
|
components, such as in an EJB 2.1 environment, or when you want to share
|
|
a single ApplicationContext as a parent to WebApplicationContexts across
|
|
WAR files. In this case you should look into using the utility class
|
|
<ulink
|
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html"><classname>ContextSingletonBeanFactoryLocator</classname></ulink>
|
|
locator that is described in this <ulink
|
|
url="http://blog.springsource.com/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/">SpringSource
|
|
team blog entry</ulink>.</para>
|
|
</section>
|
|
</section>
|
|
</chapter>
|