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