You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
7346 lines
352 KiB
7346 lines
352 KiB
<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> |
|
<chapter id="beans"> |
|
<title>The IoC container</title> |
|
|
|
<section id="beans-introduction"> |
|
<title>Introduction to the Spring IoC container and beans</title> |
|
|
|
<para>This chapter covers the Spring Framework implementation of the |
|
Inversion of Control (IoC) <footnote> |
|
<para>See <xref linkend="background-ioc" /></para> |
|
</footnote>principle. IoC is also known as <emphasis>dependency |
|
injection</emphasis> (DI). It is a process whereby objects define their |
|
dependencies, that is, the other objects they work with, only through |
|
constructor arguments, arguments to a factory method, or properties that |
|
are set on the object instance after it is constructed or returned from a |
|
factory method. The container then <emphasis>injects</emphasis> those |
|
dependencies when it creates the bean. This process is fundamentally the |
|
inverse, hence the name <emphasis>Inversion of Control</emphasis> (IoC), |
|
of the bean itself controlling the instantiation or location of its |
|
dependencies by using direct construction of classes, or a mechanism such |
|
as the <emphasis>Service Locator</emphasis> pattern.</para> |
|
|
|
<!--I copied and pasted preceding from "Injecting Dependencies" to give background on IoC, since that's what chapter is about. |
|
The footnote should x-ref to first section in that chapter but I can't find the file. The current xref doesn't work.--> |
|
|
|
<para>The <literal>org.springframework.beans</literal> and |
|
<literal>org.springframework.context</literal> packages are the basis for |
|
Spring Framework's IoC container. The <interfacename><ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/BeanFactory.html">BeanFactory</ulink></interfacename> |
|
interface provides an advanced configuration mechanism capable of managing |
|
any type of object. <literal><ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html">ApplicationContext</ulink></literal> |
|
is a sub-interface of <interfacename>BeanFactory.</interfacename> It adds |
|
easier integration with Spring's AOP features; message resource handling |
|
(for use in internationalization), event publication; and |
|
application-layer specific contexts such as the |
|
<interfacename>WebApplicationContext</interfacename> for use in web |
|
applications.</para> |
|
|
|
<para>In short, the <interfacename>BeanFactory</interfacename> provides |
|
the configuration framework and basic functionality, and the |
|
<interfacename>ApplicationContext</interfacename> adds more |
|
enterprise-specific functionality. The |
|
<interfacename>ApplicationContext</interfacename> is a complete superset |
|
of the <interfacename>BeanFactory</interfacename>, and is used exclusively |
|
in this chapter in descriptions of Spring's IoC container. <!--API spec says ApplicationContext is a subinterface of BeanFactory, so is it right to call it a superset?-->For |
|
more information on using the <classname>BeanFactory</classname> instead |
|
of the <classname>ApplicationContext,</classname> refer to <xref |
|
linkend="beans-beanfactory" />.</para> |
|
|
|
<para>In Spring, the objects that form the backbone of your application |
|
and that are managed by the Spring IoC <firstterm>container</firstterm> |
|
are called <firstterm>beans</firstterm>. A bean is an object that is |
|
instantiated, assembled, and otherwise managed by a Spring IoC container. |
|
Otherwise, a bean is simply one of many objects in your application. |
|
Beans, and the <firstterm>dependencies</firstterm> among them, are |
|
reflected in the <firstterm>configuration metadata</firstterm> used by a |
|
container.</para> |
|
</section> |
|
|
|
<section id="beans-basics"> |
|
<title>Container overview</title> |
|
|
|
<para>The interface |
|
<classname>org.springframework.context.ApplicationContext</classname> |
|
represents the Spring IoC container and is responsible for instantiating, |
|
configuring, and assembling the aforementioned beans. The container gets |
|
its instructions on what objects to instantiate, configure, and assemble |
|
by reading configuration metadata. The configuration metadata is |
|
represented in XML, Java annotations, or Java code. It allows you to |
|
express the objects that compose your application and the rich |
|
interdependencies between such objects.</para> |
|
|
|
<para>Several implementations of the |
|
<classname>ApplicationContext</classname> interface are supplied |
|
out-of-the-box with Spring. In standalone applications it is common to |
|
create an instance of <ulink |
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html"><classname>ClassPathXmlApplicationContext</classname></ulink> |
|
or <ulink |
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html"><classname>FileSystemXmlApplicationContext</classname></ulink>. |
|
<!-- MLP: Beverly to review --> While XML has been the traditional format |
|
for defining configuration metadata you can instruct the container to use |
|
Java annotations or code as the metadata format by providng a small amount |
|
of XML configuration to declaratively enable support for these additional |
|
metadata formats.</para> |
|
|
|
<para>In most application scenarios, explicit user code is not required to |
|
instantiate one or more instances of a Spring IoC container. For example, |
|
in a web application scenario, a simple eight (or so) lines of boilerplate |
|
J2EE web descriptor XML in the <literal>web.xml</literal> file of the |
|
application will typically suffice (see <xref |
|
linkend="context-create" />). If you are using the <ulink |
|
url="http://www.springsource.com/produts/sts">SpringSource Tool |
|
Suite</ulink> Eclipse-powered development environment or <ulink |
|
url="http://www.springsource.org/roo">Spring Roo</ulink> this boilerplate |
|
configuration can be easily created with few mouse clicks or |
|
keystrokes.</para> |
|
|
|
<para>The following diagram is a high-level view of how Spring works. Your |
|
application classes are combined with configuration metadata so that after |
|
the <classname>ApplicationContext</classname> is created and initialized, |
|
you have a fully configured and executable system or application.</para> |
|
|
|
<para><mediaobject> |
|
<imageobject> |
|
<imagedata align="center" fileref="images/container-magic.png" |
|
format="PNG" /> |
|
</imageobject> |
|
|
|
<caption><para>The Spring IoC container</para></caption> |
|
</mediaobject></para> |
|
|
|
<section id="beans-factory-metadata"> |
|
<title>Configuration metadata</title> |
|
|
|
<para>As the preceding diagram shows, the Spring IoC container consumes |
|
a form of <emphasis>configuration metadata</emphasis>; this |
|
configuration metadata represents how you as an application developer |
|
tell the Spring container to instantiate, configure, and assemble the |
|
objects in your application.</para> |
|
|
|
<para>Configuration metadata is traditionally supplied in a simple and |
|
intuitive XML format, which is what most of this chapter uses to convey |
|
key concepts and features of the Spring IoC container.</para> |
|
|
|
<note> |
|
<para>XML-based metadata is <emphasis>not</emphasis> the only allowed |
|
form of configuration metadata. The Spring IoC container itself is |
|
<emphasis>totally</emphasis> decoupled from the format in which this |
|
configuration metadata is actually written.</para> |
|
</note> |
|
|
|
<para>For information about using other forms of metadata with the |
|
Spring container, see:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para><link linkend="beans-annotation-config">Annotation-based |
|
configuration</link>: Spring 2.5 introduced support for |
|
annotation-based configuration metadata.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><link linkend="beans-java">Java-based |
|
configuration</link>: Starting with Spring 3.0, many features |
|
provided by the <ulink |
|
url="http://www.springsource.org/javaconfig">Spring JavaConfig |
|
project</ulink> became part of the core Spring Framework. Thus you |
|
can define beans external to your application classes by using Java |
|
rather than XML files. To use these new features, see the |
|
<interfacename>@Configuration</interfacename>, <interfacename>@Bean, |
|
@Import</interfacename> and |
|
<interfacename>@DependsOn</interfacename> annotations.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>Spring configuration consists of at least one and typically more |
|
than one bean definition that the container must manage. XML-based |
|
configuration metadata shows these beans configured as |
|
<literal><bean/></literal> elements inside a top-level |
|
<literal><beans/></literal> element.</para> |
|
|
|
<para>These bean definitions correspond to the actual objects that make |
|
up your application. Typically you define service layer objects, data |
|
access objects (DAOs), presentation objects such as Struts |
|
<interfacename>Action</interfacename> instances, infrastructure objects |
|
such as Hibernate <interfacename>SessionFactories</interfacename>, JMS |
|
<interfacename>Queues</interfacename>, and so forth. Typically one does |
|
not configure fine-grained domain objects in the container, because it |
|
is usually the responsibility of DAOs and business logic to create and |
|
load domain objects. However, you can use Spring's integration with |
|
AspectJ to configure objects that have been created outside the control |
|
of an IoC container. See <link linkend="aop-atconfigurable">Using |
|
AspectJ to dependency-inject domain objects with Spring</link>.</para> |
|
|
|
<para>The following example shows the basic structure of XML-based |
|
configuration metadata:</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean id="..." class="..."> |
|
<!-- collaborators and configuration for this bean go here --> |
|
</bean> |
|
|
|
<bean id="..." class="..."> |
|
<!-- collaborators and configuration for this bean go here --> |
|
</bean> |
|
|
|
<!-- more bean definitions go here --> |
|
|
|
</beans></programlisting> |
|
|
|
<para>The <literal>id</literal> attribute is a string that you use to |
|
identify the individual bean definition. The <literal>class</literal> |
|
attribute defines the type of the bean and uses the fully qualified |
|
classname. The value of the id attribute refers to collaborating |
|
objects. The XML for referring to collaborating objects is not shown in |
|
this example; see <link linkend="beans-dependencies">Dependencies</link> |
|
for more information.</para> |
|
</section> |
|
|
|
<section id="beans-factory-instantiation"> |
|
<title>Instantiating a container</title> |
|
|
|
<para>Instantiating a Spring IoC container is straightforward. The |
|
location path or paths supplied to an |
|
<interfacename>ApplicationContext</interfacename> constructor are |
|
actually resource strings that allow the container to load configuration |
|
metadata from a variety of external resources such as the local file |
|
system, from the Java <literal>CLASSPATH</literal>, and so on.</para> |
|
|
|
<programlisting language="java">ApplicationContext context = |
|
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});</programlisting> |
|
|
|
<note> |
|
<para>After you learn about Spring's IoC container, you may want to |
|
know more about Spring's <interfacename>Resource</interfacename> |
|
abstraction, as described in <xref linkend="resources" />, which |
|
provides a convenient mechanism for reading an InputSream from |
|
locations defined in a URI syntax. In particular, |
|
<classname>Resource</classname> paths are used to construct |
|
applications contexts as described in <xref |
|
linkend="resources-app-ctx" />.</para> |
|
</note> |
|
|
|
<para>The following example shows the service layer objects |
|
<literal>(services.xml)</literal> configuration file:</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<!-- services --> |
|
|
|
<bean id="petStore" |
|
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"> |
|
<property name="accountDao" ref="accountDao"/> |
|
<property name="itemDao" ref="itemDao"/> |
|
<!-- additional collaborators and configuration for this bean go here --> |
|
</bean> |
|
|
|
<!-- more bean definitions for services go here --> |
|
|
|
</beans> |
|
</programlisting> |
|
|
|
<para>The following example shows the data access objects |
|
<literal>daos.xml</literal>) file:</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean id="accountDao" |
|
class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao"> |
|
<!-- additional collaborators and configuration for this bean go here --> |
|
</bean> |
|
|
|
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapItemDao"> |
|
<!-- additional collaborators and configuration for this bean go here --> |
|
</bean> |
|
|
|
<!-- more bean definitions for data access objects go here --> |
|
|
|
</beans></programlisting> |
|
|
|
<para>In the preceding example, the service layer consists of the class |
|
<classname>PetStoreServiceImpl</classname>, and two data access objects |
|
of the type <classname>SqlMapAccountDao</classname> and SqlMapItemDao |
|
are based on the <ulink url="http://ibatis.apache.org/">iBatis</ulink> |
|
Object/Relational mapping framework. The <literal>property |
|
name</literal> element refers to the name of the JavaBean property, and |
|
the <literal>ref</literal> element refers to the name of another bean |
|
definition. This linkage between id and ref elements expresses the |
|
dependency between collaborating objects. For details of configuring an |
|
object's dependencies, see <link |
|
linkend="beans-dependencies">Dependencies</link>.</para> |
|
|
|
<section id="beans-factory-xml-import"> |
|
<title>Composing XML-based configuration metadata</title> |
|
|
|
<para>It can be useful to have bean definitions span multiple XML |
|
files. Often each individual XML configuration file represents a |
|
logical layer or module in your architecture.</para> |
|
|
|
<para>You can use the application context constructor to load bean |
|
definitions from all these XML fragments. This constructor takes |
|
multiple <interfacename>Resource</interfacename> locations, as was |
|
shown in the previous section. Alternatively, use one or more |
|
occurrences of the <literal><import/></literal> element to load |
|
bean definitions from another file or files. For example:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<import resource="services.xml"/> |
|
<import resource="resources/messageSource.xml"/> |
|
<import resource="/resources/themeSource.xml"/> |
|
|
|
<bean id="bean1" class="..."/> |
|
<bean id="bean2" class="..."/> |
|
|
|
</beans></programlisting> |
|
|
|
<para>In the preceding example, external bean definitions are loaded |
|
from three files, <literal>services.xml</literal>, |
|
<literal>messageSource.xml</literal>, and |
|
<literal>themeSource.xml</literal>. All location paths are relative to |
|
the definition file doing the importing, so |
|
<literal>services.xml</literal> must be in the same directory or |
|
classpath location as the file doing the importing, while |
|
<literal>messageSource.xml</literal> and |
|
<literal>themeSource.xml</literal> must be in a |
|
<literal>resources</literal> location below the location of the |
|
importing file. As you can see, a leading slash is ignored, but given |
|
that these paths are relative, it is better form not to use the slash |
|
at all. The contents of the files being imported, including the top |
|
level <literal><beans/></literal> element, must be valid XML |
|
bean definitions according to the Spring Schema or DTD.</para> |
|
|
|
<note> |
|
<para>It is possible, but not recommended, to reference files in |
|
parent directories using a relative "../" path. Doing so creates a |
|
dependency on a file that is outside the current application. In |
|
particular, this reference is not recommended for "classpath:" URLs |
|
(for example, "classpath:../services.xml"), where the runtime |
|
resolution process chooses the "nearest" classpath root and then |
|
looks into its parent directory. Classpath configuration changes may |
|
lead to the choice of a different, incorrect directory.</para> |
|
|
|
<para>You can always use fully qualified resource locations instead |
|
of relative paths: for example, "file:C:/config/services.xml" or |
|
"classpath:/config/services.xml". However, be aware that you are |
|
coupling your application's configuration to specific absolute |
|
locations. It is generally preferable to keep an indirection for |
|
such absolute locations, for example, through "${...}" placeholders |
|
that are resolved against JVM system properties at runtime.</para> |
|
</note> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-client"> |
|
<title>Using the container</title> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> is the |
|
interface for an advanced factory capable of maintaining a registry of |
|
different beans and their dependencies. Using the method <methodname>T |
|
getBean(Stringname, Class<T> requiredType)</methodname> you can |
|
retrieve instances of your beans.</para> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> enables you |
|
to read bean definitions and access them as follows:</para> |
|
|
|
<programlisting language="java">// create and configure beans |
|
ApplicationContext context = |
|
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"}); |
|
|
|
// retrieve configured instance |
|
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class); |
|
|
|
// use configured instance |
|
List userList service.getUsernameList(); |
|
</programlisting> |
|
|
|
<para>You use <methodname>getBean</methodname> to retrieve instances of |
|
your beans. The <interfacename>ApplicationContext</interfacename> |
|
interface has a few other methods for retrieving beans, but ideally your |
|
application code should never use them. Indeed, your application code |
|
should have no calls to the <methodname>getBean</methodname> method at |
|
all, and thus no dependency on Spring APIs at all. For example, Spring's |
|
integration with web frameworks provides for dependency injection for |
|
various web framework classes such as controllers and JSF-managed |
|
beans.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-definition"> |
|
<title>Bean overview</title> |
|
|
|
<para>A Spring IoC container manages one or more |
|
<emphasis>beans</emphasis>. These beans are created with the configuration |
|
metadata that you supply to the container, for example, in the form of XML |
|
<literal><bean/></literal> definitions.</para> |
|
|
|
<para>Within the container itself, these bean definitions are represented |
|
as <interfacename>BeanDefinition</interfacename> objects, which contain |
|
(among other information) the following metadata:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para><emphasis>A package-qualified class name:</emphasis> typically |
|
the actual implementation class of the bean being defined.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Bean behavioral configuration elements, which state how the bean |
|
should behave in the container (scope, lifecycle callbacks, and so |
|
forth).</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>References to other beans that are needed for the bean to do its |
|
work; these references are also called |
|
<emphasis>collaborators</emphasis> or |
|
<emphasis>dependencies</emphasis>.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Other configuration settings to set in the newly created object, |
|
for example, the number of connections to use in a bean that manages a |
|
connection pool, or the size limit of the pool.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>This metadata translates to a set of properties that make up each |
|
bean definition.</para> |
|
|
|
<table id="beans-factory-bean-definition-tbl"> |
|
<title>The bean definition</title> |
|
|
|
<tgroup cols="2"> |
|
<colspec colname="c1" colwidth="2*" /> |
|
|
|
<colspec colname="c2" colwidth="4*" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Property</entry> |
|
|
|
<entry>Explained in...</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry>class</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-class" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>name</entry> |
|
|
|
<entry><para> <xref linkend="beans-beanname" /> </para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>scope</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-scopes" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>constructor arguments</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-collaborators" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>properties</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-collaborators" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>autowiring mode</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-autowire" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>dependency checking mode</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-dependencies" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>lazy-initialization mode</entry> |
|
|
|
<entry><para> <xref linkend="beans-factory-lazy-init" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>initialization method</entry> |
|
|
|
<entry><para> <xref |
|
linkend="beans-factory-lifecycle-initializingbean" /> |
|
</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>destruction method</entry> |
|
|
|
<entry><para> <xref |
|
linkend="beans-factory-lifecycle-disposablebean" /> |
|
</para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>In addition to bean definitions that contain information on how to |
|
create a specific bean, the |
|
<interfacename>ApplicationContext</interfacename> implementations also |
|
permit the registration of existing objects that are created outside the |
|
container, by users. This is done by accessing the ApplicationContext's |
|
BeanFactory via the method <methodname>getBeanFactory</methodname> which |
|
returns the BeanFactory implementation |
|
<classname>DefaultListableBeanFactory</classname>. |
|
<classname>DefaultListableBeanFactory</classname> supports this |
|
registration through the methods |
|
<methodname>registerSingleton(..)</methodname> and |
|
<methodname>registerBeanDefinition(..)</methodname>. However, typical |
|
applications work solely with beans defined through metadata bean |
|
definitions.</para> |
|
|
|
<section id="beans-beanname"> |
|
<title>Naming beans</title> |
|
|
|
<para>Every bean has one or more identifiers. These identifiers must be |
|
unique within the container that hosts the bean. A bean usually has only |
|
one identifier, but if it requires more than one, the extra ones can be |
|
considered aliases.</para> |
|
|
|
<para>In XML-based configuration metadata, you use the |
|
<literal>id</literal> and/or <literal>name</literal> attributes to |
|
specify the bean identifier(s). The <literal>id</literal> attribute |
|
allows you to specify exactly one id, and because it is a real XML |
|
element ID attribute, the XML parser can do some extra validation when |
|
other elements reference the id. As such, it is the preferred way to |
|
specify a bean identifier. However, the XML specification does limit the |
|
characters that are legal in XML ids. This is usually not a constraint, |
|
but if you need to use one of these special XML characters, or want to |
|
introduce other aliases to the bean, you can also specify them in the |
|
<literal>name</literal> attribute, separated by a comma |
|
(<literal>,</literal>), semicolon (<literal>;</literal>), or white |
|
space.</para> |
|
|
|
<para>You are not required to supply a name or id for a bean. If no name |
|
or id is supplied explicitly, the container generates a unique name for |
|
that bean. However, if you want to refer to that bean by name, through |
|
the use of the <literal>ref</literal> element or <link lang="" |
|
linkend="beans-servicelocation">Service Location</link> style lookup, |
|
you must provide a name. Motivations for not supplying a name are |
|
related to using <link linkend="beans-inner-beans">inner beans</link> |
|
and <link linkend="beans-factory-autowire">autowiring |
|
collaborators</link>.</para> |
|
|
|
<sidebar> |
|
<title>Bean naming conventions</title> |
|
|
|
<para>The convention is to use the standard Java convention for |
|
instance field names when naming beans. That is, bean names start with |
|
a lowercase letter, and are camel-cased from then on. Examples of such |
|
names would be (without quotes) <literal>'accountManager'</literal>, |
|
<literal>'accountService'</literal>, <literal>'userDao'</literal>, |
|
<literal>'loginController'</literal>, and so forth.</para> |
|
|
|
<para>Naming beans consistently makes your configuration easier to |
|
read and understand, and if you are using Spring AOP it helps a lot |
|
when applying advice to a set of beans related by name.</para> |
|
</sidebar> |
|
|
|
<section id="beans-beanname-alias"> |
|
<title>Aliasing a bean outside the bean definition</title> |
|
|
|
<para>In a bean definition itself, you can supply more than one name |
|
for the bean, by using a combination of up to one name specified by |
|
the <literal>id</literal> attribute, and any number of other names in |
|
the <literal>name</literal> attribute. These names can be equivalent |
|
aliases to the same bean, and are useful for some situations, such as |
|
allowing each component in an application to refer to a common |
|
dependency by using a bean name that is specific to that component |
|
itself.</para> |
|
|
|
<para>Specifying all aliases where the bean is actually defined is not |
|
always adequate, however. It is sometimes desirable to introduce an |
|
alias for a bean that is defined elsewhere. This is commonly the case |
|
in large systems where configuration is split amongst each subsystem, |
|
each subsystem having its own set of object defintions. In XML-based |
|
configuration metadata, you can use of the |
|
<literal><alias/></literal> element to accomplish this.</para> |
|
|
|
<programlisting language="xml"><alias name="fromName" alias="toName"/></programlisting> |
|
|
|
<para>In this case, a bean in the same container which is named |
|
<literal>fromName</literal>, may also after the use of this alias |
|
definition, be referred to as <literal>toName</literal>.</para> |
|
|
|
<!-- MLP: Beverly to review --> |
|
|
|
<para>For example, the configuration metadata for subsystem A may |
|
refer to a DataSource via the name 'subsystemA-dataSource. The |
|
configuration metadata for subsystem B may refer to a DataSource via |
|
the name 'subsystemB-dataSource'. When composing the main application |
|
that uses both these subsystems the main application refers to the |
|
DataSource via the name 'myApp-dataSource'. To have all three names |
|
refer to the same object you add to the MyApp configuration metadata |
|
the following aliases definitions:</para> |
|
|
|
<programlisting language="xml"><alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/> |
|
<alias name="subsystemA-dataSource" alias="myApp-dataSource" /></programlisting> |
|
|
|
<para>Now each component and the main application can refer to the |
|
dataSource through a name that is unique and guaranteed not to clash |
|
with any other definition (effectively creating a namespace), yet they |
|
refer to the same bean.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-class"> |
|
<title>Instantiating beans</title> |
|
|
|
<para>A bean definition essentially is a recipe for creating one or more |
|
objects. The container looks at the recipe for a named bean when asked, |
|
and uses the configuration metadata encapsulated by that bean definition |
|
to create (or acquire) an actual object.</para> |
|
|
|
<para>If you use XML-based configuration metadata, you specify the type |
|
(or class) of object that is to be instantiated in the |
|
<literal>class</literal> attribute of the |
|
<literal><bean/></literal> element. This <literal>class</literal> |
|
attribute, which internally is a <classname>Class</classname> property |
|
on a <interfacename>BeanDefinition</interfacename> instance, is usually |
|
mandatory. (For exceptions, see <xref |
|
linkend="beans-factory-class-instance-factory-method" /> and <xref |
|
linkend="beans-child-bean-definitions" />.) You use the |
|
<classname>Class</classname> property in one of two ways: <itemizedlist> |
|
<listitem> |
|
<para>Typically, to specify the bean class to be constructed in |
|
the case where the container itself directly creates the bean by |
|
calling its constructor reflectively, somewhat equivalent to Java |
|
code using the <code>new</code> operator.</para> |
|
</listitem> |
|
</itemizedlist></para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>To specify the actual class containing the |
|
<literal>static</literal> factory method that will be invoked to |
|
create the object, in the less common case where the container |
|
invokes a <literal>static</literal>, <emphasis>factory</emphasis> |
|
method on a class to create the bean. The object type returned from |
|
the invocation of the <literal>static</literal> factory method may |
|
be the same class or another class entirely.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<sidebar> |
|
<title>Inner class names</title> |
|
|
|
<para>If you want to configure a bean definition for a |
|
<literal>static</literal> nested class, you have to use the |
|
<emphasis>binary</emphasis> name of the inner class.</para> |
|
|
|
<para>For example, if you have a class called |
|
<classname>Foo</classname> in the <literal>com.example</literal> |
|
package, and this <classname>Foo</classname> class has a |
|
<literal>static</literal> inner class called |
|
<classname>Bar</classname>, the value of the |
|
<literal>'class'</literal> attribute on a bean definition would |
|
be...</para> |
|
|
|
<para><classname>com.example.Foo$Bar</classname></para> |
|
|
|
<para>Notice the use of the <literal>$</literal> character in the name |
|
to separate the inner class name from the outer class name.</para> |
|
</sidebar> |
|
|
|
<section id="beans-factory-class-ctor"> |
|
<title>Instantiation with a constructor</title> |
|
|
|
<para>When you create a bean by the constructor approach, all normal |
|
classes are usable by and compatible with Spring. That is, the class |
|
being developed does not need to implement any specific interfaces or |
|
to be coded in a specific fashion. Simply specifying the bean class |
|
should suffice. However, depending on what type of IoC you use for |
|
that specific bean, you may need a default (empty) constructor.</para> |
|
|
|
<para>The Spring IoC container can manage virtually |
|
<emphasis>any</emphasis> class you want it to manage; it is not |
|
limited to managing true JavaBeans. Most Spring users prefer actual |
|
JavaBeans with only a default (no-argument) constructor and |
|
appropriate setters and getters modeled after the properties in the |
|
container. You can also have more exotic non-bean-style classes in |
|
your container. If, for example, you need to use a legacy connection |
|
pool that absolutely does not adhere to the JavaBean specification, |
|
Spring can manage it as well.</para> |
|
|
|
<para>With XML-based configuration metadata you can specify your bean |
|
class as follows:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"/> |
|
|
|
<bean name="anotherExample" class="examples.ExampleBeanTwo"/></programlisting> |
|
|
|
<para>For details about the mechanism for supplying arguments to the |
|
constructor (if required) and setting object instance properties after |
|
the object is constructed, see <link |
|
linkend="beans-factory-collaborators">Injecting |
|
Dependencies</link>.</para> |
|
</section> |
|
|
|
<section id="beans-factory-class-static-factory-method"> |
|
<title>Instantiation with a static factory method</title> |
|
|
|
<para>When defining a bean that you create with a static factory |
|
method, you use the <literal>class</literal> attribute to specify the |
|
class containing the <literal>static</literal> factory method and an |
|
attribute named <literal>factory-method</literal> to specify the name |
|
of the factory method itself. You should be able to call this method |
|
(with optional arguments as described later) and return a live object, |
|
which subsequently is treated as if it had been created through a |
|
constructor. One use for such a bean definition is to call |
|
<literal>static</literal> factories in legacy code.</para> |
|
|
|
<para>The following bean definition specifies that the bean will be |
|
created by calling a factory-method. The definition does not specify |
|
the type (class) of the returned object, only the class containing the |
|
factory method. In this example, the |
|
<methodname>createInstance()</methodname> method must be a |
|
<emphasis>static</emphasis> method.</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" |
|
class="examples.ExampleBean2" |
|
factory-method="createInstance"/></programlisting> |
|
|
|
<para>For details about the mechanism for supplying (optional) |
|
arguments to the factory method and setting object instance properties |
|
after the object is returned from the factory, see <link |
|
linkend="beans-factory-properties-detailed">Dependencies and |
|
configuration in detail</link>.</para> |
|
</section> |
|
|
|
<section id="beans-factory-class-instance-factory-method"> |
|
<title>Instantiation using an instance factory method</title> |
|
|
|
<para>Similar to instantiation through a <link |
|
linkend="beans-factory-class-static-factory-method">static factory |
|
method</link>, instantiation with an instance factory method invokes a |
|
non-static method of an existing bean from the container to create a |
|
new bean. To use this mechanism, leave the <literal>class |
|
</literal>attribute empty, and in the <literal>factory-bean</literal> |
|
attribute, specify the name of a bean in the current (or |
|
parent/ancestor) container that contains the instance method that is |
|
to be invoked to create the object. Set the name of the factory method |
|
itself with the <literal>factory-method</literal> attribute.</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- the factory bean, which contains a method called <methodname>createInstance()</methodname> --></lineannotation> |
|
<bean id="serviceLocator" class="com.foo.DefaultServiceLocator"> |
|
<lineannotation><!-- inject any dependencies required by this locator bean --></lineannotation> |
|
</bean> |
|
|
|
<lineannotation><!-- the bean to be created via the factory bean --></lineannotation> |
|
<bean id="exampleBean" |
|
factory-bean="serviceLocator" |
|
factory-method="createInstance"/></programlisting> |
|
|
|
<para>This approach shows that the factory bean itself can be managed |
|
and configured through dependency injection (DI). See <link |
|
linkend="beans-factory-properties-detailed"><link |
|
linkend="beans-factory-properties-detailed">Dependencies and |
|
configuration in detail</link>.</link></para> |
|
|
|
<note> |
|
<para>In Spring documentation,<emphasis> factory bean</emphasis> |
|
refers to a bean that is configured in the Spring container that |
|
will create objects through an <link |
|
linkend="beans-factory-class-instance-factory-method">instance</link> |
|
or <link |
|
linkend="beans-factory-class-static-factory-method">static</link> |
|
factory method. By contrast, |
|
<interfacename>FactoryBean</interfacename> (notice the |
|
capitalization) refers to a Spring-specific <link |
|
linkend="beans-factory-extension-factorybean"> |
|
<interfacename>FactoryBean</interfacename> </link>.</para> |
|
</note> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-dependencies"> |
|
<title>Dependencies</title> |
|
|
|
<para>A typical enterprise application does not consist of a single object |
|
(or bean in the Spring parlance). Even the simplest application has a few |
|
objects that work together to present what the end-user sees as a coherent |
|
application. This next section explains how you go from defining a number |
|
of bean definitions that stand alone to a fully realized application where |
|
objects collaborate to achieve a goal.</para> |
|
|
|
<section id="beans-factory-collaborators"> |
|
<title>Dependency injection</title> |
|
|
|
<!-- MLP: Beverly review the following two paragraphs --> |
|
|
|
<para><emphasis>Dependency injection</emphasis> (DI) is a process |
|
whereby objects define their dependencies, that is, the other objects |
|
they work with, only through constructor arguments, arguments to a |
|
factory method, or properties that are set on the object instance after |
|
it is constructed or returned from a factory method. The container then |
|
<emphasis>injects</emphasis> those dependencies when it creates the |
|
bean. This process is fundamentally the inverse, hence the name |
|
<emphasis>Inversion of Control</emphasis> (IoC), of the bean itself |
|
controlling the instantiation or location of its dependencies on its own |
|
by using direct construction of classes, or the <emphasis>Service |
|
Locator</emphasis> pattern.</para> |
|
|
|
<para>Code is cleaner with the DI principle and decoupling is more |
|
effective when objects are provided with their dependencies. The object |
|
does not look up its dependencies, and does not know the location or |
|
class of the dependencies. As such, your classes become easier to test, |
|
in particular when the dependencies are on interfaces or abstract base |
|
classes, which allow for stub or mock implementations to be used in unit |
|
tests.</para> |
|
|
|
<para>DI exists in two major variants, <link |
|
linkend="beans-constructor-injection">Constructor-based dependency |
|
injection</link> and <link linkend="beans-setter-injection">Setter-based |
|
dependency injection</link>.</para> |
|
|
|
<section id="beans-constructor-injection"> |
|
<title>Constructor-based dependency injection</title> |
|
|
|
<para><emphasis>Constructor-based</emphasis> DI is accomplished by the |
|
container invoking a constructor with a number of arguments, each |
|
representing a dependency. Calling a <literal>static</literal> factory |
|
method with specific arguments to construct the bean is nearly |
|
equivalent, and this discussion treats arguments to a constructor and |
|
to a <literal>static</literal> factory method similarly. The following |
|
example shows a class that can only be dependency-injected with |
|
constructor injection. Notice that there is nothing |
|
<emphasis>special</emphasis> about this class, it is a POJO that has |
|
no dependencies on container specific interfaces, base classes or |
|
annotations.</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on a <interfacename>MovieFinder</interfacename></lineannotation> |
|
private MovieFinder movieFinder; |
|
|
|
<lineannotation>// a constructor so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation> |
|
public SimpleMovieLister(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation> |
|
}</programlisting> |
|
|
|
<section id="beans-factory-ctor-arguments-resolution"> |
|
<title>Constructor argument resolution</title> |
|
|
|
<para>Constructor argument resolution matching occurs using the |
|
argument's type. If no potential ambiguity exists in the constructor |
|
arguments of a bean definition, then the order in which the |
|
constructor arguments are defined in a bean definition is the order |
|
in which those arguments are supplied to the appropriate constructor |
|
when the bean is being instantiated. Consider the following |
|
class:</para> |
|
|
|
<programlisting language="java">package x.y; |
|
|
|
public class Foo { |
|
|
|
public Foo(Bar bar, Baz baz) { |
|
<lineannotation>// ...</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>No potential ambiguity exists, assuming that |
|
<classname>Bar</classname> and <classname>Baz</classname> classes |
|
are not related by inheritance. Thus the following configuration |
|
works fine, and you do not need to specify the constructor argument |
|
indexes and/or types explicitly in the |
|
<literal><constructor-arg/></literal> element.</para> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="foo" class="x.y.Foo"> |
|
<constructor-arg ref="bar"/> |
|
<constructor-arg ref="baz"/> |
|
</bean> |
|
|
|
<bean id="bar" class="x.y.Bar"/> |
|
<bean id="baz" class="x.y.Baz"/> |
|
|
|
</beans></programlisting> |
|
|
|
<para>When another bean is referenced, the type is known, and |
|
matching can occur (as was the case with the preceding example). |
|
When a simple type is used, such as |
|
<literal><value>true<value></literal>, Spring cannot |
|
determine the type of the value, and so cannot match by type without |
|
help. Consider the following class:</para> |
|
|
|
<programlisting language="java">package examples; |
|
|
|
public class ExampleBean { |
|
|
|
<lineannotation>// No. of years to the calculate the Ultimate Answer</lineannotation> |
|
private int years; |
|
|
|
<lineannotation>// The Answer to Life, the Universe, and Everything</lineannotation> |
|
private String ultimateAnswer; |
|
|
|
public ExampleBean(int years, String ultimateAnswer) { |
|
this.years = years; |
|
this.ultimateAnswer = ultimateAnswer; |
|
} |
|
}</programlisting> |
|
|
|
<section id="beans-factory-ctor-arguments-type"> |
|
<title>Constructor argument type matching</title> |
|
|
|
<para>In the preceding scenario, the container |
|
<emphasis>can</emphasis> use type matching with simple types if |
|
you explicitly specify the type of the constructor argument using |
|
the <literal>type</literal> attribute. For example:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
<constructor-arg type="int" value="7500000"/> |
|
<constructor-arg type="java.lang.String" value="42"/> |
|
</bean></programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-ctor-arguments-index"> |
|
<title>Constructor argument index</title> |
|
|
|
<para>Use the <literal>index</literal> attribute to specify |
|
explicitly the index of constructor arguments. For example:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
<constructor-arg index="0" value="7500000"/> |
|
<constructor-arg index="1" value="42"/> |
|
</bean></programlisting> |
|
|
|
<para>In addition to resolving the ambiguity of multiple simple |
|
values, specifying an index resolves ambiguity where a constructor |
|
has two arguments of the same type. Note that the <emphasis>index |
|
is 0 based</emphasis>.</para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-setter-injection"> |
|
<title>Setter-based dependency injection</title> |
|
|
|
<para><emphasis>Setter-based</emphasis> DI is accomplished by the |
|
container calling setter methods on your beans after invoking a |
|
no-argument constructor or no-argument <literal>static</literal> |
|
factory method to instantiate your bean.</para> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> supports |
|
constructor- and setter-based DI for the beans it manages. It also |
|
supports setter-based DI after some dependencies are already injected |
|
through the constructor approach.</para> |
|
|
|
<para>The following example shows a class that can only be |
|
dependency-injected using pure setter injection. This class is |
|
conventional Java. It is a POJO that has no dependencies on container |
|
specific interfaces, base classes or annotations.</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on the <interfacename>MovieFinder</interfacename></lineannotation> |
|
private MovieFinder movieFinder; |
|
|
|
<lineannotation>// a setter method so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation> |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> supports |
|
constructor- and setter-based DI for the beans it manages. It also |
|
supports setter-based DI after some dependencies are already injected |
|
through the constructor approach. You configure the dependencies in |
|
the form of a <interfacename>BeanDefinition</interfacename>, which you |
|
use with <interfacename>PropertyEditor</interfacename> instances to |
|
convert properties from one format to another. However, most Spring |
|
users do not work with these classes directly (programmatically), but |
|
rather with an XML definition file that is then converted internally |
|
into instances of these classes, and used to load an entire Spring IoC |
|
container instance.</para> |
|
|
|
<sidebar> |
|
<title>Constructor-based or setter-based DI?</title> |
|
|
|
<para>Since you can mix both, Constructor- and Setter-based DI, it |
|
is a good rule of thumb to use constructor arguments for mandatory |
|
dependencies and setters for optional dependencies. Note that the |
|
use of a <link linkend="beans-required-annotation">@Required</link> |
|
annotation on a setter can be used to make setters required |
|
dependencies.</para> |
|
|
|
<para>The Spring team generally advocates setter injection, because |
|
large numbers of constructor arguments can get unwieldy, especially |
|
when properties are optional. Setter methods also make objects of |
|
that class amenable to reconfiguration or re-injection later. |
|
Management through <link linkend="jmx">JMX MBeans</link> is a |
|
compelling use case.</para> |
|
|
|
<para>Some purists favor constructor-based injection. Supplying all |
|
object dependencies means that the object is always returned to |
|
client (calling) code in a totally initialized state. The |
|
disadvantage is that the object becomes less amenable to |
|
reconfiguration and re-injection.</para> |
|
|
|
<para>Use the DI that makes the most sense for a particular class. |
|
Sometimes, when dealing with third-party classes to which you do not |
|
have the source, the choice is made for you. A legacy class may not |
|
expose any setter methods, and so constructor injection is the only |
|
available DI.</para> |
|
</sidebar> |
|
</section> |
|
|
|
<section> |
|
<title>Dependency resolution process</title> |
|
|
|
<para>The container performs bean dependency resolution as |
|
follows:</para> |
|
|
|
<!-- MLP: Beverly to review all list items--> |
|
|
|
<orderedlist> |
|
<listitem> |
|
<para>The <interfacename>ApplicationContext</interfacename> is |
|
created an initialized with configuration metadata that describes |
|
all the beans. Configuration metadata can be specified via XML, |
|
Java code or annotations.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>For each bean, its dependencies are expressed in the form of |
|
properties, constructor arguments, or arguments to the |
|
static-factory method if you are using that instead of a normal |
|
constructor. These dependencies are provided to the bean, |
|
<emphasis>when the bean is actually created</emphasis>.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Each property or constructor argument an actual definition |
|
of the value to set, or a reference to another bean in the |
|
container.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Each property or constructor argument which is a value is |
|
converted from its specified format to the actual type of that |
|
property or constructor argument. By default Spring can convert a |
|
value supplied in string format to all built-in types, such as |
|
<literal>int</literal>, <literal>long</literal>, |
|
<literal>String</literal>, <literal>boolean</literal>, etc.</para> |
|
</listitem> |
|
</orderedlist> |
|
|
|
<para>The Spring container validates the configuration of each bean as |
|
the container is created, including the validation of whether bean |
|
reference properties refer to valid beans. However, the bean |
|
properties themselves are not set until the bean <emphasis>is actually |
|
created</emphasis>. Beans that are singleton-scoped and set to be |
|
pre-instantiated (the default) are created when the container is |
|
created. Scopes are defined in <xref linkend="beans-factory-scopes" /> |
|
Otherwise, the bean is created only when it is requested. Creation of |
|
a bean potentially causes a graph of beans to be created, as the |
|
bean's dependencies and its dependencies' dependencies (and so on) are |
|
created and assigned.</para> |
|
|
|
<sidebar> |
|
<title>Circular dependencies</title> |
|
|
|
<para>If you use predominantly constructor injection, it is possible |
|
to create an unresolvable circular dependency scenario.</para> |
|
|
|
<para>For example: Class A requires an instance of class B through |
|
constructor injection, and class B requires an instance of class A |
|
through constructor injection. If you configure beans for classes A |
|
and B to be injected into each other, the Spring IoC container |
|
detects this circular reference at runtime, and throws a |
|
<classname>BeanCurrentlyInCreationException</classname>.</para> |
|
|
|
<para>One possible solution is to edit the source code of some |
|
classes to be configured by setters rather than constructors. |
|
Alternatively, avoid constructor injection and use setter injection |
|
only. In other words, although it is not recommended, you can |
|
configure circular dependencies with setter injection.</para> |
|
|
|
<para>Unlike the <emphasis>typical</emphasis> case (with no circular |
|
dependencies), a circular dependency between bean A and bean B |
|
forces one of the beans to be injected into the other prior to being |
|
fully initialized itself (a classic chicken/egg scenario).</para> |
|
</sidebar> |
|
|
|
<para>You can generally trust Spring to do the right thing. It detects |
|
configuration problems, such as references to non-existent beans and |
|
circular dependencies, at container load-time. Spring sets properties |
|
and resolves dependencies as late as possible, when the bean is |
|
actually created. This means that a Spring container which has loaded |
|
correctly can later generate an exception when you request an object |
|
if there is a problem creating that object or one of its dependencies. |
|
For example, the bean throws an exception as a result of a missing or |
|
invalid property. This potentially delayed visibility of some |
|
configuration issues is why |
|
<interfacename>ApplicationContext</interfacename> implementations by |
|
default pre-instantiate singleton beans. At the cost of some upfront |
|
time and memory to create these beans before they are actually needed, |
|
you discover configuration issues when the |
|
<interfacename>ApplicationContext</interfacename> is created, not |
|
later. You can still override this default behavior so that singleton |
|
beans will lazy-initialize, rather than be pre-instantiated.</para> |
|
|
|
<para>If no circular dependencies exist, when one or more |
|
collaborating beans are being injected into a dependent bean, each |
|
collaborating bean is <emphasis>totally</emphasis> configured prior to |
|
being injected into the dependent bean. This means that if bean A has |
|
a dependency on bean B, the Spring IoC container completely configures |
|
bean B prior to invoking the setter method on bean A. In other words, |
|
the bean is instantiated (if not a pre-instantiated singleton), its |
|
dependencies are set, and the relevant lifecycle methods (such as a |
|
<link linkend="beans-factory-lifecycle-initializingbean">configured |
|
init method</link> or the <link |
|
linkend="beans-factory-lifecycle-initializingbean">IntializingBean |
|
callback method</link>) are invoked.</para> |
|
</section> |
|
|
|
<section id="beans-some-examples"> |
|
<title>Examples of dependency injection</title> |
|
|
|
<para>The following example uses XML-based configuration metadata for |
|
setter-based DI. A small part of a Spring XML configuration file |
|
specifies some bean definitions:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
|
|
<lineannotation><!-- setter injection using the nested <literal><ref/></literal> element --></lineannotation> |
|
<property name="beanOne"><ref bean="anotherExampleBean"/></property> |
|
|
|
<lineannotation><!-- setter injection using the neater 'ref' attribute --></lineannotation> |
|
<property name="beanTwo" ref="yetAnotherBean"/> |
|
<property name="integerProperty" value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
private AnotherBean beanOne; |
|
private YetAnotherBean beanTwo; |
|
private int i; |
|
|
|
public void setBeanOne(AnotherBean beanOne) { |
|
this.beanOne = beanOne; |
|
} |
|
|
|
public void setBeanTwo(YetAnotherBean beanTwo) { |
|
this.beanTwo = beanTwo; |
|
} |
|
|
|
public void setIntegerProperty(int i) { |
|
this.i = i; |
|
} |
|
}</programlisting> |
|
|
|
<para>In the preceding example, setters are declared to match against |
|
the properties specified in the XML file. The following example uses |
|
constructor-based DI:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean"> |
|
|
|
<lineannotation><!-- constructor injection using the nested <literal><ref/></literal> element --></lineannotation> |
|
<constructor-arg> |
|
<ref bean="anotherExampleBean"/> |
|
</constructor-arg> |
|
|
|
<lineannotation><!-- constructor injection using the neater 'ref' attribute --></lineannotation> |
|
<constructor-arg ref="yetAnotherBean"/> |
|
|
|
<constructor-arg type="int" value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
private AnotherBean beanOne; |
|
private YetAnotherBean beanTwo; |
|
private int i; |
|
|
|
public ExampleBean( |
|
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { |
|
this.beanOne = anotherBean; |
|
this.beanTwo = yetAnotherBean; |
|
this.i = i; |
|
} |
|
}</programlisting> |
|
|
|
<para>The constructor arguments specified in the bean definition will |
|
be used as arguments to the constructor of the |
|
<classname>ExampleBean</classname>.</para> |
|
|
|
<para>Now consider a variant of this example, where instead of using a |
|
constructor, Spring is told to call a <literal>static</literal> |
|
factory method to return an instance of the object:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleBean" class="examples.ExampleBean" |
|
factory-method="createInstance"> |
|
<constructor-arg ref="anotherExampleBean"/> |
|
<constructor-arg ref="yetAnotherBean"/> |
|
<constructor-arg value="1"/> |
|
</bean> |
|
|
|
<bean id="anotherExampleBean" class="examples.AnotherBean"/> |
|
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
<lineannotation>// a private constructor</lineannotation> |
|
private ExampleBean(...) { |
|
... |
|
} |
|
<lineannotation> |
|
// a static factory method; the arguments to this method can be |
|
// considered the dependencies of the bean that is returned, |
|
// regardless of how those arguments are actually used.</lineannotation> |
|
public static ExampleBean createInstance ( |
|
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) { |
|
|
|
ExampleBean eb = new ExampleBean (...); |
|
<lineannotation>// some other operations...</lineannotation> |
|
return eb; |
|
} |
|
}</programlisting> |
|
|
|
<para>Arguments to the <literal>static</literal> factory method are |
|
supplied via <literal><constructor-arg/></literal> elements, |
|
exactly the same as if a constructor had actually been used. The type |
|
of the class being returned by the factory method does not have to be |
|
of the same type as the class that contains the |
|
<literal>static</literal> factory method, although in this example it |
|
is. An instance (non-static) factory method would be used in an |
|
essentially identical fashion (aside from the use of the |
|
<literal>factory-bean</literal> attribute instead of the |
|
<literal>class</literal> attribute), so details will not be discussed |
|
here.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-properties-detailed"> |
|
<title>Dependencies and configuration in detail</title> |
|
|
|
<para>As mentioned in the previous section, you can define bean |
|
properties and constructor arguments as references to other managed |
|
beans (collaborators), or as values defined inline. Spring's XML-based |
|
configuration metadata supports sub-element types within its |
|
<literal><property/></literal> and |
|
<literal><constructor-arg/></literal> elements for this |
|
purpose.</para> |
|
|
|
<section id="beans-value-element"> |
|
<title>Straight values (primitives, <literal>Strings</literal>, and so |
|
on)</title> |
|
|
|
<para>The <literal>value</literal> attribute of the |
|
<literal><property/></literal> element specifies a property or |
|
constructor argument as a human-readable string representation. <link |
|
linkend="beans-factory-collaborators-propertyeditor">As mentioned |
|
previously</link>, JavaBeans <literal>PropertyEditors</literal> are |
|
used to convert these string values from a |
|
<classname>String</classname> to the actual type of the property or |
|
argument.</para> |
|
|
|
<programlisting language="xml"><bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> |
|
|
|
<lineannotation><!-- results in a <methodname>setDriverClassName(String)</methodname> call --></lineannotation> |
|
<property name="driverClassName" value="com.mysql.jdbc.Driver"/> |
|
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/> |
|
<property name="username" value="root"/> |
|
<property name="password" value="masterkaoli"/> |
|
</bean></programlisting> |
|
|
|
<para>The following example uses the <link |
|
linkend="beans-p-namespace">p-namespace</link> for even more succinct |
|
XML configuration.</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" |
|
destroy-method="close" |
|
p:driverClassName="com.mysql.jdbc.Driver" |
|
p:url="jdbc:mysql://localhost:3306/mydb" |
|
p:username="root" |
|
p:password="masterkaoli"/> |
|
|
|
</beans> |
|
|
|
</programlisting> |
|
|
|
<para>The preceding XML is more succinct; however, typos are |
|
discovered at runtime rather than design time, unless you use an IDE |
|
such as <ulink url="http://www.jetbrains.com/idea/">IntelliJ |
|
IDEA</ulink> or the <ulink |
|
url="http://www.springsource.com/products/sts">SpringSource Tool |
|
Suite</ulink> (STS) that support automatic property completion when |
|
you create bean definitions. Such IDE assistance is highly |
|
recommended.</para> |
|
|
|
<para>You can also configure a |
|
<classname>java.util.Properties</classname> instance as:</para> |
|
|
|
<programlisting language="xml"><bean id="mappings" |
|
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> |
|
|
|
<lineannotation><!-- typed as a <classname>java.util.Properties</classname> --></lineannotation> |
|
<property name="properties"> |
|
<value> |
|
jdbc.driver.className=com.mysql.jdbc.Driver |
|
jdbc.url=jdbc:mysql://localhost:3306/mydb |
|
</value> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>The Spring container converts the text inside the |
|
<literal><value/></literal> element into a |
|
<classname>java.util.Properties</classname> instance by using the |
|
JavaBeans <interfacename>PropertyEditor</interfacename> mechanism. |
|
This is a nice shortcut, and is one of a few places where the Spring |
|
team do favor the use of the nested <literal><value/></literal> |
|
element over the <literal>value</literal> attribute style.</para> |
|
|
|
<section id="beans-idref-element"> |
|
<title>The <literal>idref</literal> element</title> |
|
|
|
<para>The <literal>idref</literal> element is simply an error-proof |
|
way to pass the <emphasis>id</emphasis> (string value - not a |
|
reference) of another bean in the container to a |
|
<literal><constructor-arg/></literal> or |
|
<literal><property/></literal> element.</para> |
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..."/> |
|
|
|
<bean id="theClientBean" class="..."> |
|
<property name="targetName"> |
|
<idref bean="theTargetBean" /> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>The above bean definition snippet is |
|
<emphasis>exactly</emphasis> equivalent (at runtime) to the |
|
following snippet:</para> |
|
|
|
<programlisting language="xml"><bean id="theTargetBean" class="..." /> |
|
|
|
<bean id="client" class="..."> |
|
<property name="targetName" value="theTargetBean" /> |
|
</bean></programlisting> |
|
|
|
<para>The first form is preferable to the second, because using the |
|
<literal>idref</literal> tag allows the container to validate |
|
<emphasis>at deployment time</emphasis> that the referenced, named |
|
bean actually exists. In the second variation, no validation is |
|
performed on the value that is passed to the |
|
<literal>targetName</literal> property of the |
|
<literal>client</literal> bean. Typos are only discovered (with most |
|
likely fatal results) when the <literal>client</literal> bean is |
|
actually instantiated. If the <literal>client</literal> bean is a |
|
<link linkend="beans-factory-scopes">prototype</link> bean, this |
|
typo and the resulting exception may only be discovered long after |
|
the container is deployed.</para> |
|
|
|
<para>Additionally, if the referenced bean is in the same XML unit, |
|
and the bean name is the bean <emphasis>id</emphasis>, you can use |
|
the <literal>local</literal> attribute, which allows the XML parser |
|
itself to validate the bean id earlier, at XML document parse |
|
time.</para> |
|
|
|
<programlisting language="xml"><property name="targetName"> |
|
<lineannotation><!-- a bean with id '<literal>theTargetBean</literal>' must exist; otherwise an exception will be thrown --></lineannotation> |
|
<idref local="theTargetBean"/> |
|
</property></programlisting> |
|
|
|
<para>A common place (at least in versions earlier than Spring 2.0) |
|
where the <idref/> element brings value is in the |
|
configuration of <link linkend="aop-pfb-1">AOP interceptors</link> |
|
in a <classname>ProxyFactoryBean</classname> bean definition. Using |
|
<idref/> elements when you specify the interceptor names |
|
prevents you from misspelling an interceptor id.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-ref-element"> |
|
<title>References to other beans (collaborators)</title> |
|
|
|
<para>The <literal>ref</literal> element is the final element inside a |
|
<literal><constructor-arg/></literal> or |
|
<literal><property/></literal> definition element. Here you set |
|
the value of the specified property of a bean to be a reference to |
|
another bean (a collaborator) managed by the container. The referenced |
|
bean is a dependency of the bean whose property will be set, and it is |
|
initialized on demand as needed before the property is set. (If the |
|
collaborator is a singleton bean, it may be initialized already by the |
|
container.) All references are ultimately a reference to another |
|
object. Scoping and validation depend on whether you specify the |
|
id/name of the other object through the |
|
<literal>bean,<literal>local,</literal></literal> or |
|
<literal>parent</literal> attributes.</para> |
|
|
|
<para>Specifying the target bean through the <literal>bean</literal> |
|
attribute of the <literal><ref/></literal> tag is the most |
|
general form, and allows creation of a reference to any bean in the |
|
same container or parent container, regardless of whether it is in the |
|
same XML file. The value of the <literal>bean</literal> attribute may |
|
be the same as the <literal>id</literal> attribute of the target bean, |
|
or as one of the values in the <literal>name</literal> attribute of |
|
the target bean.</para> |
|
|
|
<programlisting language="xml"><ref bean="someBean"/></programlisting> |
|
|
|
<para>Specifying the target bean through the <literal>local</literal> |
|
attribute leverages the ability of the XML parser to validate XML id |
|
references within the same file. The value of the |
|
<literal>local</literal> attribute must be the same as the |
|
<literal>id</literal> attribute of the target bean. The XML parser |
|
issues an error if no matching element is found in the same file. As |
|
such, using the local variant is the best choice (in order to know |
|
about errors as early as possible) if the target bean is in the same |
|
XML file.</para> |
|
|
|
<programlisting language="xml"><ref local="someBean"/></programlisting> |
|
|
|
<para>Specifying the target bean through the <literal>parent</literal> |
|
attribute creates a reference to a bean that is in a parent container |
|
of the current container. The value of the <literal>parent</literal> |
|
attribute may be the same as either the <literal>id</literal> |
|
attribute of the target bean, or one of the values in the |
|
<literal>name</literal> attribute of the target bean, and the target |
|
bean must be in a parent container of the current one. You use this |
|
bean reference variant mainly when you have a hierarchy of containers |
|
and you want to wrap an existing bean in a parent container with a |
|
proxy that will have the same name as the parent bean.</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- in the parent context --></lineannotation> |
|
<bean id="accountService" class="com.foo.SimpleAccountService"> |
|
<lineannotation><!-- insert dependencies as required as here --></lineannotation> |
|
</bean></programlisting> |
|
|
|
<programlisting language="xml"><lineannotation><!-- in the child (descendant) context --></lineannotation> |
|
<bean id="accountService" <lineannotation><-- bean name is the same as the parent bean --></lineannotation> |
|
class="org.springframework.aop.framework.ProxyFactoryBean"> |
|
<property name="target"> |
|
<ref parent="accountService"/> <lineannotation><!-- notice how we refer to the parent bean --></lineannotation> |
|
</property> |
|
<lineannotation><!-- insert other configuration and dependencies as required here --></lineannotation> |
|
</bean></programlisting> |
|
</section> |
|
|
|
<section id="beans-inner-beans"> |
|
<title>Inner beans</title> |
|
|
|
<para>A <literal><bean/></literal> element inside the |
|
<literal><property/></literal> or |
|
<literal><constructor-arg/></literal> elements defines a |
|
so-called <firstterm>inner bean</firstterm>.</para> |
|
|
|
<programlisting language="xml"><bean id="outer" class="..."> |
|
<lineannotation><!-- instead of using a reference to a target bean, simply define the target bean inline --></lineannotation> |
|
<property name="target"> |
|
<bean class="com.example.Person"> <lineannotation><!-- this is the inner bean --></lineannotation> |
|
<property name="name" value="Fiona Apple"/> |
|
<property name="age" value="25"/> |
|
</bean> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>An inner bean definition does not require a defined id or name; |
|
the container ignores these values. It also ignores the |
|
<literal>scope</literal> flag. Inner beans are |
|
<emphasis>always</emphasis> anonymous and they are |
|
<emphasis>always</emphasis> scoped as <link |
|
linkend="beans-factory-scopes-prototype">prototypes</link>. It is |
|
<emphasis>not</emphasis> possible to inject inner beans into |
|
collaborating beans other than into the enclosing bean.</para> |
|
</section> |
|
|
|
<section id="beans-collection-elements"> |
|
<title>Collections</title> |
|
|
|
<para>In the <literal><list/></literal>, |
|
<literal><set/></literal>, <literal><map/></literal>, and |
|
<literal><props/></literal> elements, you set the properties and |
|
arguments of the Java <interfacename>Collection</interfacename> types |
|
<interfacename>List</interfacename>, |
|
<interfacename>Set</interfacename>, |
|
<interfacename>Map</interfacename>, and |
|
<interfacename>Properties</interfacename>, respectively.</para> |
|
|
|
<programlisting language="xml"><bean id="moreComplexObject" class="example.ComplexObject"> |
|
<lineannotation><!-- results in a setAdminEmails(<classname>java.util.Properties</classname>) call --></lineannotation> |
|
<property name="adminEmails"> |
|
<props> |
|
<prop key="administrator">administrator@example.org</prop> |
|
<prop key="support">support@example.org</prop> |
|
<prop key="development">development@example.org</prop> |
|
</props> |
|
</property> |
|
<lineannotation><!-- results in a setSomeList(<interfacename>java.util.List</interfacename>) call --></lineannotation> |
|
<property name="someList"> |
|
<list> |
|
<value>a list element followed by a reference</value> |
|
<ref bean="myDataSource" /> |
|
</list> |
|
</property> |
|
<lineannotation><!-- results in a setSomeMap(<interfacename>java.util.Map</interfacename>) call --></lineannotation> |
|
<property name="someMap"> |
|
<map> |
|
<entry key="an entry" value="just some string"/> |
|
<entry key ="a ref" value-ref="myDataSource"/> |
|
</map> |
|
</property> |
|
<lineannotation><!-- results in a setSomeSet(java.util.Set) call --></lineannotation> |
|
<property name="someSet"> |
|
<set> |
|
<value>just some string</value> |
|
<ref bean="myDataSource" /> |
|
</set> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para><emphasis>The value of a map key or value, or a set value, can |
|
also again be any of the following elements:</emphasis></para> |
|
|
|
<programlisting language="xml">bean | ref | idref | list | set | map | props | value | null</programlisting> |
|
|
|
<section id="beans-collection-elements-merging"> |
|
<title>Collection merging</title> |
|
|
|
<para>As of Spring 2.0, the container supports the |
|
<emphasis>merging</emphasis> of collections. An application |
|
developer can define a parent-style |
|
<literal><list/></literal>, <literal><map/></literal>, |
|
<literal><set/></literal> or <literal><props/></literal> |
|
element, and have child-style <literal><list/></literal>, |
|
<literal><map/></literal>, <literal><set/></literal> or |
|
<literal><props/></literal> elements inherit and override |
|
values from the parent collection. That is, the child collection's |
|
values are the result of merging the elements of the parent and |
|
child collections, with the child's collection elements overriding |
|
values specified in the parent collection.</para> |
|
|
|
<para><emphasis>This section on merging discusses the parent-child |
|
bean mechanism. Readers unfamiliar with parent and child bean |
|
definitions may wish to read the <link |
|
linkend="beans-child-bean-definitions">relevant section</link> |
|
before continuing.</emphasis></para> |
|
|
|
<para>The following example demonstrates collection merging:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="parent" abstract="true" class="example.ComplexObject"> |
|
<property name="adminEmails"> |
|
<props> |
|
<prop key="administrator">administrator@example.com</prop> |
|
<prop key="support">support@example.com</prop> |
|
</props> |
|
</property> |
|
</bean> |
|
<bean id="child" parent="parent"> |
|
<property name="adminEmails"> |
|
<lineannotation><!-- the merge is specified on the *child* collection definition --></lineannotation> |
|
<props merge="true"> |
|
<prop key="sales">sales@example.com</prop> |
|
<prop key="support">support@example.co.uk</prop> |
|
</props> |
|
</property> |
|
</bean> |
|
<beans></programlisting> |
|
|
|
<para>Notice the use of the <literal>merge=true</literal> attribute |
|
on the <literal><props/></literal> element of the |
|
<literal>adminEmails</literal> property of the |
|
<literal>child</literal> bean definition. When the |
|
<literal>child</literal> bean is resolved and instantiated by the |
|
container, the resulting instance has an |
|
<literal>adminEmails</literal> <classname>Properties</classname> |
|
collection that contains the result of the merging of the child's |
|
<literal>adminEmails</literal> collection with the parent's |
|
<literal>adminEmails</literal> collection.</para> |
|
|
|
<programlisting>administrator=administrator@example.com |
|
sales=sales@example.com |
|
support=support@example.co.uk</programlisting> |
|
|
|
<para>The child <classname>Properties</classname> collection's value |
|
set inherits all property elements from the parent |
|
<literal><props/></literal>, and the child's value for the |
|
<literal>support</literal> value overrides the value in the parent |
|
collection.</para> |
|
|
|
<para>This merging behavior applies similarly to the |
|
<literal><list/></literal>, <literal><map/></literal>, |
|
and <literal><set/></literal> collection types. In the |
|
specific case of the <literal><list/></literal> element, the |
|
semantics associated with the <classname>List</classname> collection |
|
type, that is, the notion of an <literal>ordered</literal> |
|
collection of values, is maintained; the parent's values precede all |
|
of the child list's values. In the case of the |
|
<interfacename>Map</interfacename>, |
|
<interfacename>Set</interfacename>, and |
|
<interfacename>Properties</interfacename> collection types, no |
|
ordering exists. Hence no ordering semantics are in effect for the |
|
collection types that underlie the associated |
|
<interfacename>Map</interfacename>, |
|
<interfacename>Set</interfacename>, and |
|
<interfacename>Properties</interfacename> implementation types that |
|
the container uses internally.</para> |
|
</section> |
|
|
|
<section> |
|
<title>Limitations of collection merging</title> |
|
|
|
<para>You cannot merge different collection types (such as a |
|
<interfacename>Map</interfacename> and a |
|
<interfacename>List</interfacename>), and if you do attempt to do so |
|
an appropriate <classname>Exception</classname> is thrown. The |
|
<literal>merge</literal> attribute must be specified on the lower, |
|
inherited, child definition; specifying the <literal>merge</literal> |
|
attribute on a parent collection definition is redundant and will |
|
not result in the desired merging. The merging feature is available |
|
only in Spring 2.0 and later.</para> |
|
</section> |
|
|
|
<section id="beans-collection-elements-strongly-typed"> |
|
<title>Strongly-typed collection (Java 5+ only)</title> |
|
|
|
<para>In Java 5 and later, you can use strongly typed collections |
|
(using generic types). That is, it is possible to declare a |
|
<interfacename>Collection</interfacename> type such that it can only |
|
contain <classname>String</classname> elements (for example). If you |
|
are using Spring to dependency-inject a strongly-typed |
|
<interfacename>Collection</interfacename> into a bean, you can take |
|
advantage of Spring's type-conversion support such that the elements |
|
of your strongly-typed <interfacename>Collection</interfacename> |
|
instances are converted to the appropriate type prior to being added |
|
to the <interfacename>Collection</interfacename>.</para> |
|
|
|
<programlisting language="java">public class Foo { |
|
|
|
private Map<String, Float> accounts; |
|
|
|
public void setAccounts(Map<String, Float> accounts) { |
|
this.accounts = accounts; |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="foo" class="x.y.Foo"> |
|
<property name="accounts"> |
|
<map> |
|
<entry key="one" value="9.99"/> |
|
<entry key="two" value="2.75"/> |
|
<entry key="six" value="3.99"/> |
|
</map> |
|
</property> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<para>When the <literal>accounts</literal> property of the |
|
<literal>foo</literal> bean is prepared for injection, the generics |
|
information about the element type of the strongly-typed |
|
<classname>Map<String, Float></classname> is available by |
|
reflection. Thus Spring's type conversion infrastructure recognizes |
|
the various value elements as being of type |
|
<classname>Float</classname>, and the string values <literal>9.99, |
|
2.75</literal>, and <literal>3.99</literal> are converted into an |
|
actual <classname>Float</classname> type.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-null-element"> |
|
<title>Null and empty string values</title> |
|
|
|
<para><!--Clarify difference between null value and empty string value?-->Spring |
|
treats empty arguments for properties and the like as empty |
|
<literal>Strings</literal>. The following XML-based configuration |
|
metadata snippet sets the email property to the empty |
|
<classname>String</classname> value ("")</para> |
|
|
|
<programlisting language="xml"><bean class="ExampleBean"> |
|
<property name="email" value=""/> |
|
</bean></programlisting> |
|
|
|
<para>The preceding example is equivalent to the following Java code: |
|
<methodname>exampleBean.setEmail("")</methodname>. The |
|
<literal><null/></literal> element handles |
|
<literal>null</literal> values. For example:</para> |
|
|
|
<programlisting language="xml"><bean class="ExampleBean"> |
|
<property name="email"><null/></property> |
|
</bean></programlisting> |
|
|
|
<para>The above configuration is equivalent to the following Java |
|
code: <methodname>exampleBean.setEmail(null)</methodname>.</para> |
|
</section> |
|
|
|
<section id="beans-p-namespace"> |
|
<title>XML shortcut with the p-namespace</title> |
|
|
|
<para>The p-namespace enables you to use the <literal>bean</literal> |
|
element's attributes, instead of nested |
|
<literal><property/></literal> elements, to describe your |
|
property values and/or collaborating beans.</para> |
|
|
|
<para>Spring 2.0 and later supports extensible configuration formats |
|
<link linkend="xsd-config">with namespaces</link>, which are based on |
|
an XML Schema definition. The <literal>beans</literal> configuration |
|
format discussed in this chapter is defined in an XML Schema document. |
|
However, the p-namespace is not defined in an XSD file and exists only |
|
in the core of Spring.</para> |
|
|
|
<para>The following example shows two XML snippets that resolve to the |
|
same result: The first uses standard XML format and the second uses |
|
the p-namespace.</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean name="classic" class="com.example.ExampleBean"> |
|
<property name="email" value="foo@bar.com"/> |
|
</bean> |
|
|
|
<bean name="p-namespace" class="com.example.ExampleBean" |
|
p:email="foo@bar.com"/> |
|
</beans></programlisting> |
|
|
|
<para>The example shows an attribute in the p-namespace called email |
|
in the bean definition. This tells Spring to include a property |
|
declaration. As previously mentioned, the p-namespace not have a |
|
schema definition, so you can set the name of the attribute to the |
|
property name.</para> |
|
|
|
<para>This next example includes two more bean definitions that both |
|
have a reference to another bean:</para> |
|
|
|
<programlisting language="xml"><beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:p="http://www.springframework.org/schema/p" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> |
|
|
|
<bean name="john-classic" class="com.example.Person"> |
|
<property name="name" value="John Doe"/> |
|
<property name="spouse" ref="jane"/> |
|
</bean> |
|
|
|
<bean name="john-modern" |
|
class="com.example.Person" |
|
p:name="John Doe" |
|
p:spouse-ref="jane"/> |
|
|
|
<bean name="jane" class="com.example.Person"> |
|
<property name="name" value="Jane Doe"/> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<para>As you can see, this example includes not only a property value |
|
using the p-namespace, but also uses a special format to declare |
|
property references. Whereas the first bean definition uses |
|
<literal><property name="spouse" ref="jane"/></literal> to |
|
create a reference from bean <literal>john</literal> to bean |
|
<literal>jane</literal>, the second bean definition uses |
|
<literal>p:spouse-ref="jane"</literal> as an attribute to do the exact |
|
same thing. In this case <literal>spouse</literal> is the property |
|
name, whereas the <literal>-ref</literal> part indicates that this is |
|
not a straight value but rather a reference to another bean.</para> |
|
|
|
<note> |
|
<para>The p-namespace is not as flexible as the standard XML format. |
|
For example, the format for declaring property references clashes |
|
with properties that end in <literal>Ref</literal>, whereas the |
|
standard XML format does not. We recommend that you choose your |
|
approach carefully and communicate this to your team members, to |
|
avoid producing XML documents that use all three approaches at the |
|
same time.<!--Clarify ref to all three approaches.I see two, XML and namespace.--></para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-compound-property-names"> |
|
<title>Compound property names</title> |
|
|
|
<para>You can use compound or nested property names when you set bean |
|
properties, as long as all components of the path except the final |
|
property name are not <literal>null</literal>. Consider the following |
|
bean definition.</para> |
|
|
|
<programlisting language="xml"><bean id="foo" class="foo.Bar"> |
|
<property name="fred.bob.sammy" value="123" /> |
|
</bean></programlisting> |
|
|
|
<para>The <literal>foo</literal> bean has a <literal>fred</literal> |
|
property, which has a <literal>bob</literal> property, which has a |
|
<literal>sammy</literal> property, and that final |
|
<literal>sammy</literal> property is being set to the value |
|
<literal>123</literal>. In order for this to work, the |
|
<literal>fred</literal> property of <literal>foo</literal>, and the |
|
<literal>bob</literal> property of <literal>fred</literal> must not be |
|
<literal>null</literal> after the bean is constructed, or a |
|
<exceptionname>NullPointerException</exceptionname> is thrown.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-dependson"> |
|
<title>Using <literal>depends-on</literal></title> |
|
|
|
<para>If a bean is a dependency of another that usually means that one |
|
bean is set as a property of another. Typically you accomplish this with |
|
the <link linkend="beans-ref-element"><literal><ref/></literal> |
|
element</link> in XML-based configuration metadata. However, sometimes |
|
dependencies between beans are less direct; for example, a static |
|
initializer in a class needs to be triggered, such as database driver |
|
registration. The <literal>depends-on</literal> attribute can explicitly |
|
force one or more beans to be initialized before the bean using this |
|
element is initialized. The following example uses the |
|
<literal>depends-on</literal> attribute to express a dependency on a |
|
single bean:</para> |
|
|
|
<programlisting language="xml"><bean id="beanOne" class="ExampleBean" depends-on="<emphasis |
|
role="bold">manager</emphasis>"/> |
|
|
|
<bean id="<emphasis role="bold">manager</emphasis>" class="ManagerBean" /></programlisting> |
|
|
|
<para>To express a dependency on multiple beans, supply a list of bean |
|
names as the value of the <literal>depends-on</literal> attribute, with |
|
commas, whitespace and semicolons, used as valid delimiters:</para> |
|
|
|
<programlisting language="xml"><bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao"> |
|
<property name="manager" ref="manager" /> |
|
</bean> |
|
|
|
<bean id="manager" class="ManagerBean" /> |
|
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" /></programlisting> |
|
|
|
<note> |
|
<para>The <literal>depends-on</literal> attribute in the bean |
|
definition can specify both an initialization time dependency and, in |
|
the case of <link |
|
linkend="beans-factory-scopes-singleton">singleton</link> beans only, |
|
a corresponding destroy time dependency. Dependent beans that define a |
|
<literal>depends-on</literal> relationship with a given bean are |
|
destroyed first, prior to the given bean itself being destroyed. Thus |
|
<literal>depends-on</literal> can also control shutdown order.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-factory-lazy-init"> |
|
<title>Lazy-initialized beans<!--Changed to lazy-initialized from lazily instantiated because attribute is lazy-init, and there was a lot of inconsistency. --></title> |
|
|
|
<para>By default,<interfacename> ApplicationContext</interfacename> |
|
implementations eagerly create and configure all <link |
|
linkend="beans-factory-scopes-singleton">singleton</link> beans as part |
|
of the initialization process. Generally, this pre-instantiation is |
|
desirable, because errors in the configuration or surrounding |
|
environment are discovered immediately, as opposed to hours or even days |
|
later. When this behavior is <emphasis>not</emphasis> desirable, you can |
|
prevent pre-instantiation of a singleton bean by marking the bean |
|
definition as lazy-initialized. A lazy-initialized bean tells the IoC |
|
container to create a bean instance when it is first requested, rather |
|
than at startup.<!--Above, clarify what you mean by eagerly. Note, I've trimmed this section for conciseness, but info is still here.--></para> |
|
|
|
<para>In XML, this behavior is controlled by the |
|
<literal>lazy-init</literal> attribute on the |
|
<literal><bean/></literal> element; for example:</para> |
|
|
|
<programlisting language="xml"><bean id="lazy" class="com.foo.ExpensiveToCreateBean" <emphasis |
|
role="bold">lazy-init="true"</emphasis>/> |
|
|
|
<bean name="not.lazy" class="com.foo.AnotherBean"/></programlisting> |
|
|
|
<para>When the preceding configuration is consumed by an |
|
<interfacename>ApplicationContext</interfacename>, the bean named |
|
<literal>lazy</literal> is not eagerly pre-instantiated when the |
|
<interfacename>ApplicationContext</interfacename> is starting up, |
|
whereas the <literal>not.lazy</literal> bean is eagerly |
|
pre-instantiated.</para> |
|
|
|
<para>However, when a lazy-initialized bean is a dependency of a |
|
singleton bean that is <emphasis>not</emphasis> lazy-initialized, the |
|
<interfacename>ApplicationContext</interfacename> creates the |
|
lazy-initialized bean at startup, because it must satisfy the |
|
singleton's dependencies. The lazy-initialized bean is injected into a |
|
singleton bean elsewhere that is not lazy-initialized.</para> |
|
|
|
<para>You can also control lazy-initialization at the container level by |
|
using the <literal>default-lazy-init</literal> attribute on the |
|
<literal><beans/></literal> element; for example:</para> |
|
|
|
<programlisting language="xml"><beans default-lazy-init="true"> |
|
<lineannotation><!-- no beans will be pre-instantiated... --></lineannotation> |
|
</beans></programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-autowire"> |
|
<title>Autowiring collaborators</title> |
|
|
|
<!--I've moved around info and done a lot of editing/reformatting in this section, but nothing is missing.--> |
|
|
|
<para>The Spring container can <emphasis>autowire</emphasis> |
|
relationships between collaborating beans. You can allow Spring to |
|
resolve collaborators (other beans) automatically for your bean by |
|
inspecting the contents of the |
|
<interfacename>ApplicationContext</interfacename>. Autowiring has the |
|
following advantages:</para> |
|
|
|
<para><itemizedlist> |
|
<listitem> |
|
<para>Autowiring can significantly reduce the need to specify |
|
properties or constructor arguments. (Other mechanisms such as a |
|
bean template <link |
|
linkend="beans-child-bean-definitions">discussed elsewhere in this |
|
chapter</link> are also valuable in this regard.)</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Autowiring can update a configuration as your objects |
|
evolve. For example, if you need to add a dependency to a class, |
|
that dependency can be satisfied automatically your needing to |
|
modify the configuration. Thus autowiring can be especially useful |
|
during development, without negating the option of switching to |
|
explicit wiring when the code base becomes more stable.</para> |
|
</listitem> |
|
</itemizedlist><footnote> |
|
<para>See <xref linkend="beans-factory-collaborators" /></para> |
|
</footnote> When using XML-based configuration metadata, you specify |
|
autowire mode for a bean definition with the <literal>autowire</literal> |
|
attribute of the <literal><bean/></literal> element. The |
|
autowiring functionality has five modes. You specify autowiring |
|
<emphasis>per</emphasis> bean and thus can choose which ones to |
|
autowire.</para> |
|
|
|
<table id="beans-factory-autowiring-modes-tbl"> |
|
<title>Autowiring modes</title> |
|
|
|
<tgroup cols="2"> |
|
<colspec colname="c1" colwidth="1*" /> |
|
|
|
<colspec colname="c2" colwidth="5*" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Mode</entry> |
|
|
|
<entry>Explanation</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry>no</entry> |
|
|
|
<entry><para>(Default) No autowiring. Bean references must be |
|
defined via a <literal>ref</literal> element. Changing the |
|
default setting is not recommended for larger deployments, |
|
because specifying collaborators explicitly gives greater |
|
control and clarity. To some extent, it documents the structure |
|
of a system.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>byName</entry> |
|
|
|
<entry><para>Autowiring by property name. Spring looks for a |
|
bean with the same name as the property that needs to be |
|
autowired. For example, if a bean definition is set to autowire |
|
by name, and it contains a <emphasis>master</emphasis> property |
|
(that is, it has a <emphasis>setMaster(..)</emphasis> method), |
|
Spring looks for a bean definition named |
|
<literal>master</literal>, and uses it to set the |
|
property.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>byType</entry> |
|
|
|
<entry><para>Allows a property to be autowired if exactly one |
|
bean of the property type exists in the container. If more than |
|
one exists, a fatal exception is thrown, which indicates that |
|
you may not use <emphasis>byType</emphasis> autowiring for that |
|
bean. If there are no matching beans, nothing happens; the |
|
property is not set. If this is not desirable, setting the |
|
<literal>dependency-check="objects"</literal> attribute value |
|
specifies that an error should be thrown in this |
|
case.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>constructor</entry> |
|
|
|
<entry><para>Analogous to <emphasis>byType</emphasis>, but |
|
applies to constructor arguments. If there is not exactly one |
|
bean of the constructor argument type in the container, a fatal |
|
error is raised.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>autodetect</entry> |
|
|
|
<entry><para>Chooses <emphasis>constructor</emphasis> or |
|
<emphasis>byType</emphasis> through introspection of the bean |
|
class. If a default constructor is found, the |
|
<emphasis>byType</emphasis> mode is applied.</para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>With <emphasis>byType</emphasis> or |
|
<emphasis>constructor</emphasis> autowiring mode, you can wire arrays |
|
and typed-collections. In such cases <emphasis>all</emphasis> autowire |
|
candidates within the container that match the expected type are |
|
provided to satisfy the dependency. You can autowire strongly-typed Maps |
|
if the expected key type is <classname>String</classname>. An autowired |
|
Maps values will consist of all bean instances that match the expected |
|
type, and the Maps keys will contain the corresponding bean |
|
names.</para> |
|
|
|
<para>You can combine autowire behavior with dependency checking, which |
|
is performed after autowiring completes.</para> |
|
|
|
<section id="beans-autowired-exceptions"> |
|
<title>Limitations and disadvantages of autowiring</title> |
|
|
|
<para>Autowiring works best when it is used consistently across a |
|
project. If autowiring is not used in general, it might be confusing |
|
to developers to use it to wire only one or two bean |
|
definitions.</para> |
|
|
|
<para>Consider the limitations and disadvantages of autowiring:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Explicit dependencies in <literal>property</literal> and |
|
<literal>constructor-arg</literal> settings always override |
|
autowiring. You cannot autowire so-called |
|
<emphasis>simple</emphasis> properties such as primitives, |
|
<classname>Strings</classname>, and <classname>Classes</classname> |
|
(and arrays of such simple properties). This limitation is |
|
by-design.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Autowiring is less exact than explicit wiring. Although, as |
|
noted in the above table, Spring is careful to avoid guessing in |
|
case of ambiguity that might have unexpected results, the |
|
relationships between your Spring-managed objects are no longer |
|
documented explicitly.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Wiring information may not be available to tools that may |
|
generate documentation from a Spring container.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Multiple bean definitions within the container may match the |
|
type specified by the setter method or constructor argument to be |
|
autowired. For arrays, collections, or Maps, this is not |
|
necessarily a problem. However for dependencies that expect a |
|
single value, this ambiguity is not arbitrarily resolved. If no |
|
unique bean definition is available, an exception is |
|
thrown.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>In the latter scenario, you have several options:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Abandon autowiring in favor of explicit wiring.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Avoid autowiring for a bean definition by setting its |
|
<literal>autowire-candidate</literal> attributes to |
|
<literal>false</literal> as described in the next section.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>Designate a single bean definition as the |
|
<emphasis>primary</emphasis> candidate by setting the |
|
<literal>primary</literal> attribute of its |
|
<literal><bean/></literal> element to |
|
<literal>true</literal>.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>If you are using Java 5 or later, implement the more |
|
fine-grained control available with annotation-based |
|
configuration, as described in <xref |
|
linkend="beans-annotation-config" />.</para> |
|
</listitem> |
|
</itemizedlist> |
|
</section> |
|
|
|
<section id="beans-factory-autowire-candidate"> |
|
<title>Excluding a bean from autowiring</title> |
|
|
|
<para>On a per-bean basis, you can exclude a bean from autowiring. In |
|
Spring's XML format, set the <literal>autowire-candidate</literal> |
|
attribute of the <literal><bean/></literal> element to |
|
<literal>false</literal>; the container makes that specific bean |
|
definition unavailable to the autowiring infrastructure.</para> |
|
|
|
<para>You can also limit autowire candidates based on pattern-matching |
|
against bean names. The top-level <literal><beans/></literal> |
|
element accepts one or more patterns within its |
|
<literal>default-autowire-candidates</literal> attribute. For example, |
|
to limit autowire candidate status to any bean whose name ends with |
|
<emphasis>Repository,</emphasis> provide a value of *Repository. To |
|
provide multiple patterns, define them in a comma-separated list. An |
|
explicit value of <literal>true</literal> or <literal>false</literal> |
|
for a bean definitions <literal>autowire-candidate</literal> attribute |
|
always takes precedence, and for such beans, the pattern matching |
|
rules do not apply.</para> |
|
|
|
<para>These techniques are useful for beans that you never want to be |
|
injected into other beans by autowiring. It does not mean that an |
|
excluded bean cannot itself be configured using autowiring. Rather, |
|
the bean itself is not a candidate for autowiring other beans.</para> |
|
|
|
<!--Last paragraph unclear to me. Is my edit ok? Revise as necessary.--> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-dependencies"> |
|
<title>Checking for dependencies</title> |
|
|
|
<!-- MLP: Beverly to review paragraph --> |
|
|
|
<para>The Spring IoC container can check for unresolved dependencies of |
|
a bean deployed into the container. When enabling checking for |
|
unresolved dependencies all JavaBean properties of the bean must have |
|
explicit values set for them in the bean definition or have their values |
|
set via autowiring.<!--Please revise preceding sentence, wording doesn't track.--></para> |
|
|
|
<para>This feature is useful when you want to ensure that all properties |
|
(or all properties of a certain type) are set on a bean. A bean class |
|
often has default values for many properties, or some properties do not |
|
apply to all usage scenarios, so this feature is of limited use. You can |
|
enable dependency checking per bean, just as with the autowiring |
|
functionality. The default is to <emphasis>not</emphasis> check |
|
dependencies. In XML-based configuration metadata, you specify |
|
dependency checking via the <literal>dependency-check</literal> |
|
attribute in a bean definition, which can have the following |
|
values.</para> |
|
|
|
<table id="beans-factory-dependency-check-modes-tbl"> |
|
<title>Dependency checking modes</title> |
|
|
|
<tgroup cols="2"> |
|
<colspec colname="c1" colwidth="1*" /> |
|
|
|
<colspec colname="c2" colwidth="5*" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Mode</entry> |
|
|
|
<entry>Explanation</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry>none</entry> |
|
|
|
<entry><para>(Default) No dependency checking. Properties of the |
|
bean that have no value specified for them are not |
|
set.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>simple</entry> |
|
|
|
<entry><para>Dependency checking for primitive types and |
|
collections (everything except collaborators).</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>object</entry> |
|
|
|
<entry><para>Dependency checking for collaborators |
|
only.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry>all</entry> |
|
|
|
<entry><para>Dependency checking for collaborators, primitive |
|
types, and collections.</para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>If you use Java 5 and thus have access to source-level |
|
annotations, you may find <literal><xref |
|
linkend="metadata-annotations-required" /></literal> to be of |
|
interest.</para> |
|
</section> |
|
|
|
<section id="beans-factory-method-injection"> |
|
<title>Method injection</title> |
|
|
|
<para>In most application scenarios, most beans in the container are |
|
<link linkend="beans-factory-scopes-singleton">singletons</link>. When a |
|
singleton bean needs to collaborate with another singleton bean, or a |
|
non-singleton bean needs to collaborate with another non-singleton bean, |
|
you typically handle the dependency by defining one bean as a property |
|
of the other. A problem arises when the bean lifecycles are different. |
|
Suppose singleton bean A needs to use non-singleton (prototype) bean B, |
|
perhaps on each method invocation on A. The container only creates the |
|
singleton bean A once, and thus only gets one opportunity to set the |
|
properties. The container cannot provide bean A with a new instance of |
|
bean B every time one is needed.</para> |
|
|
|
<para>A solution is to forego some inversion of control. You can <link |
|
linkend="beans-factory-aware-beanfactoryaware">make bean A aware of the |
|
container</link> by implementing the |
|
<interfacename>ApplicationContextAware</interfacename> interface, and by |
|
<link linkend="beans-factory-client">making a getBean("B") call to the |
|
container</link> ask for (a typically new) bean B instance every time |
|
bean A needs it. The following is an example of this approach:</para> |
|
|
|
<programlisting language="java"><lineannotation>// a class that uses a stateful Command-style class to perform some processing</lineannotation> |
|
package fiona.apple; |
|
|
|
<lineannotation>// Spring-API imports</lineannotation> |
|
import org.springframework.beans.BeansException; |
|
import org.springframework.context.Applicationcontext; |
|
import org.springframework.context.ApplicationContextAware; |
|
|
|
public class CommandManager implements ApplicationContextAware { |
|
|
|
private ApplicationContext applicationContext; |
|
|
|
public Object process(Map commandState) { |
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename></lineannotation> |
|
Command command = createCommand(); |
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation> |
|
command.setState(commandState); |
|
return command.execute(); |
|
} |
|
|
|
protected Command createCommand() { |
|
<lineannotation>// notice the Spring API dependency!</lineannotation> |
|
return this.applicationContext.getBean("command", Command.class); |
|
} |
|
|
|
public void setApplicationContext(ApplicationContext applicationContext) |
|
throws BeansException { |
|
this.applicationContext = applicationContext; |
|
} |
|
}</programlisting> |
|
|
|
<para>The preceding is not desirable, because the business code is aware |
|
of and coupled to the Spring Framework. Method Injection, a somewhat |
|
advanced feature of the Spring IoC container, allows this use case to be |
|
handled in a clean fashion.<!--Why give an example that is not desirable? Unclear whether this is an illustration of true method injection.--></para> |
|
|
|
<sidebar> |
|
<para>You can read more about the motivation for Method Injection in |
|
<ulink url="http://blog.springsource.com/2004/08/06/method-injection/">this blog |
|
entry</ulink>.</para> |
|
</sidebar> |
|
|
|
<section id="beans-factory-lookup-method-injection"> |
|
<title>Lookup method injection</title> |
|
|
|
<!--Deleted a box here that doesn't seem to have much info; I moved the blog entry link above. --> |
|
|
|
<para>Lookup method injection is the ability of the container to |
|
override methods on <emphasis>container managed beans</emphasis>, to |
|
return the lookup result for another named bean in the container. The |
|
lookup typically involves a prototype bean as in the scenario |
|
described in the preceding section. The Spring Framework implements |
|
this method injection by using bytecode generation from the CGLIB |
|
library to generate dynamically a subclass that overrides the |
|
method.<!--Note was plain text; I made it a note and moved it up.--></para> |
|
|
|
<note> |
|
<para>For this dynamic subclassing to work, you must have the CGLIB |
|
jar(s) in your classpath. The class that the Spring container will |
|
subclass cannot be <literal>final</literal>, and the method to be |
|
overridden cannot be <literal>final</literal> either. Also, testing |
|
a class that has an <literal>abstract</literal> method requires you |
|
to subclass the class yourself and to supply a stub implementation |
|
of the <literal>abstract</literal> method. Finally, objects that |
|
have been the target of method injection cannot be |
|
serialized.</para> |
|
</note> |
|
|
|
<para>Looking at the <classname>CommandManager</classname> class in |
|
the previous code snippet, you see that the Spring container will |
|
dynamically override the implementation of the |
|
<methodname>createCommand()</methodname> method. Your |
|
<classname>CommandManager</classname> class will not have any Spring |
|
dependencies, as can be seen in the reworked example:</para> |
|
|
|
<programlisting language="java">package fiona.apple; |
|
|
|
<lineannotation>// no more Spring imports! </lineannotation> |
|
|
|
public abstract class CommandManager { |
|
|
|
public Object process(Object commandState) { |
|
<lineannotation>// grab a new instance of the appropriate <interfacename>Command</interfacename> interface</lineannotation> |
|
Command command = createCommand(); |
|
<lineannotation>// set the state on the (hopefully brand new) <interfacename>Command</interfacename> instance</lineannotation> |
|
command.setState(commandState); |
|
return command.execute(); |
|
} |
|
|
|
<lineannotation>// okay... but where is the implementation of this method?</lineannotation> |
|
protected abstract Command createCommand(); |
|
}</programlisting> |
|
|
|
<para>In the client class containing the method to be injected (the |
|
<classname>CommandManager</classname> in this case), the method to be |
|
injected requires a signature of the following form:</para> |
|
|
|
<programlisting language="xml"><public|protected> [abstract] <return-type> theMethodName(<lineannotation>no-arguments</lineannotation>);</programlisting> |
|
|
|
<para>If the method is <literal>abstract</literal>, the |
|
dynamically-generated subclass implements the method. Otherwise, the |
|
dynamically-generated subclass overrides the concrete method defined |
|
in the original class. For example:</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- a stateful bean deployed as a prototype (non-singleton) --></lineannotation> |
|
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> |
|
<lineannotation><!-- inject dependencies here as required --></lineannotation> |
|
</bean> |
|
|
|
<lineannotation><!-- <literal>commandProcessor</literal> uses <literal>statefulCommandHelper</literal> --></lineannotation> |
|
<bean id="commandManager" class="fiona.apple.CommandManager"> |
|
<lookup-method name="createCommand" bean="command"/> |
|
</bean></programlisting> |
|
|
|
<para>The bean identified as <emphasis>commandManager</emphasis> calls |
|
its own method <methodname>createCommand()</methodname> whenever it |
|
needs a new instance of the <emphasis>command</emphasis> bean. You |
|
must be careful to deploy the <literal>command</literal> bean as a |
|
prototype, if that is actually what is needed. If it is deployed as a |
|
<link linkend="beans-factory-scopes-singleton">singleton</link>, the |
|
same instance of the <literal>command</literal> bean is returned each |
|
time.</para> |
|
|
|
<tip> |
|
<para>The interested reader may also find the |
|
<classname>ServiceLocatorFactoryBean</classname> (in the |
|
<literal>org.springframework.beans.factory.config</literal> package) |
|
to be of use. The approach used in ServiceLocatorFactoryBean is |
|
similar to that of another utility class, |
|
<classname>ObjectFactoryCreatingFactoryBean</classname>, but it |
|
allows you to specify your own lookup interface as opposed to a |
|
Spring-specific lookup interface. Consult the JavaDocs for these |
|
classes as well as this <ulink |
|
url="http://blog.arendsen.net/index.php/2006/10/05/on-the-servicelocatorfactorybean-dlas-and-the-sustainability-of-code-and-design/">blog |
|
entry</ulink> for additional information |
|
ServiceLocatorFactoryBean.</para> |
|
</tip> |
|
</section> |
|
|
|
<section id="beans-factory-arbitrary-method-replacement"> |
|
<title>Arbitrary method replacement</title> |
|
|
|
<para>A less useful form of method injection than lookup method |
|
Injection is the ability to replace arbitrary methods in a managed |
|
bean with another method implementation. Users may safely skip the |
|
rest of this section until the functionality is actually needed.<!--Delete this section? See preceding sentence.--></para> |
|
|
|
<para>With XML-based configuration metadata, you can use the |
|
<literal>replaced-method</literal> element to replace an existing |
|
method implementation with another, for a deployed bean. Consider the |
|
following class, with a method computeValue, which we want to |
|
override:</para> |
|
|
|
<programlisting language="java">public class MyValueCalculator { |
|
|
|
public String computeValue(String input) { |
|
<lineannotation>// some real code...</lineannotation> |
|
} |
|
|
|
<lineannotation>// some other methods...</lineannotation> |
|
|
|
}</programlisting> |
|
|
|
<para>A class implementing the |
|
<interfacename>org.springframework.beans.factory.support.MethodReplacer</interfacename> |
|
interface provides the new method definition.</para> |
|
|
|
<programlisting language="java"><lineannotation>/** meant to be used to override the existing <methodname>computeValue(String)</methodname> |
|
implementation in <classname>MyValueCalculator</classname> |
|
*/</lineannotation> |
|
public class ReplacementComputeValue implements MethodReplacer { |
|
|
|
public Object reimplement(Object o, Method m, Object[] args) throws Throwable { |
|
<lineannotation>// get the input value, work with it, and return a computed result</lineannotation> |
|
String input = (String) args[0]; |
|
... |
|
return ...; |
|
} |
|
}</programlisting> |
|
|
|
<para>The bean definition to deploy the original class and specify the |
|
method override would look like this:</para> |
|
|
|
<programlisting language="xml"><bean id="myValueCalculator" class="x.y.z.MyValueCalculator"> |
|
|
|
<lineannotation><!-- arbitrary method replacement --></lineannotation> |
|
<replaced-method name="computeValue" replacer="replacementComputeValue"> |
|
<arg-type>String</arg-type> |
|
</replaced-method> |
|
</bean> |
|
|
|
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/></programlisting> |
|
|
|
<para>You can use one or more contained |
|
<literal><arg-type/></literal> elements within the |
|
<literal><replaced-method/></literal> element to indicate the |
|
method signature of the method being overridden. The signature for the |
|
arguments is necessary only if the method is overloaded and multiple |
|
variants exist within the class. For convenience, the type string for |
|
an argument may be a substring of the fully qualified type name. For |
|
example, the following all match |
|
<classname>java.lang.String</classname>:</para> |
|
|
|
<programlisting language="java"> java.lang.String |
|
String |
|
Str</programlisting> |
|
|
|
<para>Because the number of arguments is often enough to distinguish |
|
between each possible choice, this shortcut can save a lot of typing, |
|
by allowing you to type only the shortest string that will match an |
|
argument type.</para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-scopes"> |
|
<title>Bean scopes</title> |
|
|
|
<para>When you create a bean definition, you create a |
|
<emphasis>recipe</emphasis> for creating actual instances of the class |
|
defined by that bean definition. The idea that a bean definition is a |
|
recipe is important, because it means that, as with a class, you can |
|
create many object instances from a single recipe.</para> |
|
|
|
<para>You can control not only the various dependencies and configuration |
|
values that are to be plugged into an object that is created from a |
|
particular bean definition, but also the <firstterm>scope</firstterm> of |
|
the objects created from a particular bean definition. This approach is |
|
powerful and flexible in that you can <emphasis>choose</emphasis> the |
|
scope of the objects you create through configuration instead of having to |
|
bake in the scope of an object at the Java class level. Beans can be |
|
defined to be deployed in one of a number of scopes: out of the box, the |
|
Spring Framework supports five scopes, three of which are available only |
|
if you use a web-aware |
|
<interfacename>ApplicationContext</interfacename>.</para> |
|
|
|
<para>The following scopes are supported out of the box. You can also |
|
create <link linkend="beans-factory-scopes-custom">a custom |
|
scope.</link></para> |
|
|
|
<table id="beans-factory-scopes-tbl"> |
|
<title>Bean scopes</title> |
|
|
|
<tgroup cols="2"> |
|
<thead> |
|
<row> |
|
<entry align="center">Scope</entry> |
|
|
|
<entry align="center">Description</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry><para> <link |
|
linkend="beans-factory-scopes-singleton">singleton</link> |
|
</para></entry> |
|
|
|
<entry><para>Scopes a single bean definition to a single object |
|
instance per Spring IoC container.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para> <link |
|
linkend="beans-factory-scopes-prototype">prototype</link> |
|
</para></entry> |
|
|
|
<entry><para>Scopes a single bean definition to any number of |
|
object instances.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para> <link |
|
linkend="beans-factory-scopes-request">request</link> |
|
</para></entry> |
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of a |
|
single HTTP request; that is, each HTTP request has its own |
|
instance of a bean created off the back of a single bean |
|
definition. Only valid in the context of a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename>.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para> <link |
|
linkend="beans-factory-scopes-session">session</link> |
|
</para></entry> |
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of |
|
an HTTP <interfacename>Session</interfacename>. Only valid in the |
|
context of a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename>.</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para> <link |
|
linkend="beans-factory-scopes-global-session">global |
|
session</link> </para></entry> |
|
|
|
<entry><para>Scopes a single bean definition to the lifecycle of a |
|
global HTTP <interfacename>Session</interfacename>. Typically only |
|
valid when used in a portlet context. Only valid in the context of |
|
a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename>.</para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<note> |
|
<title>Thread-scoped beans</title> |
|
|
|
<para>As of Spring 3.0, a <emphasis>thread scope</emphasis> is |
|
available, but is not registered by default. For more information, see |
|
the documentation for <ulink |
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/SimpleThreadScope.html">SimpleThreadScope</ulink>. |
|
For instructions on how to register this or any other custom scope, see |
|
<xref linkend="beans-factory-scopes-custom-using" />.</para> |
|
</note> |
|
|
|
<section id="beans-factory-scopes-singleton"> |
|
<title>The singleton scope</title> |
|
|
|
<para>Only one <emphasis>shared</emphasis> instance of a singleton bean |
|
is managed, and all requests for beans with an id or ids matching that |
|
bean definition result in that one specific bean instance being returned |
|
by the Spring container.</para> |
|
|
|
<para>To put it another way, when you define a bean definition and it is |
|
scoped as a singleton, the Spring IoC container creates |
|
<emphasis>exactly one</emphasis> instance of the object defined by that |
|
bean definition. This single instance is stored in a cache of such |
|
singleton beans, and <emphasis>all subsequent requests and |
|
references</emphasis> for that named bean return the cached |
|
object.</para> |
|
|
|
<para><mediaobject> |
|
<imageobject role="fo"> |
|
<imagedata align="center" fileref="images/singleton.png" |
|
format="PNG" /> |
|
</imageobject> |
|
|
|
<imageobject role="html"> |
|
<imagedata align="center" fileref="images/singleton.png" |
|
format="PNG" /> |
|
</imageobject> |
|
</mediaobject></para> |
|
|
|
<para>Spring's concept of a singleton bean differs from the Singleton |
|
pattern as defined in the Gang of Four (GoF) patterns book. The GoF |
|
Singleton hard-codes the scope of an object such that one <emphasis>and |
|
only one</emphasis> instance of a particular class is created<emphasis> |
|
per <classname>ClassLoader</classname></emphasis>. The scope of the |
|
Spring singleton is best described as <emphasis>per container and per |
|
bean</emphasis>. This means that if you define one bean for a particular |
|
class in a single Spring container, then the Spring container creates |
|
one <emphasis>and only one</emphasis> instance of the class defined by |
|
that bean definition. <emphasis>The singleton scope is the default scope |
|
in Spring</emphasis>. To define a bean as a singleton in XML, you would |
|
write, for example:</para> |
|
|
|
<programlisting language="xml"><bean id="accountService" class="com.foo.DefaultAccountService"/> |
|
|
|
<lineannotation><!-- the following is equivalent, though redundant (singleton scope is the default) --></lineannotation> |
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/></programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-prototype"> |
|
<title>The prototype scope</title> |
|
|
|
<para>The non-singleton, prototype scope of bean deployment results in |
|
the <emphasis>creation of a new bean instance</emphasis> every time a |
|
request for that specific bean is made. That is, the bean is injected |
|
into another bean or you request it through a |
|
<literal>getBean()</literal> method call on the container. As a rule, |
|
use the prototype scope for all stateful beans and the singleton scope |
|
for stateless beans.</para> |
|
|
|
<para>The following diagram illustrates the Spring prototype scope. |
|
<emphasis>A data access object (DAO) is not typically configured as a |
|
prototype, because a typical DAO does not hold any conversational state; |
|
it was just easier for this author to reuse the core of the singleton |
|
diagram.</emphasis><!--First it says diagram illustrates scope, but then says it's not typical of a prototype scope. Why not use realistic one? --></para> |
|
|
|
<para><mediaobject> |
|
<imageobject role="fo"> |
|
<imagedata align="center" fileref="images/prototype.png" |
|
format="PNG" /> |
|
</imageobject> |
|
|
|
<imageobject role="html"> |
|
<imagedata align="center" fileref="images/prototype.png" |
|
format="PNG" /> |
|
</imageobject> |
|
</mediaobject></para> |
|
|
|
<para>The following example defines a bean as a prototype in XML:</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- using <literal>spring-beans-2.0.dtd</literal> --></lineannotation> |
|
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/></programlisting> |
|
|
|
<para>In contrast to the other scopes, Spring does not manage the |
|
complete lifecycle of a prototype bean: the container instantiates, |
|
configures, and otherwise assembles a prototype object, and hands it to |
|
the client, with no further record of that prototype instance. Thus, |
|
although <emphasis>initialization</emphasis> lifecycle callback methods |
|
are called on all objects regardless of scope, in the case of |
|
prototypes, configured <emphasis>destruction</emphasis> lifecycle |
|
callbacks are <emphasis>not</emphasis> called. The client code must |
|
clean up prototype-scoped objects and release expensive resources that |
|
the prototype bean(s) are holding. To get the Spring container to |
|
release resources held by prototype-scoped beans, try using a custom |
|
<link linkend="beans-factory-extension-bpp">bean post-processor</link>, |
|
which holds a reference to beans that need to be cleaned up.</para> |
|
|
|
<para>In some respects, the Spring container's role in regard to a |
|
prototype-scoped bean is a replacement for the Java |
|
<literal>new</literal> operator. All lifecycle management past that |
|
point must be handled by the client. (For details on the lifecycle of a |
|
bean in the Spring container, see <xref |
|
linkend="beans-factory-lifecycle" />.)</para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-sing-prot-interaction"> |
|
<title>Singleton beans with prototype-bean dependencies</title> |
|
|
|
<para>When you use singleton-scoped beans with dependencies on prototype |
|
beans, be aware that <emphasis>dependencies are resolved at |
|
instantiation time</emphasis>. Thus if you dependency-inject a |
|
prototype-scoped bean into a singleton-scoped bean, a new prototype bean |
|
is instantiated and then dependency-injected into the singleton bean. |
|
The prototype instance is the sole instance that is ever supplied to the |
|
singleton-scoped bean.</para> |
|
|
|
<para>However, suppose you want the singleton-scoped bean to acquire a |
|
new instance of the prototype-scoped bean repeatedly at runtime. You |
|
cannot dependency-inject a prototype-scoped bean into your singleton |
|
bean, because that injection occurs only <emphasis>once</emphasis>, when |
|
the Spring container is instantiating the singleton bean and resolving |
|
and injecting its dependencies. If you need a new instance of a |
|
prototype bean at runtime more than once, see <xref |
|
linkend="beans-factory-method-injection" /></para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-other"> |
|
<title>Request, session, and global session scopes</title> |
|
|
|
<para>The <literal>request</literal>, <literal>session</literal>, and |
|
<literal>global session</literal> scopes are <emphasis>only</emphasis> |
|
available if you use a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename> implementation (such |
|
as <classname>XmlWebApplicationContext</classname>). If you use these |
|
scopes with regular Spring IoC containers such as the |
|
<classname>ClassPathXmlApplicationContext</classname>, you get an |
|
<classname>IllegalStateException</classname> complaining about an |
|
unknown bean scope.</para> |
|
|
|
<section id="beans-factory-scopes-other-web-configuration"> |
|
<title>Initial web configuration</title> |
|
|
|
<para>To support the scoping of beans at the |
|
<literal>request</literal>, <literal>session</literal>, and |
|
<literal>global session</literal> levels (web-scoped beans), some |
|
minor initial configuration is required before you define your beans. |
|
(This initial setup is <emphasis>not</emphasis> required for the |
|
standard scopes, singleton and prototype.)</para> |
|
|
|
<para>How you accomplish this initial setup depends on your particular |
|
Servlet environment..</para> |
|
|
|
<para>If you access scoped beans within Spring Web MVC, in effect, |
|
within a request that is processed by the Spring |
|
<classname>DispatcherServlet</classname>, or |
|
<classname>DispatcherPortlet</classname>, then no special setup is |
|
necessary: <classname>DispatcherServlet</classname> and |
|
<classname>DispatcherPortlet</classname> already expose all relevant |
|
state.</para> |
|
|
|
<para>If you use a Servlet 2.4+ web container, with requests processed |
|
outside of Spring's DispatcherServlet (for example, when using JSF or |
|
Struts), you need to add the following |
|
<interfacename>javax.servlet.ServletRequestListener</interfacename> to |
|
the declarations in your web applications <literal>web.xml</literal> |
|
file:</para> |
|
|
|
<programlisting language="xml"><web-app> |
|
... |
|
<listener> |
|
<listener-class> |
|
org.springframework.web.context.request.RequestContextListener |
|
</listener-class> |
|
</listener> |
|
... |
|
</web-app></programlisting> |
|
|
|
<para>If you use an older web container (Servlet 2.3), use the |
|
provided <interfacename>javax.servlet.Filter</interfacename> |
|
implementation. The following snippet of XML configuration must be |
|
included in the <literal>web.xml</literal> file of your web |
|
application if you want to access web-scoped beans in requests outside |
|
of Spring's DispatcherServlet on a Servlet 2.3 container. (The filter |
|
mapping depends on the surrounding web application configuration, so |
|
you must change it as appropriate.)</para> |
|
|
|
<programlisting language="xml"><web-app> |
|
.. |
|
<filter> |
|
<filter-name>requestContextFilter</filter-name> |
|
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> |
|
</filter> |
|
<filter-mapping> |
|
<filter-name>requestContextFilter</filter-name> |
|
<url-pattern>/*</url-pattern> |
|
</filter-mapping> |
|
... |
|
</web-app></programlisting> |
|
|
|
<para><classname>DispatcherServlet</classname>, |
|
<classname>RequestContextListener</classname> and |
|
<classname>RequestContextFilter</classname> all do exactly the same |
|
thing, namely bind the HTTP request object to the |
|
<classname>Thread</classname> that is servicing that request. This |
|
makes beans that are request- and session-scoped available further |
|
down the call chain.</para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-request"> |
|
<title>Request scope</title> |
|
|
|
<para>Consider the following bean definition:</para> |
|
|
|
<programlisting language="xml"><bean id="loginAction" class="com.foo.LoginAction" scope="request"/></programlisting> |
|
|
|
<para>The Spring container creates a new instance of the |
|
<classname>LoginAction</classname> bean by using the |
|
<literal>loginAction</literal> bean definition for each and every HTTP |
|
request. That is, the <literal>loginAction</literal> bean is scoped at |
|
the HTTP request level. You can change the internal state of the |
|
instance that is created as much as you want, because other instances |
|
created from the same <literal>loginAction</literal> bean definition |
|
will not see these changes in state; they are particular to an |
|
individual request. When the request completes processing, the bean |
|
that is scoped to the request is discarded.</para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-session"> |
|
<title>Session scope</title> |
|
|
|
<para>Consider the following bean definition:</para> |
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/></programlisting> |
|
|
|
<para>The Spring container creates a new instance of the |
|
<classname>UserPreferences</classname> bean by using the |
|
<literal>userPreferences</literal> bean definition for the lifetime of |
|
a single HTTP <interfacename>Session</interfacename>. In other words, |
|
the <literal>userPreferences</literal> bean is effectively scoped at |
|
the HTTP <interfacename>Session</interfacename> level. As with |
|
<literal>request-scoped</literal> beans, you can change the internal |
|
state of the instance that is created as much as you want, knowing |
|
that other HTTP <interfacename>Session</interfacename> instances that |
|
are also using instances created from the same |
|
<literal>userPreferences</literal> bean definition do not see these |
|
changes in state, because they are particular to an individual HTTP |
|
<interfacename>Session</interfacename>. When the HTTP |
|
<interfacename>Session</interfacename> is eventually discarded, the |
|
bean that is scoped to that particular HTTP |
|
<interfacename>Session</interfacename> is also discarded.</para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-global-session"> |
|
<title>Global session scope</title> |
|
|
|
<para>Consider the following bean definition:</para> |
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/></programlisting> |
|
|
|
<para>The <literal>global session</literal> scope is similar to the |
|
standard HTTP <interfacename>Session</interfacename> scope (<link |
|
linkend="beans-factory-scopes-session">described above</link>), and |
|
applies only in the context of portlet-based web applications. The |
|
portlet specification defines the notion of a global |
|
<interfacename>Session</interfacename> that is shared among all |
|
portlets that make up a single portlet web application. Beans defined |
|
at the <literal>global session</literal> scope are scoped (or bound) |
|
to the lifetime of the global portlet |
|
<interfacename>Session</interfacename>.</para> |
|
|
|
<para>If you write a standard Servlet-based web application and you |
|
define one or more beans as having <literal>global session</literal> |
|
scope, the standard HTTP <interfacename>Session</interfacename> scope |
|
is used, and no error is raised.</para> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-other-injection"> |
|
<title>Scoped beans as dependencies</title> |
|
|
|
<para>The Spring IoC container manages not only the instantiation of |
|
your objects (beans), but also the wiring up of collaborators (or |
|
dependencies). If you want to inject (for example) an HTTP request |
|
scoped bean into another bean, you must inject an AOP proxy in place |
|
of the scoped bean. That is, you need to inject a proxy object that |
|
exposes the same public interface as the scoped object but that can |
|
also retrieve the real, target object from the relevant scope (for |
|
example, an HTTP request) and delegate method calls onto the real |
|
object.</para> |
|
|
|
<note> |
|
<para>You <emphasis>do not</emphasis> need to use the |
|
<literal><aop:scoped-proxy/></literal> in conjunction with |
|
beans that are scoped as <literal>singletons</literal> or |
|
<literal>prototypes</literal>. If you try to create a scoped proxy |
|
for a singleton bean, the |
|
<exceptionname>BeanCreationException</exceptionname> is |
|
raised.</para> |
|
</note> |
|
|
|
<para>The configuration in the following example is only one line, but |
|
it is important to understand the <quote>why</quote> as well as the |
|
<quote>how</quote> behind it.</para> |
|
|
|
<!--What is this example supposed to show?--> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:aop="http://www.springframework.org/schema/aop" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/aop |
|
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> |
|
|
|
<lineannotation><!-- an HTTP <interfacename>Session</interfacename>-scoped bean exposed as a proxy --></lineannotation> |
|
<bean id="userPreferences" class="com.foo.UserPreferences" <emphasis |
|
role="bold">scope="session"</emphasis>> |
|
|
|
<lineannotation><!-- this next element effects the proxying of the surrounding bean --></lineannotation> |
|
<emphasis role="bold"><aop:scoped-proxy/></emphasis> |
|
</bean> |
|
|
|
<lineannotation><!-- a singleton-scoped bean <emphasis role="bold">injected with a proxy to the above bean</emphasis> --></lineannotation> |
|
<bean id="userService" class="com.foo.SimpleUserService"> |
|
|
|
<lineannotation><!-- a reference to the <emphasis role="bold">proxied</emphasis> <literal>userPreferences</literal> bean --></lineannotation> |
|
<property name="userPreferences" ref="userPreferences"/> |
|
|
|
</bean> |
|
</beans> |
|
</programlisting> |
|
|
|
<para>To create such a proxy, you insert a child |
|
<literal><aop:scoped-proxy/></literal> element into a scoped |
|
bean definition. <!--To create what such proxy? Is the proxy created above? Also, below added an x-ref that seems relevant.-->(If |
|
you choose class-based proxying, you also need the CGLIB library in |
|
your classpath. See <xref |
|
linkend="beans-factory-scopes-other-injection-proxies" /> and <xref |
|
linkend="xsd-config" />.) Why do definitions of beans scoped at the |
|
<literal>request</literal>, <literal>session</literal>, |
|
<literal>globalSession</literal> and custom-scope levels require the |
|
<literal><aop:scoped-proxy/></literal> element ? Let's examine |
|
the following singleton bean definition and contrast it with what you |
|
need to define for the aforementioned scopes. (The following |
|
<literal>userPreferences</literal> bean definition as it stands is |
|
<emphasis>incomplete.)</emphasis></para> |
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> |
|
|
|
<bean id="userManager" class="com.foo.UserManager"> |
|
<property name="userPreferences" ref="userPreferences"/> |
|
</bean></programlisting> |
|
|
|
<para>In the preceding example, the singleton bean |
|
<literal>userManager</literal> is injected with a reference to the |
|
HTTP <interfacename>Session</interfacename>-scoped bean |
|
<literal>userPreferences</literal>. The salient point here is that the |
|
<literal>userManager</literal> bean is a singleton: it will be |
|
instantiated <emphasis>exactly once</emphasis> per container, and its |
|
dependencies (in this case only one, the |
|
<literal>userPreferences</literal> bean) are also injected only once. |
|
This means that the <literal>userManager</literal> bean will only |
|
operate on the exact same <literal>userPreferences</literal> object, |
|
that is, the one that it was originally injected with.</para> |
|
|
|
<!-- MLP: Beverly to review paragraph --> |
|
|
|
<para>This is <emphasis>not</emphasis> the behavior you want when |
|
injecting a shorter-lived scoped bean into a longer-lived scoped bean, |
|
for example injecting an HTTP |
|
<interfacename>Session</interfacename>-scoped collaborating bean as a |
|
dependency into singleton bean. Rather, you need a single |
|
<literal>userManager</literal> object, and for the lifetime of an HTTP |
|
<interfacename>Session</interfacename>, you need a |
|
<literal>userPreferences</literal> object that is specific to said |
|
HTTP <interfacename>Session</interfacename>. Thus the container |
|
creates an object that exposes the exact same public interface as the |
|
<classname>UserPreferences</classname> class (ideally an object that |
|
<emphasis>is a</emphasis> <classname>UserPreferences</classname> |
|
instance) which can fetch the real |
|
<classname>UserPreferences</classname> object from the scoping |
|
mechanism (HTTP request, <interfacename>Session</interfacename>, |
|
etc.). The container injects this proxy object into the |
|
<literal>userManager</literal> bean, which is unaware that this |
|
<classname>UserPreferences</classname> reference is a proxy. In this |
|
example, when a <interfacename>UserManager</interfacename> instance |
|
invokes a method on the dependency-injected |
|
<classname>UserPreferences</classname> object, it actually is invoking |
|
a method on the proxy. The proxy then fetches the real |
|
<classname>UserPreferences</classname> object from (in this case) the |
|
HTTP <interfacename>Session</interfacename>, and delegates the method |
|
invocation onto the retrieved real |
|
<classname>UserPreferences</classname> object.</para> |
|
|
|
<para>Thus you need the following, correct and complete, configuration |
|
when injecting <literal>request-</literal>, |
|
<literal>session-</literal>, and |
|
<literal>globalSession-scoped</literal> beans into collaborating |
|
objects:</para> |
|
|
|
<programlisting language="xml"><bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> |
|
<emphasis role="bold"><literal><aop:scoped-proxy/></literal></emphasis> |
|
</bean> |
|
|
|
<bean id="userManager" class="com.foo.UserManager"> |
|
<property name="userPreferences" ref="userPreferences"/> |
|
</bean></programlisting> |
|
|
|
<section id="beans-factory-scopes-other-injection-proxies"> |
|
<title>Choosing the type of proxy to create</title> |
|
|
|
<para>By default, when the Spring container creates a proxy for a |
|
bean that is marked up with the |
|
<literal><aop:scoped-proxy/></literal> element, <emphasis>a |
|
CGLIB-based class proxy is created</emphasis>. This means that you |
|
need to have the CGLIB library in the classpath of your |
|
application.</para> |
|
|
|
<para><emphasis>Note: CGLIB proxies only intercept public method |
|
calls!</emphasis> Do not call non-public methods on such a proxy; |
|
they will not be delegated to the scoped target object.</para> |
|
|
|
<para>Alternatively, you can configure the Spring container to |
|
create standard JDK interface-based proxies for such scoped beans, |
|
by specifying <literal>false</literal> for the value of the |
|
<literal>proxy-target-class</literal> attribute of the |
|
<literal><aop:scoped-proxy/></literal> element. Using JDK |
|
interface-based proxies means that you do not need additional |
|
libraries in your application classpath to effect such proxying. |
|
However, it also means that the class of the scoped bean must |
|
implement at least one interface, and <emphasis>that all</emphasis> |
|
collaborators into which the scoped bean is injected must reference |
|
the bean through one of its interfaces.</para> |
|
|
|
<programlisting language="xml"><lineannotation><!-- <classname>DefaultUserPreferences</classname> implements the <interfacename>UserPreferences</interfacename> interface --></lineannotation> |
|
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"> |
|
<aop:scoped-proxy <emphasis role="bold">proxy-target-class="false"<literal></literal></emphasis>/> |
|
</bean> |
|
|
|
<bean id="userManager" class="com.foo.UserManager"> |
|
<property name="userPreferences" ref="userPreferences"/> |
|
</bean></programlisting> |
|
|
|
<para>For more detailed information about choosing class-based or |
|
interface-based proxying, see <xref |
|
linkend="aop-proxying" />.</para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-custom"> |
|
<title>Custom scopes</title> |
|
|
|
<para>As of Spring 2.0, the bean scoping mechanism is extensible. You |
|
can define your own scopes, or even redefine existing scopes, although |
|
the latter is considered bad practice and you |
|
<emphasis>cannot</emphasis> override the built-in |
|
<literal>singleton</literal> and <literal>prototype</literal> |
|
scopes.</para> |
|
|
|
<section id="beans-factory-scopes-custom-creating"> |
|
<title>Creating a custom scope</title> |
|
|
|
<para>To integrate your custom scope(s) into the Spring container, you |
|
need to implement the |
|
<interfacename>org.springframework.beans.factory.config.Scope</interfacename> |
|
interface, which is described in this section. For an idea of how to |
|
implement your own scopes, see the |
|
<interfacename>Scope</interfacename> implementations that are supplied |
|
with the Spring Framework itself and the <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Scope.html">Scope |
|
Javadoc</ulink>, which explains the methods you need to implement in |
|
more detail.</para> |
|
|
|
<para>The <literal>Scope</literal> interface has four methods to get |
|
objects from the scope, remove them from the scope, and allow them to |
|
be destroyed.</para> |
|
|
|
<para>The following method returns the object from the underlying |
|
scope. The session scope implementation, for example, returns the |
|
session-scoped bean (and if it does not exist, the method returns a |
|
new instance of the bean, after having bound it to the session for |
|
future reference).<!--How can it return a a new instance of a bean that doesn't exist? Revise to clarify.--></para> |
|
|
|
<programlisting language="java">Object get(String name, ObjectFactory objectFactory)</programlisting> |
|
|
|
<para>The following method removes the object from the underlying |
|
scope. The session scope implementation for example, removes the |
|
session-scoped bean from the underlying session. The object should be |
|
returned, but you can return null if the object with the specified |
|
name is not found.</para> |
|
|
|
<programlisting language="java">Object remove(String name)</programlisting> |
|
|
|
<para>The following method registers the callbacks the scope should |
|
execute when it is destroyed or when the specified object in the scope |
|
is destroyed. Refer to the Javadoc or a Spring scope implementation |
|
for more information on destruction callbacks.</para> |
|
|
|
<programlisting language="java">void registerDestructionCallback(String name, Runnable destructionCallback)</programlisting> |
|
|
|
<para>The following method obtains the conversation identifier for the |
|
underlying scope. This identifier is different for each scope. For a |
|
session scoped implementation, this identifier can be the session |
|
identifier.</para> |
|
|
|
<programlisting language="java">String getConversationId()</programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-scopes-custom-using"> |
|
<title>Using a custom scope</title> |
|
|
|
<para>After you write and test one or more custom |
|
<interfacename>Scope</interfacename> implementations, you need to make |
|
the Spring container aware of your new scope(s). The central method to |
|
register a new <interfacename>Scope</interfacename> with the Spring |
|
container.</para> |
|
|
|
<programlisting language="java">void registerScope(String scopeName, Scope scope);</programlisting> |
|
|
|
<para>This method is declared on the |
|
<interfacename>ConfigurableBeanFactory</interfacename> interface, |
|
which is available on most of the concrete |
|
<interfacename>ApplicationContext</interfacename> implementations that |
|
ship with Spring via the BeanFactory property.</para> |
|
|
|
<para>The first argument to the |
|
<methodname>registerScope(..)</methodname> method is the unique name |
|
associated with a scope; examples of such names in the Spring |
|
container itself are <literal>singleton</literal> and |
|
<literal>prototype</literal>. The second argument to the |
|
<methodname>registerScope(..)</methodname> method is an actual |
|
instance of the custom <interfacename>Scope</interfacename> |
|
implementation that you wish to register and use.</para> |
|
|
|
<para>Suppose that you write your custom |
|
<interfacename>Scope</interfacename> implementation, and then register |
|
it as below.</para> |
|
|
|
<note> |
|
<para>The example below uses <literal>SimpleThreadScope</literal> |
|
which is included with Spring, but not registered by default. The |
|
instructions would be the same for your own custom |
|
<literal>Scope</literal> implementations.</para> |
|
</note> |
|
|
|
<programlisting language="java"> |
|
Scope threadScope = new SimpleThreadScope(); |
|
beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope);</programlisting> |
|
|
|
<para>You then create bean definitions that adhere to the scoping |
|
rules of your custom <interfacename>Scope</interfacename>:</para> |
|
|
|
<programlisting language="xml"><bean id="..." class="..." scope="thread"></programlisting> |
|
|
|
<para>With a custom <interfacename>Scope</interfacename> |
|
implementation, you are not limited to programmatic registration of |
|
the scope. You can also do the <interfacename>Scope</interfacename> |
|
registration declaratively, using the |
|
<classname>CustomScopeConfigurer</classname> class:</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:aop="http://www.springframework.org/schema/aop" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/aop |
|
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> |
|
|
|
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> |
|
<property name="scopes"> |
|
<map><emphasis role="bold"> |
|
<entry key="thread"> |
|
<bean class="org.springframework.context.support.SimpleThreadScope"/> |
|
</entry></emphasis> |
|
</map> |
|
</property> |
|
</bean> |
|
|
|
<bean id="bar" class="x.y.Bar" scope="thread"> |
|
<property name="name" value="Rick"/> |
|
<aop:scoped-proxy/> |
|
</bean> |
|
|
|
<bean id="foo" class="x.y.Foo"> |
|
<property name="bar" ref="bar"/> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<note> |
|
<para>When you place <aop:scoped-proxy/> in a |
|
<interfacename>FactoryBean</interfacename> implementation, it is the |
|
factory bean itself that is scoped, not the object returned from |
|
<methodname>getObject()</methodname>.</para> |
|
</note> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-nature"> |
|
<title>Customizing the nature of a bean</title> |
|
|
|
<section id="beans-factory-lifecycle"> |
|
<title>Lifecycle callbacks</title> |
|
|
|
<!-- MLP Beverly to review: Old Text: The Spring Framework provides several callback interfaces to |
|
change the behavior of your bean in the container; they include --> |
|
|
|
<para>To interact with the container's management of the bean lifecycle, |
|
you can implement the Spring |
|
<interfacename>InitializingBean</interfacename> and |
|
<interfacename>DisposableBean</interfacename> interfaces. The container |
|
calls <methodname>afterPropertiesSet()</methodname> for the former and |
|
<methodname>destroy()</methodname> for the latter to allow the bean to |
|
perform certain actions upon initialization and destruction of your |
|
beans. You can also achieve the same integration with the container |
|
without coupling your classes to Spring interfaces though the use of |
|
init-method and destroy method object definition metadata.</para> |
|
|
|
<para>Internally, the Spring Framework uses |
|
<interfacename>BeanPostProcessor</interfacename> implementations to |
|
process any callback interfaces it can find and call the appropriate |
|
methods. If you need custom features or other lifecycle behavior Spring |
|
does not offer out-of-the-box, you can implement a |
|
<interfacename>BeanPostProcessor</interfacename> yourself. For more |
|
information, see <xref linkend="beans-factory-extension" />.</para> |
|
|
|
<para>In addition to the initialization and destruction callbacks, |
|
Spring-managed objects may also implement the |
|
<interfacename>Lifecycle</interfacename> interface so that those |
|
objects can participate in the startup and shutdown process as |
|
driven by the container's own lifecycle.</para> |
|
|
|
<para>The lifecycle callback interfaces are described in this |
|
section.</para> |
|
|
|
<section id="beans-factory-lifecycle-initializingbean"> |
|
<title>Initialization callbacks</title> |
|
|
|
<para>The |
|
<interfacename>org.springframework.beans.factory.InitializingBean</interfacename> |
|
interface allows a bean to perform initialization work after all |
|
necessary properties on the bean have been set by the container. The |
|
<interfacename>InitializingBean</interfacename> interface specifies a |
|
single method:</para> |
|
|
|
<programlisting language="java">void afterPropertiesSet() throws Exception;</programlisting> |
|
|
|
<para>It is recommended that you do not use the |
|
<interfacename>InitializingBean</interfacename> interface because it |
|
unnecessarily couples the code to Spring. Alternatively, specify a |
|
POJO initialization method. In the case of XML-based configuration |
|
metadata, you use the <literal>init-method</literal> attribute to |
|
specify the name of the method that has a void no-argument signature. |
|
For example, the following definition:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
public void init() { |
|
<lineannotation>// do some initialization work</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>...is exactly the same as...</para> |
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.AnotherExampleBean"/></programlisting> |
|
|
|
<programlisting language="java">public class AnotherExampleBean implements InitializingBean { |
|
|
|
public void afterPropertiesSet() { |
|
<lineannotation>// do some initialization work</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>... but does not couple the code to Spring.</para> |
|
</section> |
|
|
|
<section id="beans-factory-lifecycle-disposablebean"> |
|
<title>Destruction callbacks</title> |
|
|
|
<para>Implementing the |
|
<interfacename>org.springframework.beans.factory.DisposableBean</interfacename> |
|
interface allows a bean to get a callback when the container |
|
containing it is destroyed. The |
|
<interfacename>DisposableBean</interfacename> interface specifies a |
|
single method:</para> |
|
|
|
<programlisting language="java">void destroy() throws Exception;</programlisting> |
|
|
|
<para>It is recommended that you do not use the |
|
<interfacename>DisposableBean</interfacename> callback interface |
|
because it unnecessarily couples the code to Spring. Alternatively, |
|
specify a generic method that is supported by bean definitions. With |
|
XML-based configuration metadata, you use the |
|
<literal>destroy-method</literal> attribute on the |
|
<literal><bean/></literal>. For example, the following |
|
definition:</para> |
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/></programlisting> |
|
|
|
<programlisting language="java">public class ExampleBean { |
|
|
|
public void cleanup() { |
|
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>...is exactly the same as...</para> |
|
|
|
<programlisting language="xml"><bean id="exampleInitBean" class="examples.AnotherExampleBean"/></programlisting> |
|
|
|
<programlisting language="java">public class AnotherExampleBean implements DisposableBean { |
|
|
|
public void destroy() { |
|
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<para>... but does not couple the code to Spring.</para> |
|
</section> |
|
|
|
<section id="beans-factory-lifecycle-default-init-destroy-methods"> |
|
<title>Default initialization and destroy methods</title> |
|
|
|
<para>When you write initialization and destroy method callbacks that |
|
do not use the Spring-specific |
|
<interfacename>InitializingBean</interfacename> and |
|
<interfacename>DisposableBean</interfacename> callback interfaces, you |
|
typically write methods with names such as <literal>init()</literal>, |
|
<literal>initialize()</literal>, <literal>dispose()</literal>, and so |
|
on. Ideally, the names of such lifecycle callback methods are |
|
standardized across a project so that all developers use the same |
|
method names and ensure consistency.</para> |
|
|
|
<para>You can configure the Spring container to |
|
<literal>look</literal> for named initialization and destroy callback |
|
method names on <emphasis>every</emphasis> bean. This means that you, |
|
as an application developer, can write your application classes and |
|
use an initialization callback called <literal>init()</literal>, |
|
without having to configure an <literal>init-method="init"</literal> |
|
attribute with each bean definition. The Spring IoC container calls |
|
that method when the bean is created (and in accordance with the |
|
standard lifecycle callback contract described previously). This |
|
feature also enforces a consistent naming convention for |
|
initialization and destroy method callbacks.</para> |
|
|
|
<para>Suppose that your initialization callback methods are named |
|
<literal>init()</literal> and destroy callback methods are named |
|
<literal>destroy()</literal>. Your class will resemble the class in |
|
the following example.</para> |
|
|
|
<programlisting language="java">public class DefaultBlogService implements BlogService { |
|
|
|
private BlogDao blogDao; |
|
|
|
public void setBlogDao(BlogDao blogDao) { |
|
this.blogDao = blogDao; |
|
} |
|
|
|
<lineannotation>// this is (unsurprisingly) the initialization callback method</lineannotation> |
|
public void init() { |
|
if (this.blogDao == null) { |
|
throw new IllegalStateException("The [blogDao] property must be set."); |
|
} |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="xml"><beans <emphasis role="bold">default-init-method="init"</emphasis>> |
|
|
|
<bean id="blogService" class="com.foo.DefaultBlogService"> |
|
<property name="blogDao" ref="blogDao" /> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<para>The presence of the <literal>default-init-method</literal> |
|
attribute on the top-level <literal><beans/></literal> element |
|
attribute causes the Spring IoC container to recognize a method called |
|
<literal>init</literal> on beans as the initialization method |
|
callback. When a bean is created and assembled, if the beans class has |
|
such a method, it is invoked at the appropriate time.</para> |
|
|
|
<para>You configure destroy method callbacks similarly (in XML, that |
|
is) by using the <literal>default-destroy-method</literal> attribute |
|
on the top-level <literal><beans/></literal> element.</para> |
|
|
|
<para>Where existing bean classes already have callback methods that |
|
are named at variance with the convention, you can override the |
|
default by specifying (in XML, that is) the method name using the |
|
<literal>init-method</literal> and <literal>destroy-method</literal> |
|
attributes of the <bean/> itself.</para> |
|
|
|
<para>The Spring container guarantees that a configured initialization |
|
callback is called immediately after a bean is supplied with all |
|
dependencies. Thus the initialization callback is called on the raw |
|
bean reference, which means that AOP interceptors and so forth are not |
|
yet applied to the bean. A target bean is fully created |
|
<emphasis>first</emphasis>, <emphasis>then</emphasis> an AOP proxy |
|
(for example) with its interceptor chain is applied. If the target |
|
bean and the proxy are defined separately, your code can even interact |
|
with the raw target bean, bypassing the proxy. Hence, it would be |
|
inconsistent to apply the interceptors to the init method, because |
|
doing so would couple the lifecycle of the target bean with its |
|
proxy/interceptors and leave strange semantics when your code |
|
interacts directly to the raw target bean.</para> |
|
</section> |
|
|
|
<section id="beans-factory-lifecycle-combined-effects"> |
|
<title>Combining lifecycle mechanisms</title> |
|
|
|
<para>As of Spring 2.5, you have three options for controlling bean |
|
lifecycle behavior: the <link |
|
linkend="beans-factory-lifecycle-initializingbean"><interfacename>InitializingBean</interfacename></link> |
|
and <link |
|
linkend="beans-factory-lifecycle-disposablebean"><interfacename>DisposableBean</interfacename></link> |
|
callback interfaces; custom <literal>init()</literal> and |
|
<literal>destroy()</literal> methods; and the <link |
|
linkend="beans-postconstruct-and-predestroy-annotations"><interfacename>@PostConstruct</interfacename> |
|
and <interfacename>@PreDestroy</interfacename> annotations</link>. You |
|
can combine these mechanisms to control a given bean.</para> |
|
|
|
<note> |
|
<para>If multiple lifecycle mechanisms are configured for a bean, |
|
and each mechanism is configured with a different method name, then |
|
each configured method is executed in the order listed below. |
|
However, if the same method name is configured - for example, |
|
<literal>init()</literal> for an initialization method - for more |
|
than one of these lifecycle mechanisms, that method is executed |
|
once, as explained in the preceding section.</para> |
|
</note> |
|
|
|
<para>Multiple lifecycle mechanisms configured for the same bean, with |
|
different initialization methods, are called as follows:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Methods annotated with |
|
<interfacename>@PostConstruct</interfacename></para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><literal>afterPropertiesSet()</literal> as defined by the |
|
<interfacename>InitializingBean</interfacename> callback |
|
interface</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>A custom configured <literal>init()</literal> method</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>Destroy methods are called in the same order:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para>Methods annotated with |
|
<interfacename>@PreDestroy</interfacename></para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><literal>destroy()</literal> as defined by the |
|
<interfacename>DisposableBean</interfacename> callback |
|
interface</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para>A custom configured <literal>destroy()</literal> |
|
method</para> |
|
</listitem> |
|
</itemizedlist> |
|
</section> |
|
|
|
<section id="beans-factory-lifecycle-processor"> |
|
<title>Startup and shutdown callbacks</title> |
|
|
|
<para>The <interfacename>Lifecycle</interfacename> interface defines |
|
the essential methods for any object that has its own lifecycle |
|
requirements (e.g. starts and stops some background process):</para> |
|
|
|
<programlisting language="java">public interface Lifecycle { |
|
|
|
void start(); |
|
|
|
void stop(); |
|
|
|
boolean isRunning(); |
|
|
|
}</programlisting> |
|
|
|
<para>Any Spring-managed object may implement that interface. Then, |
|
when the ApplicationContext itself starts and stops, it will cascade |
|
those calls to all Lifecycle implementations defined within that context. |
|
It does this by delegating to a <interfacename>LifecycleProcessor</interfacename>: |
|
</para> |
|
|
|
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle { |
|
|
|
void onRefresh(); |
|
|
|
void onClose(); |
|
|
|
}</programlisting> |
|
|
|
<para>Notice that the <interfacename>LifecycleProcessor</interfacename> |
|
is itself an extension of the <interfacename>Lifecycle</interfacename> |
|
interface. It also adds two other methods for reacting to the context |
|
being refreshed and closed.</para> |
|
|
|
<para>The order of startup and shutdown invocations can be important. |
|
If a "depends-on" relationship exists between any two objects, the |
|
dependent side will start <emphasis>after</emphasis> its dependency, |
|
and it will stop <emphasis>before</emphasis> its dependency. However, |
|
at times the direct dependencies are unknown. You may only know that |
|
objects of a certain type should start prior to objects of another |
|
type. In those cases, the <interfacename>SmartLifecycle</interfacename> |
|
interface defines another option, namely the <methodname>getPhase()</methodname> |
|
method as defined on its super-interface, <interfacename>Phased</interfacename>. |
|
</para> |
|
|
|
<programlisting language="java">public interface Phased { |
|
|
|
int getPhase(); |
|
|
|
} |
|
|
|
|
|
public interface SmartLifecycle extends Lifecycle, Phased { |
|
|
|
boolean isAutoStartup(); |
|
|
|
void stop(Runnable callback); |
|
|
|
}</programlisting> |
|
|
|
<para>When starting, the objects with the lowest phase start first, and |
|
when stopping, the reverse order is followed. Therefore, an object that |
|
implements <interfacename>SmartLifecycle</interfacename> and whose getPhase() |
|
method returns <literal>Integer.MIN_VALUE</literal> would be among the first |
|
to start and the last to stop. At the other end of the spectrum, a phase |
|
value of <literal>Integer.MAX_VALUE</literal> would indicate that the |
|
object should be started last and stopped first (likely because it |
|
depends on other processes to be running). When considering the phase value, |
|
it's also important to know that the default phase for any "normal" |
|
<interfacename>Lifecycle</interfacename> object that does not implement |
|
<interfacename>SmartLifecycle</interfacename> would be 0. Therefore, any |
|
negative phase value would indicate that an object should start before |
|
those standard components (and stop after them), and vice versa for any |
|
positive phase value.</para> |
|
|
|
<para>As you can see the stop method defined by <interfacename>SmartLifecycle</interfacename> |
|
accepts a callback. Any implementation <emphasis>must</emphasis> invoke that |
|
callback's run() method after that implementation's shutdown process is complete. |
|
That enables asynchronous shutdown where necessary since the default |
|
implementation of the <interfacename>LifecycleProcessor</interfacename> |
|
interface, <classname>DefaultLifecycleProcessor</classname>, will wait |
|
up to its timeout value for the group of objects within each phase to |
|
invoke that callback. The default per-phase timeout is 30 seconds. You |
|
can override the default lifecycle processor instance by defining a bean |
|
named "lifecycleProcessor" within the context. If you only want to modify |
|
the timeout, then defining the following would be sufficient:</para> |
|
|
|
<programlisting language="xml"><![CDATA[<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> |
|
<!-- timeout value in milliseconds --> |
|
<property name="timeoutPerShutdownPhase" value="10000"/> |
|
</bean>]]></programlisting> |
|
|
|
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename> interface |
|
defines callback methods for the refreshing and closing of the context as well. The |
|
latter will simply drive the shutdown process as if stop() had been called explicitly, |
|
but it will happen when the context is closing. The 'refresh' callback on the other |
|
hand enables another feature of <interfacename>SmartLifecycle</interfacename> beans. |
|
When the context is refreshed (after all objects have been instantiated and initialized), |
|
that callback will be invoked, and at that point the default lifecycle processor will |
|
check the boolean value returned by each <interfacename>SmartLifecycle</interfacename> |
|
object's <methodname>isAutoStartup()</methodname> method. If "true", then that object |
|
will be started at that point rather than waiting for an explicit invocation of the |
|
context's or its own start() method (unlike the context refresh, the context start does |
|
not happen automatically for a standard context implementation). The "phase" value as |
|
well as any "depends-on" relationships will determine the startup order in the same way |
|
as described above.</para> |
|
</section> |
|
|
|
<section id="beans-factory-shutdown"> |
|
<title>Shutting down the Spring IoC container gracefully in non-web |
|
applications</title> |
|
|
|
<note> |
|
<para>This section applies only to non-web applications. Spring's |
|
web-based <interfacename>ApplicationContext</interfacename> |
|
implementations already have code in place to shut down the Spring |
|
IoC container gracefully when the relevant web application is shut |
|
down.</para> |
|
</note> |
|
|
|
<para>If you are using Spring's IoC container in a non-web application |
|
environment; for example, in a rich client desktop environment; you |
|
register a shutdown hook with the JVM. Doing so ensures a graceful |
|
shutdown and calls the relevant destroy methods on your singleton |
|
beans so that all resources are released. Of course, you must still |
|
configure and implement these destroy callbacks correctly.</para> |
|
|
|
<para>To register a shutdown hook, you call the |
|
<methodname>registerShutdownHook()</methodname> method that is |
|
declared on the <classname>AbstractApplicationContext</classname> |
|
class:</para> |
|
|
|
<programlisting language="java">import org.springframework.context.support.AbstractApplicationContext; |
|
import org.springframework.context.support.ClassPathXmlApplicationContext; |
|
|
|
public final class Boot { |
|
|
|
public static void main(final String[] args) throws Exception { |
|
AbstractApplicationContext ctx |
|
= new ClassPathXmlApplicationContext(new String []{"beans.xml"}); |
|
|
|
<lineannotation>// add a shutdown hook for the above context... </lineannotation> |
|
ctx.registerShutdownHook(); |
|
|
|
<lineannotation>// app runs here...</lineannotation> |
|
|
|
<lineannotation>// main method exits, hook is called prior to the app shutting down...</lineannotation> |
|
} |
|
}</programlisting> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-aware"> |
|
<title><interfacename>ApplicationContextAware</interfacename> and |
|
<interfacename>BeanNameAware</interfacename></title> |
|
|
|
<para>When an <interfacename>ApplicationContext</interfacename> creates |
|
a class that implements the |
|
<interfacename>org.springframework.contxt.ApplicationContextAware</interfacename> |
|
interface, the class is provided with a reference to that |
|
<interfacename>ApplicationContext</interfacename>.</para> |
|
|
|
<programlisting language="java">public interface ApplicationContextAware { |
|
|
|
void setApplicationContext(ApplicationContext applicationContext) throws BeansException; |
|
}</programlisting> |
|
|
|
<para>Thus beans can manipulate programmatically the |
|
<interfacename>ApplicationContext</interfacename> that created them, |
|
through the <interfacename>ApplicationContext</interfacename> interface, |
|
or by casting the reference to a known subclass of this interface, such |
|
as <classname>ConfigurableApplicationContext</classname>, which exposes |
|
additional functionality. One use would be the programmatic retrieval of |
|
other beans. Sometimes this capability is useful; however, in general |
|
you should avoid it, because it couples the code to Spring and does not |
|
follow the Inversion of Control style, where collaborators are provided |
|
to beans as properties. Other methods of the ApplicationContext provide |
|
access to file resources, publishing application events, and accessing a |
|
MessageSource. These additional features are described in <xref |
|
linkend="context-introduction" /></para> |
|
|
|
<para>As of Spring 2.5, autowiring is another alternative to obtain |
|
reference to the <interfacename>ApplicationContext</interfacename>. The |
|
"traditional" <literal>constructor</literal> and |
|
<literal>byType</literal> autowiring modes (as described in <xref |
|
linkend="beans-factory-autowire" />) can provide a dependency of type |
|
<interfacename>ApplicationContext</interfacename> for a constructor |
|
argument or setter method parameter, respectively. For more flexibility, |
|
including the ability to autowire fields and multiple parameter methods, |
|
use the new annotation-based autowiring features. If you do, the |
|
<interfacename>ApplicationFactory</interfacename> is autowired into a |
|
field, constructor argument, or method parameter that is expecting the |
|
<interfacename>BeanFactory</interfacename> type if the field, |
|
constructor, or method in question carries the |
|
<interfacename>@Autowired</interfacename> annotation. For more |
|
information, see <xref linkend="beans-autowired-annotation" />.</para> |
|
|
|
<para>When an ApplicationContext creates a class that implements the |
|
<interfacename>org.springframework.beans.factory.BeanNameAware</interfacename> |
|
interface, the class is provided with a reference to the name defined in |
|
its associated object definition.</para> |
|
|
|
<programlisting language="java">public interface BeanNameAware { |
|
|
|
void setBeanName(string name) throws BeansException; |
|
}</programlisting> |
|
|
|
<para>The callback is invoked after population of normal bean properties |
|
but before an initialization callback such as |
|
<interfacename>InitializingBean</interfacename>s |
|
<emphasis>afterPropertiesSet</emphasis> or a custom init-method.</para> |
|
</section> |
|
|
|
<section id="aware-list"> |
|
<title>Other <interfacename>Aware</interfacename> interfaces</title> |
|
|
|
<para>Besides <interfacename>ApplicationContextAware</interfacename> and |
|
<interfacename>BeanNameAware</interfacename> discussed above, Spring offers a range |
|
of <emphasis><interfacename>Aware</interfacename></emphasis> interfaces that allow beans |
|
to indicate to the container that they require a certain <emphasis>infrastructure</emphasis> dependency. |
|
The most important <interfacename>Aware</interfacename> interfaces are summarized below - as a general rule, |
|
the name is a good indication of the dependency type:</para> |
|
|
|
<table id="beans-factory-nature-aware-list" pgwide="1"> |
|
<title><interfacename>Aware</interfacename> interfaces</title> |
|
|
|
<tgroup cols="3"> |
|
<colspec align="left" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Name</entry> |
|
<entry>Injected Dependency</entry> |
|
<entry>Explained in...</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry><para><classname>ApplicationContextAware</classname></para></entry> |
|
<entry><para>Declaring <interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>ApplicationEventPublisherAware</classname></para></entry> |
|
<entry><para>Event publisher of the enclosing <interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="context-introduction"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>BeanClassLoaderAware</classname></para></entry> |
|
<entry><para>Class loader used to load the bean classes.</para></entry> |
|
<entry><para><xref linkend="beans-factory-class"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>BeanFactoryAware</classname></para></entry> |
|
<entry><para>Declaring <interfacename>BeanFactory</interfacename></para></entry> |
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>BeanNameAware</classname></para></entry> |
|
<entry><para>Name of the declaring bean</para></entry> |
|
<entry><para><xref linkend="beans-factory-aware"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>BootstrapContextAware</classname></para></entry> |
|
<entry><para>Resource adapter <interfacename>BootstrapContext</interfacename> the container runs in. Typically available only |
|
in JCA aware <interfacename>ApplicationContext</interfacename>s</para></entry> |
|
<entry><para><xref linkend="cci"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>LoadTimeWeaverAware</classname></para></entry> |
|
<entry><para>Defined <emphasis>weaver</emphasis> for processing class definition at load time</para></entry> |
|
<entry><para><xref linkend="aop-aj-ltw"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>MessageSourceAware</classname></para></entry> |
|
<entry><para>Configured strategy for resolving messages (with support for parametrization and internationalization)</para></entry> |
|
<entry><para><xref linkend="context-introduction"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>NotificationPublisherAware</classname></para></entry> |
|
<entry><para>Spring JMX notification publisher</para></entry> |
|
<entry><para><xref linkend="jmx-notifications"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>PortletConfigAware</classname></para></entry> |
|
<entry><para>Current <interfacename>PortletConfig</interfacename> the container runs in. Valid only in a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="portlet"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>PortletContextAware</classname></para></entry> |
|
<entry><para>Current <interfacename>PortletContext</interfacename> the container runs in. Valid only in a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="portlet"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>ResourceLoaderAware</classname></para></entry> |
|
<entry><para>Configured loader for low-level access to resources</para></entry> |
|
<entry><para><xref linkend="resources"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>ServletConfigAware</classname></para></entry> |
|
<entry><para>Current <interfacename>ServletConfig</interfacename> the container runs in. Valid only in a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="mvc"/></para></entry> |
|
</row> |
|
<row> |
|
<entry><para><classname>ServletContextAware</classname></para></entry> |
|
<entry><para>Current <interfacename>ServletContext</interfacename> the container runs in. Valid only in a web-aware Spring |
|
<interfacename>ApplicationContext</interfacename></para></entry> |
|
<entry><para><xref linkend="mvc"/></para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>Note again that usage of these interfaces ties your code to the Spring API and does not follow the Inversion of Control |
|
style. As such, they are recommended for infrastructure beans that require programmatic access to the container.</para> |
|
|
|
</section> |
|
</section> |
|
|
|
<section id="beans-child-bean-definitions"> |
|
<title>Bean definition inheritance</title> |
|
|
|
<para>A bean definition can contain a lot of configuration information, |
|
including constructor arguments, property values, and container-specific |
|
information such as initialization method, static factory method name, and |
|
so on. A child bean definition inherits configuration data from a parent |
|
definition. The child definition can override some values, or add others, |
|
as needed. Using parent and child bean definitions can save a lot of |
|
typing. Effectively, this is a form of templating.</para> |
|
|
|
<para>If you work with an |
|
<interfacename>ApplicationContext</interfacename> interface |
|
programmatically, child bean definitions are represented by the |
|
<classname>ChildBeanDefinition</classname> class. Most users do not work |
|
with them on this level, instead configuring bean definitions |
|
declaratively in something like the |
|
<classname>ClassPathXmlApplicationContext</classname>. When you use |
|
XML-based configuration metadata, you indicate a child bean definition by |
|
using the <literal>parent</literal> attribute, specifying the parent bean |
|
as the value of this attribute.</para> |
|
|
|
<programlisting language="xml"><bean id="inheritedTestBean" abstract="true" |
|
class="org.springframework.beans.TestBean"> |
|
<property name="name" value="parent"/> |
|
<property name="age" value="1"/> |
|
</bean> |
|
|
|
<bean id="inheritsWithDifferentClass" |
|
class="org.springframework.beans.DerivedTestBean" |
|
<emphasis role="bold">parent="inheritedTestBean"</emphasis> init-method="initialize"> |
|
|
|
<property name="name" value="override"/> |
|
<lineannotation><!-- the age property value of 1 will be inherited from parent --></lineannotation> |
|
|
|
</bean></programlisting> |
|
|
|
<para>A child bean definition uses the bean class from the parent |
|
definition if none is specified, but can also override it. In the latter |
|
case, the child bean class must be compatible with the parent, that is, it |
|
must accept the parent's property values.</para> |
|
|
|
<para>A child bean definition inherits constructor argument values, |
|
property values, and method overrides from the parent, with the option to |
|
add new values. Any initialization method, destroy method, and/or |
|
<literal>static</literal> factory method settings that you specify will |
|
override the corresponding parent settings.</para> |
|
|
|
<para>The remaining settings are <emphasis>always</emphasis> taken from |
|
the child definition: <emphasis>depends on</emphasis>, <emphasis>autowire |
|
mode</emphasis>, <emphasis>dependency check</emphasis>, |
|
<emphasis>singleton</emphasis>, <emphasis>scope</emphasis>, <emphasis>lazy |
|
init</emphasis>.</para> |
|
|
|
<para>The preceding example explicitly marks the parent bean definition as |
|
abstract by using the <literal>abstract</literal> attribute. If the parent |
|
definition does not specify a class, explicitly marking the parent bean |
|
definition as <literal>abstract</literal> is required, as follows:</para> |
|
|
|
<programlisting language="xml"><bean id="inheritedTestBeanWithoutClass" abstract="true"> |
|
<property name="name" value="parent"/> |
|
<property name="age" value="1"/> |
|
</bean> |
|
|
|
<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean" |
|
parent="inheritedTestBeanWithoutClass" init-method="initialize"> |
|
<property name="name" value="override"/> |
|
<lineannotation><!-- age will inherit the value of <literal>1</literal> from the parent bean definition--></lineannotation> |
|
</bean></programlisting> |
|
|
|
<para>The parent bean cannot be instantiated on its own because it is |
|
incomplete, and it is also explicitly marked as |
|
<literal>abstract</literal>. When a definition is |
|
<literal>abstract</literal> like this, it is usable only as a pure |
|
template bean definition that serves as a parent definition for child |
|
definitions. Trying to use such an <literal>abstract</literal> parent bean |
|
on its own, by referring to it as a ref property of another bean or doing |
|
an explicit <methodname>getBean()</methodname> call with the parent bean |
|
id, returns an error. Similarly, the container's internal |
|
<methodname>preInstantiateSingletons()</methodname> method ignores bean |
|
definitions that are defined as abstract.</para> |
|
|
|
<note> |
|
<para><literal>ApplicationContext</literal> pre-instantiates all |
|
singletons by default. Therefore, it is important (at least for |
|
singleton beans) that if you have a (parent) bean definition which you |
|
intend to use only as a template, and this definition specifies a class, |
|
you must make sure to set the <emphasis>abstract</emphasis> attribute to |
|
<emphasis>true</emphasis>, otherwise the application context will |
|
actually (attempt to) pre-instantiate the <literal>abstract</literal> |
|
bean.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-factory-extension"> |
|
<title>Container extension points</title> |
|
|
|
<para>Typically, an application developer does not need to subclass any |
|
<interfacename>ApplicationContext</interfacename> implementation classes. |
|
You can extend The Spring IoC container infinitely by plugging in |
|
implementations of special integration interfaces. The next few sections |
|
describe these integration interfaces.</para> |
|
|
|
<section id="beans-factory-extension-bpp"> |
|
<title>Customizing beans using the |
|
<interfacename>BeanPostProcessor</interfacename> Interface <literal> |
|
</literal></title> |
|
|
|
<para>The <interfacename>BeanPostProcessor</interfacename> interface |
|
defines <firstterm>callback methods</firstterm> that you can implement |
|
to provide your own (or override the container's default) instantiation |
|
logic, dependency-resolution logic, and so forth. If you want to |
|
implement some custom logic after the Spring container finishes |
|
instantiating, configuring, and otherwise initializing a bean, you can |
|
plug in one or more <interfacename>BeanPostProcessor</interfacename> |
|
implementations.</para> |
|
|
|
<para>You can configure multiple <literal>BeanPostProcessor</literal> |
|
interfaces. You can control the order in which these |
|
<literal>BeanPostProcessor</literal> interfaces execute by setting the |
|
<literal>order</literal> property. You can set this property only if the |
|
<interfacename>BeanPostProcessor</interfacename> implements the |
|
<interfacename>Ordered</interfacename> interface; if you write your own |
|
<interfacename>BeanPostProcessor</interfacename> you should consider |
|
implementing the <interfacename>Ordered</interfacename> interface too. |
|
For more details, consult the Javadoc for the |
|
<interfacename>BeanPostProcessor</interfacename> and |
|
<interfacename>Ordered</interfacename> interfaces.</para> |
|
|
|
<note> |
|
<para><literal>BeanPostProcessor</literal>s operate on bean (or |
|
object) <emphasis>instances</emphasis>; that is to say, the Spring IoC |
|
container instantiates a bean instance and <emphasis>then</emphasis> |
|
<literal>BeanPostProcessor</literal> interfaces do their work.</para> |
|
|
|
<para><literal>BeanPostProcessor</literal> interfaces are scoped |
|
<emphasis>per-container</emphasis>. This is only relevant if you are |
|
using container hierarchies. If you define a |
|
<interfacename>BeanPostProcessor</interfacename> in one container, it |
|
will <emphasis>only</emphasis> do its work on the beans in that |
|
container. Beans that are defined in one container are not |
|
post-processed by a <literal>BeanPostProcessor</literal> in another |
|
container, even if both containers are part of the same |
|
hierarchy.</para> |
|
|
|
<para>To change the actual bean definition (that is, the recipe that |
|
defines the bean), you instead need to use a |
|
<interfacename>BeanFactoryPostProcessor</interfacename>, described |
|
below in <xref |
|
linkend="beans-factory-extension-factory-postprocessors" />.</para> |
|
</note> |
|
|
|
<para>The |
|
<interfacename>org.springframework.beans.factory.config.BeanPostProcessor</interfacename> |
|
interface consists of exactly two callback methods. When such a class is |
|
registered as a post-processor with the container, for each bean |
|
instance that is created by the container, the post-processor gets a |
|
callback from the container both <emphasis>before</emphasis> container |
|
initialization methods (such as <emphasis>afterPropertiesSet</emphasis> |
|
and any declared init method) are called, and also afterwards. The |
|
post-processor can take any action with the bean instance, including |
|
ignoring the callback completely. A bean post-processor typically checks |
|
for callback interfaces, or may wrap a bean with a proxy. Some Spring |
|
AOP infrastructure classes are implemented as bean post-processors and |
|
they do this proxy-wrapping logic.</para> |
|
|
|
<para>An <interfacename>ApplicationContext</interfacename> |
|
<emphasis>automatically detects</emphasis> any beans that are defined in |
|
the configuration metadata it receives that implement the |
|
<interfacename>BeanPostProcessor</interfacename> interface. The |
|
<interfacename>ApplicationContext</interfacename> registers these beans |
|
as post-processors, to be then called appropriately by the container |
|
upon bean creation. You can then deploy the post-processors as you would |
|
any bean.</para> |
|
|
|
<note> |
|
<title><interfacename>BeanPostProcessors</interfacename> and AOP |
|
auto-proxying</title> |
|
|
|
<para>Classes that implement the |
|
<interfacename>BeanPostProcessor</interfacename> interface are |
|
<emphasis>special</emphasis>, and so they are treated differently by |
|
the container. All <interfacename>BeanPostProcessors</interfacename> |
|
<emphasis>and their directly referenced beans</emphasis> are |
|
instantiated on startup, as part of the special startup phase of the |
|
<interfacename>ApplicationContext</interfacename>. Next, all those |
|
<interfacename>BeanPostProcessors</interfacename> are registered in a |
|
sorted fashion - and applied to all further beans. Because AOP |
|
auto-proxying is implemented as a |
|
<interfacename>BeanPostProcessor</interfacename> itself, no |
|
<interfacename>BeanPostProcessors</interfacename> or directly |
|
referenced beans are eligible for auto-proxying, and thus do not have |
|
aspects woven into them.</para> |
|
|
|
<para>For any such bean, you should see an info log message: |
|
<emphasis><quote>Bean foo is not eligible for getting processed by all |
|
BeanPostProcessor interfaces (for example: not eligible for |
|
auto-proxying)</quote>.</emphasis></para> |
|
</note> |
|
|
|
<para>The following examples show how to write, register, and use |
|
<literal>BeanPostProcessors</literal> in the context of an |
|
<interfacename>ApplicationContext</interfacename>.</para> |
|
|
|
<section id="beans-factory-extension-bpp-examples-hw"> |
|
<title>Example: Hello World, |
|
<interfacename>BeanPostProcessor</interfacename>-style</title> |
|
|
|
<para>This first example illustrates basic usage. The example shows a |
|
custom <interfacename>BeanPostProcessor</interfacename> implementation |
|
that invokes the <methodname>toString()</methodname> method of each |
|
bean as it is created by the container and prints the resulting string |
|
to the system console.</para> |
|
|
|
<para>Find below the custom |
|
<interfacename>BeanPostProcessor</interfacename> implementation class |
|
definition:</para> |
|
|
|
<programlisting language="java">package scripting; |
|
|
|
import org.springframework.beans.factory.config.BeanPostProcessor; |
|
import org.springframework.beans.BeansException; |
|
|
|
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor { |
|
|
|
<lineannotation>// simply return the instantiated bean as-is</lineannotation> |
|
public Object postProcessBeforeInitialization(Object bean, String beanName) |
|
throws BeansException { |
|
return bean; <lineannotation>// we could potentially return <emphasis>any</emphasis> object reference here...</lineannotation> |
|
} |
|
|
|
public Object postProcessAfterInitialization(Object bean, String beanName) |
|
throws BeansException { |
|
System.out.println("Bean '" + beanName + "' created : " + bean.toString()); |
|
return bean; |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:lang="http://www.springframework.org/schema/lang" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/lang |
|
http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"> |
|
|
|
<lang:groovy id="messenger" |
|
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"> |
|
<lang:property name="message" value="Fiona Apple Is Just So Dreamy."/> |
|
</lang:groovy> |
|
|
|
<lineannotation><!-- |
|
when the above bean (messenger) is instantiated, this custom |
|
<interfacename>BeanPostProcessor</interfacename> implementation will output the fact to the system console |
|
--></lineannotation> |
|
<bean class="scripting.InstantiationTracingBeanPostProcessor"/> |
|
|
|
</beans></programlisting> |
|
|
|
<para>Notice how the |
|
<classname>InstantiationTracingBeanPostProcessor</classname> is simply |
|
defined. It does not even have a name, and because it is a bean it can |
|
be dependency-injected just like any other bean. (The preceding |
|
configuration also defines a bean that is backed by a Groovy script. |
|
The Spring 2.0 dynamic language support is detailed in the chapter |
|
entitled <xref linkend="dynamic-language" />.)</para> |
|
|
|
<para>The following small driver script executes the preceding code |
|
and configuration:</para> |
|
|
|
<programlisting language="java">import org.springframework.context.ApplicationContext; |
|
import org.springframework.context.support.ClassPathXmlApplicationContext; |
|
import org.springframework.scripting.Messenger; |
|
|
|
public final class Boot { |
|
|
|
public static void main(final String[] args) throws Exception { |
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml"); |
|
Messenger messenger = (Messenger) ctx.getBean("messenger"); |
|
System.out.println(messenger); |
|
} |
|
}</programlisting> |
|
|
|
<para>The output of the preceding execution resembles the |
|
following:</para> |
|
|
|
<programlisting>Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 |
|
org.springframework.scripting.groovy.GroovyMessenger@272961</programlisting> |
|
</section> |
|
|
|
<section id="beans-factory-extension-bpp-examples-rabpp"> |
|
<title>Example: The |
|
<classname>RequiredAnnotationBeanPostProcessor</classname></title> |
|
|
|
<para>Using callback interfaces or annotations in conjunction with a |
|
custom <interfacename>BeanPostProcessor</interfacename> implementation |
|
is a common means of extending the Spring IoC container. An example is |
|
shown in <xref linkend="metadata-annotations-required" /> which |
|
demonstrates the usage of a custom |
|
<interfacename>BeanPostProcessor</interfacename> implementation that |
|
ships with the Spring distribution which ensures that JavaBean |
|
properties on beans that are marked with an (arbitrary) annotation are |
|
actually (configured to be) dependency-injected with a value.</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-extension-factory-postprocessors"> |
|
<title>Customizing configuration metadata with |
|
<interfacename>BeanFactoryPostProcessor</interfacename> |
|
interface</title> |
|
|
|
<para>The next extension point that we will look at is the |
|
<interfacename>org.springframework.beans.factory.config.BeanFactoryPostProcessor</interfacename>. |
|
The semantics of this interface are similar to the |
|
<interfacename>BeanPostProcessor</interfacename>, with one major |
|
difference: <literal>BeanFactoryPostProcessor</literal>s operate on the |
|
<emphasis>bean configuration metadata</emphasis>; that is, the Spring |
|
IoC container allows <literal>BeanFactoryPostProcessors</literal> to |
|
read the configuration metadata and potentially change it |
|
<emphasis>before</emphasis> the container instantiates any beans other |
|
than <literal>BeanFactoryPostProcessors</literal>.</para> |
|
|
|
<para>You can configure multiple |
|
<literal>BeanFactoryPostProcessors</literal>. You can control the order |
|
in which these <literal>BeanFactoryPostProcessors</literal> execute by |
|
setting the <literal>order</literal> property. However, you can only set |
|
this property if the |
|
<interfacename>BeanFactoryPostProcessor</interfacename> implements the |
|
<interfacename>Ordered</interfacename> interface. If you write your own |
|
<interfacename>BeanFactoryPostProcessor,</interfacename> you should |
|
consider implementing the <interfacename>Ordered</interfacename> |
|
interface too; consult the Javadoc for the |
|
<interfacename>BeanFactoryPostProcessor</interfacename> and |
|
<interfacename>Ordered</interfacename> interfaces for more |
|
details.</para> |
|
|
|
<note> |
|
<para>If you want to change the actual bean |
|
<emphasis>instances</emphasis> (the objects that are created from the |
|
configuration metadata), then you instead need to use a |
|
<interfacename>BeanPostProcessor</interfacename> (described above in |
|
<xref linkend="beans-factory-extension-bpp" />.</para> |
|
|
|
<para>Also, <literal>BeanFactoryPostProcessors</literal> are scoped |
|
<emphasis>per-container</emphasis>. This is only relevant if you are |
|
using container hierarchies. If you define a |
|
<interfacename>BeanFactoryPostProcessor</interfacename> in one |
|
container, it will <emphasis>only</emphasis> do its stuff on the bean |
|
definitions in that container. Bean definitions in another container |
|
will not be post-processed by |
|
<literal>BeanFactoryPostProcessors</literal> in another container, |
|
even if both containers are part of the same hierarchy.</para> |
|
</note> |
|
|
|
<para>A bean factory post-processor is executed automatically when it is |
|
declared inside of an <interfacename>ApplicationContext,</interfacename> |
|
in order to apply changes to the configuration metadata that defines a |
|
container. Spring includes a number of pre-existing bean factory |
|
post-processors, such as |
|
<classname>PropertyOverrideConfigurer</classname> and |
|
<classname>PropertyPlaceholderConfigurer. </classname>A custom |
|
<interfacename>BeanFactoryPostProcessor</interfacename> can also be |
|
used, for example, to register custom property editors.</para> |
|
|
|
<anchor id="beans-factory-autodetect-beanfactorypostprocessors" /> |
|
|
|
<para>An <interfacename>ApplicationContext</interfacename> detects any |
|
beans that are deployed into it and that implement the |
|
<interfacename>BeanFactoryPostProcessor</interfacename> interface. It |
|
automatically uses these beans as bean factory post-processors, at the |
|
appropriate time. You can then deploy these post-processor beans as you |
|
would any other bean.</para> |
|
|
|
<note> |
|
<para>As with <literal>BeanPostProcessors</literal>, you typically do |
|
not want <literal>BeanFactoryPostProcessors</literal> marked as |
|
lazy-initialized. If they are marked as such, the Spring container |
|
never instantiates them, and thus they cannot apply their custom |
|
logic. If you use the <literal>default-lazy-init</literal> attribute |
|
on the declaration of your <literal><beans/></literal> element, |
|
be sure to mark your various |
|
<interfacename>BeanFactoryPostProcessor</interfacename> bean |
|
definitions with <literal>lazy-init="false"</literal>.</para> |
|
</note> |
|
|
|
<section id="beans-factory-placeholderconfigurer"> |
|
<title>Example: the |
|
<interfacename>PropertyPlaceholderConfigurer</interfacename></title> |
|
|
|
<para>You use the |
|
<interfacename>PropertyPlaceholderConfigurer</interfacename> to |
|
externalize property values from a bean definition into another |
|
separate file in the standard Java <classname>Properties</classname> |
|
format. Doing so enables the person deploying an application to |
|
customize environment-specific properties such as database URLs and |
|
passwords, without the complexity or risk of modifying the main XML |
|
definition file or files for the container.</para> |
|
|
|
<!-- MLP: Beverly to review following 2 paragraphs --> |
|
|
|
<para>Consider the following XML-based configuration metadata |
|
fragment, where a <interfacename>DataSource</interfacename> with |
|
placeholder values is defined. The example shows properties configured |
|
from an external <classname>Properties</classname> file. At runtime, a |
|
<classname>PropertyPlaceholderConfigurer</classname> is applied to the |
|
metadata that will replace some properties of the DataSource. The |
|
values to replace are specified as 'placeholders' of the form |
|
${property-name} which follows the Ant / Log4J / JSP EL style.</para> |
|
|
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> |
|
<property name="locations" value="classpath:com/foo/jdbc.properties"/> |
|
</bean> |
|
|
|
<bean id="dataSource" destroy-method="close" |
|
class="org.apache.commons.dbcp.BasicDataSource"> |
|
<property name="driverClassName" value="<emphasis role="bold">${jdbc.driverClassName}</emphasis>"/> |
|
<property name="url" value="<emphasis role="bold">${jdbc.url}</emphasis>"/> |
|
<property name="username" value="<emphasis role="bold">${jdbc.username}</emphasis>"/> |
|
<property name="password" value="<emphasis role="bold">${jdbc.password}</emphasis>"/> |
|
</bean></programlisting> |
|
|
|
<para>The actual values come from another file in the standard Java |
|
<classname>Properties</classname> format:</para> |
|
|
|
<programlisting language="java">jdbc.driverClassName=org.hsqldb.jdbcDriver |
|
jdbc.url=jdbc:hsqldb:hsql://production:9002 |
|
jdbc.username=sa |
|
jdbc.password=root</programlisting> |
|
|
|
<para>Therefore, the string ${jdbc.username} is replaced at runtime |
|
with the value 'sa' and similarly for other placeholder values that |
|
match to keys in the property file. The PropertyPlaceholderConfigurer |
|
checks for placeholders in most locations of a bean definition and the |
|
placeholder prefix and suffix can be customized.</para> |
|
|
|
<para>With the <literal>context</literal> namespace introduced in |
|
Spring 2.5, it is possible to configure property placeholders with a |
|
dedicated configuration element. You can provide multiple locations as |
|
a comma-separated list in the <literal>location</literal> |
|
attribute.</para> |
|
|
|
<programlisting language="xml"><context:property-placeholder location="classpath:com/foo/jdbc.properties"/></programlisting> |
|
|
|
<para>The <classname>PropertyPlaceholderConfigurer</classname> does |
|
not look for properties only in the <classname>Properties</classname> |
|
file you specify, but also checks against the Java |
|
<classname>System</classname> properties if it cannot find a property |
|
you are trying to use. You can customize this behavior by setting the |
|
<literal>systemPropertiesMode</literal> property of the configurer. It |
|
has three values that specify configurer behavior: always override, |
|
<emphasis>never</emphasis> override, and override only if the property |
|
is not found in the properties file specified. <!--What property is it overriding and what will replace the overridden value?--> |
|
<!--MLP: override a value in the Properties with one from the 'systemProperties' --> |
|
Consult the Javadoc for the |
|
<classname>PropertyPlaceholderConfigurer</classname> for more |
|
information.</para> |
|
|
|
<tip> |
|
<title>Class name substitution</title> |
|
|
|
<para>You can use the |
|
<classname>PropertyPlaceholderConfigurer</classname> to substitute |
|
class names, which is sometimes useful when you have to pick a |
|
particular implementation class at runtime. For example:</para> |
|
|
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> |
|
<property name="locations"> |
|
<value>classpath:com/foo/strategy.properties</value> |
|
</property> |
|
<property name="properties"> |
|
<value>custom.strategy.class=com.foo.DefaultStrategy</value> |
|
</property> |
|
</bean> |
|
|
|
<bean id="serviceStrategy" class="${custom.strategy.class}"/></programlisting> |
|
|
|
<para>If the class cannot be resolved at runtime to a valid class, |
|
resolution of the bean fails when it is about to be created, which |
|
is during the <methodname>preInstantiateSingletons()</methodname> |
|
phase of an <interfacename>ApplicationContext</interfacename> for a |
|
non-lazy-init bean.</para> |
|
</tip> |
|
</section> |
|
|
|
<section id="beans-factory-overrideconfigurer"> |
|
<title>Example: the |
|
<classname>PropertyOverrideConfigurer</classname></title> |
|
|
|
<para>The <classname>PropertyOverrideConfigurer</classname>, another |
|
bean factory post-processor, resembles the |
|
<interfacename>PropertyPlaceholderConfigurer</interfacename>, but |
|
unlike the latter, the original definitions can have default values or |
|
no values at all for bean properties. If an overriding |
|
<classname>Properties</classname> file does not have an entry for a |
|
certain bean property, the default context definition is used.</para> |
|
|
|
<para>Note that the bean definition is <emphasis>not</emphasis> aware |
|
of being overridden, so it is not immediately obvious from the XML |
|
definition file that the override configurer is used. In case of |
|
multiple <classname>PropertyOverrideConfigurer</classname> instances |
|
that define different values for the same bean property, the last one |
|
wins, due to the overriding mechanism.</para> |
|
|
|
<para>Properties file configuration lines take this format:</para> |
|
|
|
<programlisting language="java">beanName.property=value</programlisting> |
|
|
|
<para>For example:</para> |
|
|
|
<programlisting language="java">dataSource.driverClassName=com.mysql.jdbc.Driver |
|
dataSource.url=jdbc:mysql:mydb</programlisting> |
|
|
|
<para>This example file is usable against a container definition that |
|
contains a bean called <emphasis>dataSource</emphasis>, which has |
|
<emphasis>driver</emphasis> and <emphasis>url</emphasis> |
|
properties.</para> |
|
|
|
<para>Compound property names are also supported, as long as every |
|
component of the path except the final property being overridden is |
|
already non-null (presumably initialized by the constructors). In this |
|
example...</para> |
|
|
|
<programlisting language="java">foo.fred.bob.sammy=123</programlisting> |
|
|
|
<para>... the <literal>sammy</literal> property of the |
|
<literal>bob</literal> property of the <literal>fred</literal> |
|
property of the <literal>foo</literal> bean is set to the scalar value |
|
<literal>123</literal>.</para> |
|
|
|
<para><note> |
|
<para>Specified override values are always |
|
<emphasis>literal</emphasis> values; they are not translated into |
|
bean references. This convention also applies when the original |
|
value in the XML bean definition specifies a bean |
|
reference.</para> |
|
</note></para> |
|
|
|
<para>With the <literal>context</literal> namespace introduced in |
|
Spring 2.5, it is possible to configure property overriding with a |
|
dedicated configuration element:</para> |
|
|
|
<programlisting language="xml"><context:property-override location="classpath:override.properties"/></programlisting> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-factory-extension-factorybean"> |
|
<title>Customizing instantiation logic with the |
|
<interfacename>FactoryBean</interfacename> Interface <literal> |
|
</literal></title> |
|
|
|
<para>You implement the |
|
<interfacename>org.springframework.beans.factory.FactoryBean</interfacename> |
|
interface for objects that <emphasis>are themselves |
|
factories</emphasis>.</para> |
|
|
|
<para>The <interfacename>FactoryBean</interfacename> interface is a |
|
point of pluggability into the Spring IoC container's instantiation |
|
logic. If you have complex initialization code that is better expressed |
|
in Java as opposed to a (potentially) verbose amount of XML, you can |
|
create your own <interfacename>FactoryBean</interfacename>, write the |
|
complex initialization inside that class, and then plug your custom |
|
<interfacename>FactoryBean</interfacename> into the container.</para> |
|
|
|
<para>The <interfacename>FactoryBean</interfacename> interface provides |
|
three methods:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para><methodname>Object getObject()</methodname>: returns an |
|
instance of the object this factory creates. The instance can |
|
possibly be shared, depending on whether this factory returns |
|
singletons or prototypes.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><methodname>boolean isSingleton()</methodname>: returns |
|
<literal>true</literal> if this |
|
<interfacename>FactoryBean</interfacename> returns singletons, |
|
<literal>false</literal> otherwise.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><methodname>Class getObjectType()</methodname>: returns the |
|
object type returned by the <methodname>getObject()</methodname> |
|
method or <literal>null</literal> if the type is not known in |
|
advance</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>The <interfacename>FactoryBean</interfacename> concept and |
|
interface is used in a number of places within the Spring Framework; |
|
more than 50 implementations of the |
|
<interfacename>FactoryBean</interfacename> interface ship with Spring |
|
itself.</para> |
|
|
|
<para>When you need to ask a container for an actual |
|
<interfacename>FactoryBean</interfacename> instance itself, not the bean |
|
it produces, you preface the bean id with the ampersand symbol |
|
<literal>&</literal> (without quotes) when calling the |
|
<methodname>getBean</methodname> method of the |
|
<interfacename>ApplicationContext</interfacename>. So for a given |
|
<interfacename>FactoryBean</interfacename> with an id of |
|
<literal>myBean</literal>, invoking <literal>getBean("myBean")</literal> |
|
on the container returns the product of the |
|
<interfacename>FactoryBean</interfacename>, and invoking |
|
<literal>getBean("&myBean")</literal> returns the |
|
<interfacename>FactoryBean</interfacename> instance itself.<!--Moved ApplicationContext section to almost the end of the doc, right before BeanFactory and renamed it Additional Capabilities of.--></para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-annotation-config"> |
|
<title>Annotation-based container configuration</title> |
|
|
|
<sidebar> |
|
<title>Are annotations better then XML for configuring Spring?</title> |
|
|
|
<para>The introduction of annotation based configurations raised the question of whether |
|
this approach is better or not then XML. The short answer is <emphasis>it depends.</emphasis>. |
|
The long answer is that each approach has it's pros and cons and usually it's up to the developer |
|
to decide which strategy suits her better. |
|
Due to the way they are defined, annotations provide a lot of context in their declaration leading |
|
to shorter, more concise configurations. However XML excels at wiring up components without touching |
|
their source code or recompile them. Some prefer having the wiring close to the source while |
|
others argue that annotated classes are no longer POJOs and further more that the configuration becomes |
|
decentralized and harder to control.</para> |
|
<para> |
|
No matter the choice, Spring can accomodate both styles and even mix them together. It's worth pointing |
|
out that through its <link linkend="beans-java">JavaConfig</link> option, Spring allows annotations to |
|
be used in a non-invasive way, without touching the target components source code and that |
|
in terms of tooling, all configuration styles are supported by the <ulink url="http://www.springsource.com/products/sts">SpringSource Tool Suite</ulink>. |
|
</para> |
|
</sidebar> |
|
|
|
<para> |
|
An alternative to XML setups is provided by annotation-based configuration which rely |
|
on the bytecode metadata for wiring up components instead on angle-bracket declarations. |
|
Instead of using XML to describe a bean wiring, the developers moves the configuration into |
|
the component class itself by using annotations on relevant class, method or field declaration. |
|
|
|
As mentioned in <xref linkend="beans-factory-extension-bpp-examples-rabpp" />, using a |
|
<interfacename>BeanPostProcessor</interfacename> in conjunction with |
|
annotations is a common means of extending the Spring IoC container. For |
|
example, Spring 2.0 introduced the possibility of enforcing required |
|
properties with the <link |
|
linkend="metadata-annotations-required">@Required</link> annotation. As of |
|
Spring 2.5, it is now possible to follow that same general approach to |
|
drive Spring's dependency injection. Essentially, the |
|
<interfacename>@Autowired</interfacename> annotation provides the same |
|
capabilities as described in <xref linkend="beans-factory-autowire" /> but |
|
with more fine-grained control and wider applicability. Spring 2.5 also |
|
adds support for JSR-250 annotations such as |
|
<interfacename>@Resource</interfacename>, |
|
<interfacename>@PostConstruct</interfacename>, and |
|
<interfacename>@PreDestroy</interfacename>. Spring 3.0 adds support for |
|
JSR-330 (Dependency Injection for Java) annotations contained in the |
|
javax.inject package such as <classname>@Inject</classname>, |
|
<literal>@Qualifier, @Named, and @Provider</literal> if the JSR330 jar is |
|
present on the classpath. Use of these annotations also requires that |
|
certain <interfacename>BeanPostProcessors</interfacename> be registered |
|
within the Spring container. As always, you can register them as |
|
individual bean definitions, but they can also be implicitly registered by |
|
including the following tag in an XML-based Spring configuration (notice |
|
the inclusion of the <literal>context</literal> namespace):</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
<lineannotation>xmlns:context="http://www.springframework.org/schema/context"</lineannotation> |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/context |
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
|
|
|
<lineannotation><context:annotation-config/></lineannotation> |
|
|
|
</beans></programlisting> |
|
|
|
<para>(The implicitly registered post-processors include <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"><classname>AutowiredAnnotationBeanPostProcessor</classname></ulink>, |
|
<ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"><classname>CommonAnnotationBeanPostProcessor</classname></ulink>, |
|
<ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html"><classname>PersistenceAnnotationBeanPostProcessor</classname></ulink>, |
|
as well as the aforementioned <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"><classname>RequiredAnnotationBeanPostProcessor</classname></ulink>.)</para> |
|
|
|
<note> |
|
<para><literal><context:annotation-config/></literal> only looks |
|
for annotations on beans in the same application context in which it is |
|
defined. This means that, if you put |
|
<literal><context:annotation-config/></literal> in a |
|
<interfacename>WebApplicationContext</interfacename> for a |
|
<classname>DispatcherServlet</classname>, it only checks for |
|
<interfacename>@Autowired</interfacename> beans in your controllers, and |
|
not your services. See <xref linkend="mvc-servlet" /> for more |
|
information.</para> |
|
</note> |
|
|
|
<section id="beans-required-annotation"> |
|
<title><interfacename>@Required</interfacename></title> |
|
|
|
<para>The <interfacename>@Required</interfacename> annotation applies to |
|
bean property setter methods, as in the following example:</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
@Required |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>This annotation simply indicates that the affected bean property |
|
must be populated at configuration time, through an explicit property |
|
value in a bean definition or through autowiring. The container throws |
|
an exception if the affected bean property has not been populated; this |
|
allows for eager and explicit failure, avoiding |
|
<classname>NullPointerException</classname>s or the like later on. It is |
|
still recommended that you put assertions into the bean class itself, |
|
for example, into an init method. Doing so enforces those required |
|
references and values even when you use the class outside of a |
|
container.</para> |
|
</section> |
|
|
|
<section id="beans-autowired-annotation"> |
|
<title><interfacename>@Autowired and @Inject</interfacename></title> |
|
|
|
<para>As expected, you can apply the |
|
<interfacename>@Autowired</interfacename> annotation to "traditional" |
|
setter methods:</para> |
|
|
|
<note> |
|
<para>JSR 330's @Inject annotation can be used in place of Spring's |
|
<interfacename>@Autowired</interfacename> in the examples below. |
|
<interfacename>@Inject</interfacename> does not have a required |
|
property unlike Spring's <interfacename>@Autowire</interfacename> |
|
annotation which has a <literal>required</literal> property to |
|
indicate if the value being injected is optional. This behavior is |
|
enabled automatically if you have the JSR 330 JAR on the |
|
classpath.</para> |
|
</note> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
@Autowired |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>You can also apply the annotation to methods with arbitrary names |
|
and/or multiple arguments:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
private MovieCatalog movieCatalog; |
|
|
|
private CustomerPreferenceDao customerPreferenceDao; |
|
|
|
@Autowired |
|
public void prepare(MovieCatalog movieCatalog, |
|
CustomerPreferenceDao customerPreferenceDao) { |
|
this.movieCatalog = movieCatalog; |
|
this.customerPreferenceDao = customerPreferenceDao; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>You can apply <interfacename>@Autowired</interfacename> to |
|
constructors and fields:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
private MovieCatalog movieCatalog; |
|
|
|
private CustomerPreferenceDao customerPreferenceDao; |
|
|
|
@Autowired |
|
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { |
|
this.customerPreferenceDao = customerPreferenceDao; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>It is also possible to provide <emphasis>all</emphasis> beans of a |
|
particular type from the |
|
<interfacename>ApplicationContext</interfacename> by adding the |
|
annotation to a field or method that expects an array of that |
|
type:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
private MovieCatalog[] movieCatalogs; |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>The same applies for typed collections:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
private Set<MovieCatalog> movieCatalogs; |
|
|
|
@Autowired |
|
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) { |
|
this.movieCatalogs = movieCatalogs; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>Even typed Maps can be autowired as long as the expected key type |
|
is <classname>String</classname>. The Map values will contain all beans |
|
of the expected type, and the keys will contain the corresponding bean |
|
names:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
private Map<String, MovieCatalog> movieCatalogs; |
|
|
|
@Autowired |
|
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) { |
|
this.movieCatalogs = movieCatalogs; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>By default, the autowiring fails whenever |
|
<emphasis>zero</emphasis> candidate beans are available; the default |
|
behavior is to treat annotated methods, constructors, and fields as |
|
indicating <emphasis>required</emphasis> dependencies. This behavior can |
|
be changed as demonstrated below.</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
@Autowired(required=false) |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<note> |
|
<para>Only <emphasis>one annotated constructor per-class</emphasis> |
|
can be marked as <emphasis>required</emphasis>, but multiple |
|
non-required constructors can be annotated. In that case, each is |
|
considered among the candidates and Spring uses the |
|
<emphasis>greediest</emphasis> constructor whose dependencies can be |
|
satisfied, that is the constructor that has the largest number of |
|
arguments.</para> |
|
|
|
<para><interfacename>@Autowired</interfacename>'s |
|
<emphasis>required</emphasis> attribute is recommended over the |
|
<interfacename>@Required</interfacename> annotation. The |
|
<emphasis>required</emphasis> attribute indicates that the property is |
|
not required for autowiring purposes, the property is ignored if it |
|
cannot be autowired. <interfacename>@Required</interfacename>, on the |
|
other hand, is stronger in that it enforces the property that was set |
|
by any means supported by the container. If no value is injected, a |
|
corresponding exception is raised.</para> |
|
</note> |
|
|
|
<para>You can also use <interfacename>@Autowired</interfacename> for |
|
interfaces that are well-known resolvable dependencies: |
|
<interfacename>BeanFactory</interfacename>, |
|
<interfacename>ApplicationContext</interfacename>, |
|
<interfacename>ResourceLoader</interfacename>, |
|
<interfacename>ApplicationEventPublisher</interfacename>, and |
|
<interfacename>MessageSource</interfacename>. These interfaces and their |
|
extended interfaces, such as |
|
<interfacename>ConfigurableApplicationContext</interfacename> or |
|
<interfacename>ResourcePatternResolver</interfacename>, are |
|
automatically resolved, with no special setup necessary.</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
private ApplicationContext context; |
|
|
|
public MovieRecommender() { |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
</section> |
|
|
|
<section id="beans-autowired-annotation-qualifiers"> |
|
<title>Fine-tuning annotation-based autowiring with qualifiers</title> |
|
|
|
<para>Because autowiring by type may lead to multiple candidates, it is |
|
often necessary to have more control over the selection process. One way |
|
to accomplish this is with Spring's |
|
<interfacename>@Qualifier</interfacename> annotation. You can associate |
|
qualifier values with specific arguments, narrowing the set of type |
|
matches so that a specific bean is chosen for each argument. In the |
|
simplest case, this can be a plain descriptive value:</para> |
|
|
|
<note> |
|
<para>JSR 330's <interfacename>@Qualifier</interfacename> annotation |
|
can only be applied as a meta-annotation unlike Spring's @Qualifier |
|
which takes a string property to discriminate among multiple injection |
|
candidates and can be placed on annotations as well as types, fields, |
|
methods, constructors, and parameters.</para> |
|
</note> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
<emphasis role="bold">@Qualifier("main")</emphasis> |
|
private MovieCatalog movieCatalog; |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>The <interfacename>@Qualifier</interfacename> annotation can also |
|
be specified on individual constructor arguments or method |
|
parameters:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
private MovieCatalog movieCatalog; |
|
|
|
private CustomerPreferenceDao customerPreferenceDao; |
|
|
|
@Autowired |
|
public void prepare(<emphasis role="bold">@Qualifier("main")</emphasis> MovieCatalog movieCatalog, |
|
CustomerPreferenceDao customerPreferenceDao) { |
|
this.movieCatalog = movieCatalog; |
|
this.customerPreferenceDao = customerPreferenceDao; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>The corresponding bean definitions appear as follows. The bean |
|
with qualifier value "main" is wired with the constructor argument that |
|
is qualified with the same value.</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:context="http://www.springframework.org/schema/context" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/context |
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
|
|
|
<context:annotation-config/> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<emphasis role="bold"><qualifier value="main"/></emphasis> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<emphasis role="bold"><qualifier value="action"/></emphasis> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean id="movieRecommender" class="example.MovieRecommender"/> |
|
|
|
</beans> |
|
</programlisting> |
|
|
|
<para>For a fallback match, the bean name is considered a default |
|
qualifier value. Thus you can define the bean with an id "main" instead |
|
of the nested qualifier element, leading to the same matching result. |
|
However, although you can use this convention to refer to specific beans |
|
by name, <interfacename>@Autowired</interfacename> is fundamentally |
|
about type-driven injection with optional semantic qualifiers. This |
|
means that qualifier values, even with the bean name fallback, always |
|
have narrowing semantics within the set of type matches; they do not |
|
semantically express a reference to a unique bean id. Good qualifier |
|
values are "main" or "EMEA" or "persistent", expressing characteristics |
|
of a specific component that are independent from the bean id, which may |
|
be auto-generated in case of an anonymous bean definition like the one |
|
in the preceding example.</para> |
|
|
|
<para>Qualifiers also apply to typed collections, as discussed above, |
|
for example, to <literal>Set<MovieCatalog></literal>. In this |
|
case, all matching beans according to the declared qualifiers are |
|
injected as a collection. This implies that qualifiers do not have to be |
|
unique; they rather simply constitute filtering criteria. For example, |
|
you can define multiple <classname>MovieCatalog</classname> beans with |
|
the same qualifier value "action"; all of which would be injected into a |
|
<literal>Set<MovieCatalog></literal> annotated with |
|
<literal>@Qualifier("action")</literal>.</para> |
|
|
|
<tip> |
|
<para>If you intend to express annotation-driven injection by name, do |
|
not primarily use <interfacename>@Autowired</interfacename>, even if |
|
is technically capable of referring to a bean name through |
|
<interfacename>@Qualifier</interfacename> values. Instead, use the |
|
JSR-250 <interfacename>@Resource</interfacename> annotation, which is |
|
semantically defined to identify a specific target component by its |
|
unique name, with the declared type being irrelevant for the matching |
|
process.</para> |
|
|
|
<para>As a specific consequence of this semantic difference, beans |
|
that are themselves defined as a collection or map type cannot be |
|
injected through <interfacename>@Autowired</interfacename>, because |
|
type matching is not properly applicable to them. Use |
|
<interfacename>@Resource</interfacename> for such beans, referring to |
|
the specific collection or map bean by unique name.</para> |
|
|
|
<para><interfacename>@Autowired</interfacename> applies to fields, |
|
constructors, and multi-argument methods, allowing for narrowing |
|
through qualifier annotations at the parameter level. By contrast, |
|
<interfacename>@Resource</interfacename> is supported only for fields |
|
and bean property setter methods with a single argument. As a |
|
consequence, stick with qualifiers if your injection target is a |
|
constructor or a multi-argument method.</para> |
|
</tip> |
|
|
|
<para>You can create your own custom qualifier annotations. Simply |
|
define an annotation and provide the |
|
<interfacename>@Qualifier</interfacename> annotation within your |
|
definition:</para> |
|
|
|
<note> |
|
<para>You can use JSR 330's <interfacename>@Qualifier |
|
</interfacename>annotation in the manner described below in place of |
|
Spring's <interfacename>@Qualifier</interfacename> annotation. This |
|
behavior is enabled automatically if you have the JSR 330 jar on the |
|
classpath.</para> |
|
</note> |
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER}) |
|
@Retention(RetentionPolicy.RUNTIME) |
|
<emphasis role="bold">@Qualifier</emphasis> |
|
public @interface Genre { |
|
|
|
String value(); |
|
}</programlisting> |
|
|
|
<para>Then you can provide the custom qualifier on autowired fields and |
|
parameters:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
<emphasis role="bold">@Genre("Action")</emphasis> |
|
private MovieCatalog actionCatalog; |
|
|
|
private MovieCatalog comedyCatalog; |
|
|
|
@Autowired |
|
public void setComedyCatalog(<emphasis role="bold">@Genre("Comedy")</emphasis> MovieCatalog comedyCatalog) { |
|
this.comedyCatalog = comedyCatalog; |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>Next, provide the information for the candidate bean definitions. |
|
You can add <literal><qualifier/></literal> tags as sub-elements |
|
of the <literal><bean/></literal> tag and then specify the |
|
<literal>type</literal> and <literal>value</literal> to match your |
|
custom qualifier annotations. The type is matched against the |
|
fully-qualified class name of the annotation. Or, as a convenience if no |
|
risk of conflicting names exists, you can use the short class name. Both |
|
approaches are demonstrated in the following example.</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:context="http://www.springframework.org/schema/context" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/context |
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
|
|
|
<context:annotation-config/> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<emphasis role="bold"><qualifier type="Genre" value="Action"/></emphasis> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<emphasis role="bold"><qualifier type="example.Genre" value="Comedy"/></emphasis> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean id="movieRecommender" class="example.MovieRecommender"/> |
|
|
|
</beans> |
|
</programlisting> |
|
|
|
<para>In <xref linkend="beans-classpath-scanning" />, you will see an |
|
annotation-based alternative to providing the qualifier metadata in XML. |
|
Specifically, see <xref linkend="beans-scanning-qualifiers" />.</para> |
|
|
|
<para>In some cases, it may be sufficient to use an annotation without a |
|
value. This may be useful when the annotation serves a more generic |
|
purpose and can be applied across several different types of |
|
dependencies. For example, you may provide an |
|
<emphasis>offline</emphasis> catalog that would be searched when no |
|
Internet connection is available. First define the simple |
|
annotation:</para> |
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER}) |
|
@Retention(RetentionPolicy.RUNTIME) |
|
@Qualifier |
|
public @interface Offline { |
|
|
|
}</programlisting> |
|
|
|
<para>Then add the annotation to the field or property to be |
|
autowired:</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
<emphasis role="bold">@Offline</emphasis> |
|
private MovieCatalog offlineCatalog; |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>Now the bean definition only needs a qualifier |
|
<literal>type</literal>:</para> |
|
|
|
<programlisting language="xml"><bean class="example.SimpleMovieCatalog"> |
|
<emphasis role="bold"><qualifier type="Offline"/></emphasis> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean></programlisting> |
|
|
|
<para>You can also define custom qualifier annotations that accept named |
|
attributes in addition to or instead of the simple |
|
<literal>value</literal> attribute. If multiple attribute values are |
|
then specified on a field or parameter to be autowired, a bean |
|
definition must match <emphasis>all</emphasis> such attribute values to |
|
be considered an autowire candidate. As an example, consider the |
|
following annotation definition:</para> |
|
|
|
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER}) |
|
@Retention(RetentionPolicy.RUNTIME) |
|
@Qualifier |
|
public @interface MovieQualifier { |
|
|
|
String genre(); |
|
|
|
Format format(); |
|
}</programlisting> |
|
|
|
<para>In this case <literal>Format</literal> is an enum:</para> |
|
|
|
<programlisting language="java">public enum Format { |
|
|
|
VHS, DVD, BLURAY |
|
}</programlisting> |
|
|
|
<para>The fields to be autowired are annotated with the custom qualifier |
|
and include values for both attributes: <literal>genre</literal> and |
|
<literal>format</literal>.</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Autowired |
|
@MovieQualifier(format=Format.VHS, genre="Action") |
|
private MovieCatalog actionVhsCatalog; |
|
|
|
@Autowired |
|
@MovieQualifier(format=Format.VHS, genre="Comedy") |
|
private MovieCatalog comedyVhsCatalog; |
|
|
|
@Autowired |
|
@MovieQualifier(format=Format.DVD, genre="Action") |
|
private MovieCatalog actionDvdCatalog; |
|
|
|
@Autowired |
|
@MovieQualifier(format=Format.BLURAY, genre="Comedy") |
|
private MovieCatalog comedyBluRayCatalog; |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<para>Finally, the bean definitions should contain matching qualifier |
|
values. This example also demonstrates that bean |
|
<emphasis>meta</emphasis> attributes may be used instead of the |
|
<literal><qualifier/></literal> sub-elements. If available, the |
|
<literal><qualifier/></literal> and its attributes take |
|
precedence, but the autowiring mechanism falls back on the values |
|
provided within the <literal><meta/></literal> tags if no such |
|
qualifier is present, as in the last two bean definitions in the |
|
following example.</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:context="http://www.springframework.org/schema/context" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/context |
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
|
|
|
<context:annotation-config/> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<qualifier type="MovieQualifier"> |
|
<attribute key="format" value="VHS"/> |
|
<attribute key="genre" value="Action"/> |
|
</qualifier> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<qualifier type="MovieQualifier"> |
|
<attribute key="format" value="VHS"/> |
|
<attribute key="genre" value="Comedy"/> |
|
</qualifier> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<meta key="format" value="DVD"/> |
|
<meta key="genre" value="Action"/> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
<bean class="example.SimpleMovieCatalog"> |
|
<meta key="format" value="BLURAY"/> |
|
<meta key="genre" value="Comedy"/> |
|
<lineannotation><!-- inject any dependencies required by this bean --></lineannotation> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
</section> |
|
|
|
<section id="beans-custom-autowire-configurer"> |
|
<title><classname>CustomAutowireConfigurer</classname></title> |
|
|
|
<para>The <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"><classname>CustomAutowireConfigurer</classname></ulink> |
|
is a <interfacename>BeanFactoryPostProcessor</interfacename> that |
|
enables you to register your own custom qualifier annotation types even |
|
if they are not annotated with Spring's |
|
<interfacename>@Qualifier</interfacename> annotation.</para> |
|
|
|
<programlisting language="xml"><bean id="customAutowireConfigurer" |
|
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"> |
|
<property name="customQualifierTypes"> |
|
<set> |
|
<value>example.CustomQualifier</value> |
|
</set> |
|
</property> |
|
</bean></programlisting> |
|
|
|
<para>The particular implementation of |
|
<interfacename>AutowireCandidateResolver</interfacename> that is |
|
activated for the application context depends on the Java version. In |
|
versions earlier than Java 5, the qualifier annotations are not |
|
supported, and therefore autowire candidates are solely determined by |
|
the <literal>autowire-candidate</literal> value of each bean definition |
|
as well as by any <literal>default-autowire-candidates</literal> |
|
pattern(s) available on the <literal><beans/></literal> element. |
|
In Java 5 or later, the presence of |
|
<interfacename>@Qualifier</interfacename> annotations and any custom |
|
annotations registered with the |
|
<classname>CustomAutowireConfigurer</classname> will also play a |
|
role.</para> |
|
|
|
<para>Regardless of the Java version, when multiple beans qualify as |
|
autowire candidates, the determination of a "primary" candidate is the |
|
same: if exactly one bean definition among the candidates has a |
|
<literal>primary</literal> attribute set to <literal>true</literal>, it |
|
will be selected.</para> |
|
</section> |
|
|
|
<section id="beans-resource-annotation"> |
|
<title><interfacename>@Resource</interfacename></title> |
|
|
|
<para>Spring also supports injection using the JSR-250 |
|
<interfacename>@Resource</interfacename> annotation on fields or bean |
|
property setter methods. This is a common pattern in Java EE 5 and Java |
|
6, for example, in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring |
|
supports this pattern for Spring-managed objects as well.</para> |
|
|
|
<para><interfacename>@Resource</interfacename> takes a name attribute, |
|
and by default Spring interprets that value as the bean name to be |
|
injected. In other words, it follows <emphasis>by-name</emphasis> |
|
semantics, as demonstrated in this example:</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
<emphasis role="bold">@Resource(name="myMovieFinder")</emphasis> |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
}</programlisting> |
|
|
|
<para>If no name is specified explicitly, the default name is derived |
|
from the field name or setter method. In case of a field, it takes the |
|
field name; in case of a setter method, it takes the bean property name. |
|
So the following example is going to have the bean with name |
|
"movieFinder" injected into its setter method:</para> |
|
|
|
<programlisting language="java">public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
<emphasis role="bold">@Resource</emphasis> |
|
public void setMovieFinder(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
}</programlisting> |
|
|
|
<note> |
|
<para>The name provided with the annotation is resolved as a bean name |
|
by the <interfacename>ApplicationContext</interfacename> of which the |
|
<classname>CommonAnnotationBeanPostProcessor</classname> is aware. The |
|
names can be resolved through JNDI if you configure Spring's <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"><classname>SimpleJndiBeanFactory</classname></ulink> |
|
explicitly. However, it is recommended that you rely on the default |
|
behavior and simply use Spring's JNDI lookup capabilities to preserve |
|
the level of indirection.</para> |
|
</note> |
|
|
|
<para>In the exclusive case of <interfacename>@Resource</interfacename> |
|
usage with no explicit name specified, and similar to |
|
<interfacename>@Autowired</interfacename>, |
|
<interfacename>@Resource</interfacename> finds a primary type match |
|
instead of a specific named bean and resolves well-known resolvable |
|
dependencies: the |
|
<interfacename>BeanFactory</interfacename><interfacename>, |
|
ApplicationContext,</interfacename><interfacename> ResourceLoader, |
|
ApplicationEventPublisher</interfacename>, and |
|
<interfacename>MessageSource</interfacename> interfaces.</para> |
|
|
|
<para>Thus in the following example, the |
|
<literal>customerPreferenceDao</literal> field first looks for a bean |
|
named customerPreferenceDao, then falls back to a primary type match for |
|
the type <classname>CustomerPreferenceDao</classname>. The "context" |
|
field is injected based on the known resolvable dependency type |
|
<interfacename>ApplicationContext</interfacename>.</para> |
|
|
|
<programlisting language="java">public class MovieRecommender { |
|
|
|
@Resource |
|
private CustomerPreferenceDao customerPreferenceDao; |
|
|
|
@Resource |
|
private ApplicationContext context; |
|
|
|
public MovieRecommender() { |
|
} |
|
|
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
</section> |
|
|
|
<section id="beans-postconstruct-and-predestroy-annotations"> |
|
<title><interfacename>@PostConstruct</interfacename> and |
|
<interfacename>@PreDestroy</interfacename></title> |
|
|
|
<para>The <classname>CommonAnnotationBeanPostProcessor</classname> not |
|
only recognizes the <interfacename>@Resource</interfacename> annotation |
|
but also the JSR-250 <emphasis>lifecycle</emphasis> annotations. |
|
Introduced in Spring 2.5, the support for these annotations offers yet |
|
another alternative to those described in <link |
|
linkend="beans-factory-lifecycle-initializingbean">initialization |
|
callbacks</link> and <link |
|
linkend="beans-factory-lifecycle-disposablebean">destruction |
|
callbacks</link>. Provided that the |
|
<classname>CommonAnnotationBeanPostProcessor</classname> is registered |
|
within the Spring <interfacename>ApplicationContext</interfacename>, a |
|
method carrying one of these annotations is invoked at the same point in |
|
the lifecycle as the corresponding Spring lifecycle interface method or |
|
explicitly declared callback method. In the example below, the cache |
|
will be pre-populated upon initialization and cleared upon |
|
destruction.</para> |
|
|
|
<programlisting language="java">public class CachingMovieLister { |
|
|
|
@PostConstruct |
|
public void populateMovieCache() { |
|
<lineannotation>// populates the movie cache upon initialization...</lineannotation> |
|
} |
|
|
|
@PreDestroy |
|
public void clearMovieCache() { |
|
<lineannotation>// clears the movie cache upon destruction...</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<note> |
|
<para>For details about the effects of combining various lifecycle |
|
mechanisms, see <xref |
|
linkend="beans-factory-lifecycle-combined-effects" />.</para> |
|
</note> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-classpath-scanning"> |
|
<title>Classpath scanning and managed components</title> |
|
|
|
<!-- MLP: Beverly to review paragraph --> |
|
|
|
<para>Most examples in this chapter use XML to specify the configuration |
|
metadata that produces each <interfacename>BeanDefinition</interfacename> |
|
within the Spring container. The previous section (<xref |
|
linkend="beans-annotation-config" />) demonstrates how to provide a lot of |
|
the configuration metadata through source-level annotations. Even in those |
|
examples, however, the "base" bean definitions are explicitly defined in |
|
the XML file, while the annotations only drive the dependency injection. |
|
This section describes an option for implicitly detecting the |
|
<emphasis>candidate components</emphasis> by scanning the classpath. |
|
Candidate components are classes that match against a filter criteria and |
|
have a corresponding bean definition registered with the container. This |
|
removes the need to use XML to perform bean registration, instead you can |
|
use annotations (for example @Component), AspectJ type expressions, or |
|
your own custom filter criteria to select which classes will have bean |
|
definitions registered with the container.</para> |
|
|
|
<note> |
|
<para>Starting with Spring 3.0, many features provided by the <ulink |
|
url="http://www.springsource.org/javaconfig">Spring JavaConfig |
|
project</ulink> are part of the core Spring Framework. This allows you |
|
to define beans using Java rather than using the traditional XML files. |
|
Take a look at the <interfacename>@Configuration</interfacename>, |
|
<interfacename>@Bean</interfacename>, |
|
<interfacename>@Import</interfacename>, and |
|
<interfacename>@DependsOn</interfacename> annotations for examples of |
|
how to use these new features.</para> |
|
</note> |
|
|
|
<section id="beans-stereotype-annotations"> |
|
<title><interfacename>@Component</interfacename> and further stereotype |
|
annotations</title> |
|
|
|
<para>In Spring 2.0 and later, the |
|
<interfacename>@Repository</interfacename> annotation is a marker for |
|
any class that fulfills the role or <emphasis>stereotype</emphasis> |
|
(also known as Data Access Object or DAO) of a repository. Among the |
|
uses of this marker is the automatic translation of exceptions as |
|
described in <xref linkend="orm-exception-translation" />.</para> |
|
|
|
<para>Spring 2.5 introduces further stereotype annotations: |
|
<interfacename>@Component</interfacename>, |
|
<interfacename>@Service</interfacename>, and |
|
<interfacename>@Controller</interfacename>. |
|
<interfacename>@Component</interfacename> is a generic stereotype for |
|
any Spring-managed component. |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, and |
|
<interfacename>@Controller</interfacename> are specializations of |
|
<interfacename>@Component</interfacename> for more specific use cases, |
|
for example, in the persistence, service, and presentation layers, |
|
respectively. Therefore, you can annotate your component classes with |
|
<interfacename>@Component</interfacename>, but by annotating them with |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, or |
|
<interfacename>@Controller</interfacename> instead, your classes are |
|
more properly suited for processing by tools or associating with |
|
aspects. For example, these stereotype annotations make ideal targets |
|
for pointcuts. It is also possible that |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, and |
|
<interfacename>@Controller</interfacename> may carry additional |
|
semantics in future releases of the Spring Framework. Thus, if you are |
|
choosing between using <interfacename>@Component</interfacename> or |
|
<interfacename>@Service</interfacename> for your service layer, |
|
<interfacename>@Service</interfacename> is clearly the better choice. |
|
Similarly, as stated above, <interfacename>@Repository</interfacename> |
|
is already supported as a marker for automatic exception translation in |
|
your persistence layer.</para> |
|
</section> |
|
|
|
<section id="beans-scanning-autodetection"> |
|
<title>Automatically detecting classes and registering bean |
|
definitions</title> |
|
|
|
<para>Spring can automatically detect stereotyped classes and register |
|
corresponding <interfacename>BeanDefinition</interfacename>s with the |
|
<interfacename>ApplicationContext</interfacename>. For example, the |
|
following two classes are eligible for such autodetection:</para> |
|
|
|
<programlisting language="java">@Service |
|
public class SimpleMovieLister { |
|
|
|
private MovieFinder movieFinder; |
|
|
|
@Autowired |
|
public SimpleMovieLister(MovieFinder movieFinder) { |
|
this.movieFinder = movieFinder; |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="java">@Repository |
|
public class JpaMovieFinder implements MovieFinder { |
|
<lineannotation>// implementation elided for clarity</lineannotation> |
|
}</programlisting> |
|
|
|
<para>To autodetect these classes and register the corresponding beans, |
|
you need to include the following element in XML, where the base-package |
|
element is a common parent package for the two classes. (Alternatively, |
|
you can specify a comma-separated list that includes the parent package |
|
of each class.)</para> |
|
|
|
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?> |
|
<beans xmlns="http://www.springframework.org/schema/beans" |
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
xmlns:context="http://www.springframework.org/schema/context" |
|
xsi:schemaLocation="http://www.springframework.org/schema/beans |
|
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd |
|
http://www.springframework.org/schema/context |
|
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> |
|
|
|
<context:component-scan base-package="org.example"/> |
|
|
|
</beans></programlisting> |
|
|
|
<note> |
|
<para>The scanning of classpath packages requires the presence of |
|
corresponding directory entries in the classpath. When you build JARs |
|
with Ant, make sure that you do <emphasis>not</emphasis> activate the |
|
files-only switch of the JAR task.</para> |
|
</note> |
|
|
|
<para>Furthermore, the |
|
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and |
|
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> are |
|
both included implicitly when you use the component-scan element. That |
|
means that the two components are autodetected <emphasis>and</emphasis> |
|
wired together - all without any bean configuration metadata provided in |
|
XML.</para> |
|
|
|
<note> |
|
<para>You can disable the registration of |
|
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> |
|
and <interfacename>CommonAnnotationBeanPostProcessor</interfacename> |
|
by including the <emphasis>annotation-config</emphasis> attribute with |
|
a value of false.</para> |
|
</note> |
|
<!-- |
|
<note> |
|
<para>In Spring 3.0 RC1 you can use JSR 330's |
|
<interfacename>@Named</interfacename> annotation in place of |
|
stereotpye annotations and they will be automatically detected during |
|
component-scanning. The value of the |
|
<interfacename>@Named</interfacename> property will be used as the |
|
Bean Name. At this time Spring defaults for bean scope will be applied |
|
when using @Named. This behavior as well as mapping of JSR 330 and JSR |
|
299 scopes is planned for Spring 3.0 GA assuming the JSRs are stable |
|
at that time.</para> |
|
</note> |
|
--> |
|
</section> |
|
|
|
<section id="beans-scanning-filters"> |
|
<title>Using filters to customize scanning</title> |
|
|
|
<para>By default, classes annotated with |
|
<interfacename>@Component</interfacename>, |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, |
|
<interfacename>@Controller</interfacename>, or a custom annotation that |
|
itself is annotated with <interfacename>@Component</interfacename> are |
|
the only detected candidate components. However, you can modify and |
|
extend this behavior simply by applying custom filters. Add them as |
|
<emphasis>include-filter</emphasis> or |
|
<emphasis>exclude-filter</emphasis> sub-elements of the |
|
<literal>component-scan</literal> element. Each filter element requires |
|
the <literal>type</literal> and <literal>expression</literal> |
|
attributes. The following table describes the filtering options.</para> |
|
|
|
<table id="beans-scanning-filters-tbl"> |
|
<title>Filter Types</title> |
|
|
|
<tgroup cols="3"> |
|
<colspec colname="c1" colwidth="1*" /> |
|
|
|
<colspec colname="c2" colwidth="3*" /> |
|
|
|
<colspec colname="c" colwidth="4*" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Filter Type</entry> |
|
|
|
<entry>Example Expression</entry> |
|
|
|
<entry>Description</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry>annotation</entry> |
|
|
|
<entry><literal>org.example.SomeAnnotation</literal></entry> |
|
|
|
<entry>An annotation to be present at the type level in target |
|
components.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry>assignable</entry> |
|
|
|
<entry><literal>org.example.SomeClass</literal></entry> |
|
|
|
<entry>A class (or interface) that the target components are |
|
assignable to (extend/implement).</entry> |
|
</row> |
|
|
|
<row> |
|
<entry>aspectj</entry> |
|
|
|
<entry><literal>org.example..*Service+</literal></entry> |
|
|
|
<entry>An AspectJ type expression to be matched by the target |
|
components.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry>regex</entry> |
|
|
|
<entry><literal>org\.example\.Default.*</literal></entry> |
|
|
|
<entry>A regex expression to be matched by the target components |
|
class names.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry>custom</entry> |
|
|
|
<entry><literal>org.example.MyTypeFilter</literal></entry> |
|
|
|
<entry>A custom implementation of the |
|
<interfacename>org.springframework.core.type |
|
.TypeFilter</interfacename> interface.</entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>The following example shows the XML configuration ignoring all |
|
<interfacename>@Repository</interfacename> annotations and using "stub" |
|
repositories instead.</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<context:component-scan base-package="org.example"> |
|
<context:include-filter type="regex" expression=".*Stub.*Repository"/> |
|
<context:exclude-filter type="annotation" |
|
expression="org.springframework.stereotype.Repository"/> |
|
</context:component-scan> |
|
|
|
</beans></programlisting> |
|
|
|
<note> |
|
<para>You can also disable the default filters by providing |
|
<emphasis>use-default-filters="false"</emphasis> as an attribute of |
|
the <component-scan/> element. This will in effect disable |
|
automatic detection of classes annotated with |
|
<interfacename>@Component</interfacename>, |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, or |
|
<interfacename>@Controller</interfacename>.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-factorybeans-annotations"> |
|
<title>Defining bean metadata within components</title> |
|
|
|
<para>Spring components can also contribute bean definition metadata to |
|
the container. You do this with the same <literal>@Bean</literal> |
|
annotation used to define bean metadata within |
|
<literal>@Configuration</literal> annotated classes. Here is a simple |
|
example:</para> |
|
|
|
<programlisting language="java">@Component |
|
public class FactoryMethodComponent { |
|
|
|
@Bean @Qualifier("public") |
|
public TestBean publicInstance() { |
|
return new TestBean("publicInstance"); |
|
} |
|
|
|
public void doWork() { |
|
// Component method implementation omitted |
|
} |
|
}</programlisting> |
|
|
|
<para>This class is a Spring component that has application-specific |
|
code contained in its <methodname>doWork</methodname> method. However, |
|
it also contributes a bean definition that has a factory method |
|
referring to the method <methodname>publicInstance</methodname>. The |
|
<literal>@Bean</literal> annotation identifies the factory method and |
|
other bean definition properties, such as a qualifier value through the |
|
<classname>@Qualifier</classname> annotation. Other method level |
|
annotations that can be specified are <literal>@Scope</literal>, |
|
<literal>@Lazy</literal>, and custom qualifier annotations. Autowired |
|
fields and methods are supported as previously discussed, with |
|
additional support for autowiring of <literal>@Bean</literal> |
|
methods:</para> |
|
|
|
<programlisting language="java">@Component |
|
public class FactoryMethodComponent { |
|
|
|
private static int i; |
|
|
|
@Bean @Qualifier("public") |
|
public TestBean publicInstance() { |
|
return new TestBean("publicInstance"); |
|
} |
|
|
|
// use of a custom qualifier and autowiring of method parameters |
|
|
|
@Bean @BeanAge(1) |
|
protected TestBean protectedInstance(@Qualifier("public") TestBean spouse, |
|
@Value("#{privateInstance.age}") String country) { |
|
TestBean tb = new TestBean("protectedInstance", 1); |
|
tb.setSpouse(tb); |
|
tb.setCountry(country); |
|
return tb; |
|
} |
|
|
|
@Bean @Scope(BeanDefinition.SCOPE_SINGLETON) |
|
private TestBean privateInstance() { |
|
return new TestBean("privateInstance", i++); |
|
} |
|
|
|
@Bean @Scope(value = WebApplicationContext.SCOPE_SESSION, |
|
proxyMode = ScopedProxyMode.TARGET_CLASS) |
|
public TestBean requestScopedInstance() { |
|
return new TestBean("requestScopedInstance", 3); |
|
} |
|
} |
|
</programlisting> |
|
|
|
<para>The example autowires the <classname>String</classname> method |
|
parameter <literal>country</literal> to the value of the |
|
<literal>Age</literal> property on another bean named |
|
<literal>privateInstance</literal>. A Spring Expression Language element |
|
defines the value of the property through the notation <literal>#{ |
|
<expression> }</literal>. For <literal>@Value</literal> |
|
annotations, an expression resolver is preconfigured to look for bean |
|
names when resolving expression text.</para> |
|
|
|
<para>The <literal>@Bean</literal> methods in a Spring component are |
|
processed differently than their counterparts inside a Spring |
|
<literal>@Configuration</literal> class. The difference is that |
|
<literal>@Component</literal> classes are not enhanced with CGLIB to |
|
intercept the invocation of methods and fields. CGLIB proxying is the |
|
means by which invoking methods or fields within |
|
<literal>@Configuration</literal> classes <literal>@Bean</literal> |
|
methods create bean metadata references to collaborating objects. |
|
Methods are <emphasis>not</emphasis> invoked with normal Java semantics. |
|
In contrast, calling a method or field within a |
|
<literal>@Component</literal> classes <literal>@Bean</literal> method |
|
<emphasis>has</emphasis> standard Java semantics.</para> |
|
</section> |
|
|
|
<section id="beans-scanning-name-generator"> |
|
<title>Naming autodetected components</title> |
|
|
|
<para>When a component is autodetected as part of the scanning process, |
|
its bean name is generated by the |
|
<interfacename>BeanNameGenerator</interfacename> strategy known to that |
|
scanner. By default, any Spring stereotype annotation |
|
(<interfacename>@Component</interfacename>, |
|
<interfacename>@Repository</interfacename>, |
|
<interfacename>@Service</interfacename>, and |
|
<interfacename>@Controller</interfacename>) that contains a |
|
<literal>name</literal> value will thereby provide that name to the |
|
corresponding bean definition.</para> |
|
|
|
<note> |
|
<para>JSR 330's @Named annotation can be used as a means to both |
|
detect components and to provide them with a name. This behavior is |
|
enabled automatically if you have the JSR 330 JAR on the |
|
classpath.</para> |
|
</note> |
|
|
|
<para>If such an annotation contains no <literal>name</literal> value or |
|
for any other detected component (such as those discovered by custom |
|
filters), the default bean name generator returns the uncapitalized |
|
non-qualified class name. For example, if the following two components |
|
were detected, the names would be myMovieLister and |
|
movieFinderImpl:</para> |
|
|
|
<programlisting language="java">@Service("myMovieLister") |
|
public class SimpleMovieLister { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<programlisting language="java">@Repository |
|
public class MovieFinderImpl implements MovieFinder { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<note> |
|
<para>If you do not want to rely on the default bean-naming strategy, |
|
you can provide a custom bean-naming strategy. First, implement the |
|
<ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/support/BeanNameGenerator.html"><interfacename>BeanNameGenerator</interfacename></ulink> |
|
interface, and be sure to include a default no-arg constructor. Then, |
|
provide the fully-qualified class name when configuring the |
|
scanner:</para> |
|
</note> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<context:component-scan base-package="org.example" |
|
name-generator="org.example.MyNameGenerator" /> |
|
|
|
</beans></programlisting> |
|
|
|
<para>As a general rule, consider specifying the name with the |
|
annotation whenever other components may be making explicit references |
|
to it. On the other hand, the auto-generated names are adequate whenever |
|
the container is responsible for wiring.</para> |
|
</section> |
|
|
|
<section id="beans-scanning-scope-resolver"> |
|
<title>Providing a scope for autodetected components</title> |
|
|
|
<para>As with Spring-managed components in general, the default and most |
|
common scope for autodetected components is singleton. However, |
|
sometimes you need other scopes, which Spring 2.5 provides with a new |
|
<interfacename>@Scope</interfacename> annotation. Simply provide the |
|
name of the scope within the annotation:</para> |
|
|
|
<programlisting language="java">@Scope(StandardScopes.PROTOTYPE) |
|
@Repository |
|
public class MovieFinderImpl implements MovieFinder { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<note> |
|
<para>To provide a custom strategy for scope resolution rather than |
|
relying on the annotation-based approach, implement the <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html"><interfacename>ScopeMetadataResolver</interfacename></ulink> |
|
interface, and be sure to include a default no-arg constructor. Then, |
|
provide the fully-qualified class name when configuring the |
|
scanner:</para> |
|
</note> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<context:component-scan base-package="org.example" |
|
scope-resolver="org.example.MyScopeResolver" /> |
|
|
|
</beans></programlisting> |
|
|
|
<para>When using certain non-singleton scopes, it may be necessary to |
|
generate proxies for the scoped objects. The reasoning is described in |
|
<xref linkend="beans-factory-scopes-other-injection" />. For this |
|
purpose, a <emphasis>scoped-proxy</emphasis> attribute is available on |
|
the component-scan element. The three possible values are: no, |
|
interfaces, and targetClass. For example, the following configuration |
|
will result in standard JDK dynamic proxies:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<context:component-scan base-package="org.example" |
|
scoped-proxy="interfaces" /> |
|
|
|
</beans></programlisting> |
|
</section> |
|
|
|
<section id="beans-scanning-qualifiers"> |
|
<title>Providing qualifier metadata with annotations</title> |
|
|
|
<para>The <interfacename>@Qualifier</interfacename> annotation is |
|
discussed in <xref linkend="beans-autowired-annotation-qualifiers" />. |
|
The examples in that section demonstrate the use of the |
|
<interfacename>@Qualifier</interfacename> annotation and custom |
|
qualifier annotations to provide fine-grained control when you resolve |
|
autowire candidates. Because those examples were based on XML bean |
|
definitions, the qualifier metadata was provided on the candidate bean |
|
definitions using the <literal>qualifier</literal> or |
|
<literal>meta</literal> sub-elements of the <literal>bean</literal> |
|
element in the XML. When relying upon classpath scanning for |
|
autodetection of components, you provide the qualifier metadata with |
|
type-level annotations on the candidate class. The following three |
|
examples demonstrate this technique:</para> |
|
|
|
<programlisting language="java">@Component |
|
<emphasis role="bold">@Qualifier("Action")</emphasis> |
|
public class ActionMovieCatalog implements MovieCatalog { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<programlisting language="java">@Component |
|
<emphasis role="bold">@Genre("Action")</emphasis> |
|
public class ActionMovieCatalog implements MovieCatalog { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<programlisting language="java">@Component |
|
<emphasis role="bold">@Offline</emphasis> |
|
public class CachingMovieCatalog implements MovieCatalog { |
|
<lineannotation>// ...</lineannotation> |
|
}</programlisting> |
|
|
|
<note> |
|
<para>As with most annotation-based alternatives, keep in mind that |
|
the annotation metadata is bound to the class definition itself, while |
|
the use of XML allows for multiple beans <emphasis>of the same |
|
type</emphasis> to provide variations in their qualifier metadata, |
|
because that metadata is provided per-instance rather than |
|
per-class.</para> |
|
</note> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java"> |
|
<title>Java-based container configuration</title> |
|
|
|
<section id="beans-java-basic-concepts"> |
|
<title>Basic concepts: <literal>@Configuration</literal> and <literal>@Bean</literal></title> |
|
|
|
<para>The central artifact in Spring's new Java-configuration support is |
|
the <interfacename>@Configuration</interfacename>-annotated class. These |
|
classes consist principally of |
|
<interfacename>@Bean</interfacename>-annotated methods that define |
|
instantiation, configuration, and initialization logic for objects to |
|
be managed by the Spring IoC container.</para> |
|
|
|
<para>Annotating a class with the |
|
<interfacename>@Configuration</interfacename> indicates that the class |
|
can be used by the Spring IoC container as a source of bean definitions. |
|
The simplest possible <interfacename>@Configuration</interfacename> |
|
class would read as follows: <programlisting language="java">@Configuration |
|
public class AppConfig { |
|
@Bean |
|
public MyService myService() { |
|
return new MyServiceImpl(); |
|
} |
|
}</programlisting></para> |
|
|
|
<para>For those more familiar with Spring <literal><beans/></literal> |
|
XML, the <literal>AppConfig</literal> class above would be equivalent to: |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="myService" class="com.acme.services.MyServiceImpl"/> |
|
</beans></programlisting> |
|
|
|
As you can see, the <literal>@Bean</literal> annotation plays the same role |
|
as the <literal><bean/></literal> element. The <literal>@Bean</literal> |
|
annotation will be discussed in depth in the sections below. First, however, |
|
we'll cover the various ways of creating a spring container using Java-based |
|
configuration.</para> |
|
</section> |
|
|
|
<section id="beans-java-instantiating-container"> |
|
<title>Instantiating the Spring container using |
|
<literal>AnnotationConfigApplicationContext</literal></title> |
|
|
|
<para>The sections below document Spring's |
|
<literal>AnnotationConfigApplicationContext</literal>, new in Spring 3.0. |
|
This versatile <literal>ApplicationContext</literal> implementation is |
|
capable of accepting not only <literal>@Configuration</literal> classes |
|
as input, but also plain <literal>@Component</literal> classes and classes |
|
annotated with JSR-330 metadata.</para> |
|
|
|
<para>When <literal>@Configuration</literal> classes are provided as input, |
|
the <literal>@Configuration</literal> class itself is registered as a bean |
|
definition, and all declared <literal>@Bean</literal> methods within the |
|
class are also registered as bean definitions.</para> |
|
|
|
<para>When <literal>@Component</literal> and JSR-330 classes are provided, |
|
they are registered as bean definitions, and it is assumed that DI metadata |
|
such as <literal>@Autowired</literal> or <literal>@Inject</literal> are used |
|
within those classes where necessary.</para> |
|
|
|
<section id="beans-java-instantiating-container-contstructor"> |
|
<title>Simple construction</title> |
|
<para>In much the same way that Spring XML files are used as input when |
|
instantiating a <literal>ClassPathXmlApplicationContext</literal>, |
|
<literal>@Configuration</literal> classes may be used as input when |
|
instantiating an <literal>AnnotationConfigApplicationContext</literal>. |
|
This allows for completely XML-free usage of the Spring container: |
|
<programlisting language="java">public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); |
|
MyService myService = ctx.getBean(MyService.class); |
|
myService.doStuff(); |
|
}</programlisting> |
|
|
|
As mentioned above, <literal>AnnotationConfigApplicationContext</literal> |
|
is not limited to working only with <literal>@Configuration</literal> |
|
classes. Any <literal>@Component</literal> or JSR-330 annotated class may |
|
be supplied as input to the constructor. For example: |
|
<programlisting language="java">public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class); |
|
MyService myService = ctx.getBean(MyService.class); |
|
myService.doStuff(); |
|
}</programlisting> |
|
|
|
The above assumes that <literal>MyServiceImpl</literal>, <literal>Dependency1</literal> and <literal>Dependency2</literal> use Spring dependency injection annotations such as <literal>@Autowired</literal>.</para> |
|
</section> |
|
|
|
<section id="beans-java-instantiating-container-register"> |
|
<title>Building the container programmatically using <literal>register(Class<?>...)</literal></title> |
|
<para>An <literal>AnnotationConfigApplicationContext</literal> may be |
|
instantiated using a no-arg constructor and then configured using the |
|
<literal>register()</literal> method. This approach is particularly |
|
useful when programmatically building an |
|
<literal>AnnotationConfigApplicationContext</literal>. |
|
<programlisting language="java">public static void main(String[] args) { |
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
|
ctx.register(AppConfig.class, OtherConfig.class); |
|
ctx.register(AdditionalConfig.class); |
|
ctx.refresh(); |
|
MyService myService = ctx.getBean(MyService.class); |
|
myService.doStuff(); |
|
}</programlisting></para> |
|
</section> |
|
|
|
<section id="beans-java-instantiating-container-scan"> |
|
<title>Enabling component scanning with <literal>scan(String...)</literal></title> |
|
<para>Experienced Spring users will be familiar with the following |
|
commonly-used XML declaration from Spring's <literal>context:</literal> namespace |
|
<programlisting language="xml"><beans> |
|
<context:component-scan base-package="com.acme"/> |
|
</beans></programlisting> |
|
|
|
In the example above, the <literal>com.acme</literal> package will |
|
be scanned, looking for any <literal>@Component</literal>-annotated |
|
classes, and those classes will be registered as Spring bean |
|
definitions within the container. |
|
|
|
<literal>AnnotationConfigApplicationContext</literal> exposes the |
|
<literal>scan(String...)</literal> method to allow for the same |
|
component-scanning functionality:<programlisting language="java">public static void main(String[] args) { |
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); |
|
ctx.scan("com.acme"); |
|
ctx.refresh(); |
|
MyService myService = ctx.getBean(MyService.class); |
|
}</programlisting></para> |
|
<note> |
|
<para>Remember that <literal>@Configuration</literal> classes are |
|
meta-annotated with <literal>@Component</literal>, so they are |
|
candidates for component-scanning! In the example above, assuming |
|
that <literal>AppConfig</literal> is declared within the |
|
<literal>com.acme</literal> package (or any package underneath), |
|
it will be picked up during the call to <literal>scan()</literal>, |
|
and upon <literal>refresh()</literal> all its <literal>@Bean</literal> |
|
methods will be processed and registered as bean definitions within |
|
the container.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-java-instantiating-container-web"> |
|
<title>Support for web applications with <literal>AnnotationConfigWebApplicationContext</literal></title> |
|
<para>A <literal>WebApplicationContext</literal> variant of <literal>AnnotationConfigApplicationContext</literal> is available with <literal>AnnotationConfigWebApplicationContext</literal>. This implementation may be used when configuring the Spring <literal>ContextLoaderListener</literal> servlet listener, Spring MVC <literal>DispatcherServlet</literal>, etc. What follows is a <literal>web.xml</literal> snippet that configures a typical Spring MVC web application. Note the use of the <literal>contextClass</literal> context-param and init-param: |
|
<programlisting language="xml"><![CDATA[ |
|
<web-app> |
|
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext |
|
instead of the default XmlWebApplicationContext --> |
|
<context-param> |
|
<param-name>contextClass</param-name> |
|
<param-value> |
|
org.springframework.web.context.support.AnnotationConfigWebApplicationContext |
|
</param-value> |
|
</context-param> |
|
|
|
<!-- Configuration locations must consist of one or more comma- or space-delimited |
|
fully-qualified @Configuration classes. Fully-qualified packages may also be |
|
specified for component-scanning --> |
|
<context-param> |
|
<param-name>contextConfigLocation</param-name> |
|
<param-value>com.acme.AppConfig</param-value> |
|
</context-param> |
|
|
|
<!-- Bootstrap the root application context as usual using ContextLoaderListener --> |
|
<listener> |
|
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> |
|
</listener> |
|
|
|
<!-- Declare a Spring MVC DispatcherServlet as usual --> |
|
<servlet> |
|
<servlet-name>dispatcher</servlet-name> |
|
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
|
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext |
|
instead of the default XmlWebApplicationContext --> |
|
<init-param> |
|
<param-name>contextClass</param-name> |
|
<param-value> |
|
org.springframework.web.context.support.AnnotationConfigWebApplicationContext |
|
</param-value> |
|
</init-param> |
|
<!-- Again, config locations must consist of one or more comma- or space-delimited |
|
and fully-qualified @Configuration classes --> |
|
<init-param> |
|
<param-name>contextConfigLocation</param-name> |
|
<param-value>com.acme.web.MvcConfig</param-value> |
|
</init-param> |
|
</servlet> |
|
|
|
<!-- map all requests for /main/* to the dispatcher servlet --> |
|
<servlet-mapping> |
|
<servlet-name>dispatcher</servlet-name> |
|
<url-pattern>/main/*</url-pattern> |
|
</servlet-mapping> |
|
</web-app>]]></programlisting></para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java-composing-configuration-classes"> |
|
<title>Composing Java-based configurations</title> |
|
<section id="beans-java-using-import"> |
|
<title>Using the <literal>@Import</literal> annotation</title> |
|
<para>Much as the <literal><import/></literal> element is used within |
|
Spring XML files to aid in modularizing configurations, the |
|
<literal>@Import</literal> annotation allows for loading <literal>@Bean</literal> |
|
definitions from another configuration class:<programlisting language="java">@Configuration |
|
public class ConfigA { |
|
public @Bean A a() { return new A(); } |
|
} |
|
|
|
@Configuration |
|
@Import(ConfigA.class) |
|
public class ConfigB { |
|
public @Bean B b() { return new B(); } |
|
}</programlisting> |
|
|
|
Now, rather than needing to specify both <literal>ConfigA.class</literal> and |
|
<literal>ConfigB.class</literal> when instantiating the context, only |
|
<literal>ConfigB</literal> needs to be supplied explicitly:<programlisting language="java">public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class); |
|
|
|
// now both beans A and B will be available... |
|
A a = ctx.getBean(A.class); |
|
B b = ctx.getBean(B.class); |
|
}</programlisting> |
|
|
|
This approach simplifies container instantiation, as only one class needs to be dealt |
|
with, rather than requiring the developer to remember a potentially large number of |
|
<literal>@Configuration</literal> classes during construction. |
|
</para> |
|
|
|
<section id="beans-java-injecting-imported-beans"> |
|
<title>Injecting dependencies on imported <literal>@Bean</literal> definitions</title> |
|
<para>The example above works, but is simplistic. In most practical scenarios, beans |
|
will have dependencies on one another across configuration classes. When using XML, |
|
this is not an issue, per se, because there is no compiler involved, and one can |
|
simply declare <literal>ref="someBean"</literal> and trust that Spring will work |
|
it out during container initialization. Of course, when using |
|
<literal>@Configuration</literal> classes, the Java compiler places constraints on |
|
the configuration model, in that references to other beans must be valid Java syntax.</para> |
|
|
|
<para>Fortunately, solving this problem is simple. Remember that |
|
<literal>@Configuration</literal> classes are ultimately just another bean in the container |
|
- this means that they can take advantage of <literal>@Autowired</literal> injection |
|
metadata just like any other bean!</para> |
|
|
|
<para>Let's consider a more real-world scenario with several <literal>@Configuration</literal> |
|
classes, each depending on beans declared in the others:<programlisting language="java">@Configuration |
|
public class ServiceConfig { |
|
private @Autowired AccountRepository accountRepository; |
|
|
|
public @Bean TransferService transferService() { |
|
return new TransferServiceImpl(accountRepository); |
|
} |
|
} |
|
|
|
@Configuration |
|
public class RepositoryConfig { |
|
private @Autowired DataSource dataSource; |
|
|
|
public @Bean AccountRepository accountRepository() { |
|
return new JdbcAccountRepository(dataSource); |
|
} |
|
} |
|
|
|
@Configuration |
|
@Import({ServiceConfig.class, RepositoryConfig.class}) |
|
public class SystemTestConfig { |
|
public @Bean DataSource dataSource() { /* return new DataSource */ } |
|
} |
|
|
|
public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); |
|
// everything wires up across configuration classes... |
|
TransferService transferService = ctx.getBean(TransferService.class); |
|
transferService.transfer(100.00, "A123", "C456"); |
|
}</programlisting></para> |
|
|
|
<section id="beans-java-injecting-imported-beans-fq"> |
|
<title>Fully-qualifying imported beans for ease of navigation</title> |
|
<para>In the scenario above, using <literal>@Autowired</literal> works |
|
well and provides the desired modularity, but determining exactly where |
|
the autowired bean definitions are declared is still somewhat ambiguous. |
|
For example, as a developer looking at <literal>ServiceConfig</literal>, |
|
how do you know exactly where the <literal>@Autowired AccountRepository</literal> |
|
bean is declared? It's not explicit in the code, and this may be just fine. |
|
Remember that the <ulink url="http://www.springsource.com/products/sts">SpringSource |
|
Tool Suite</ulink> provides tooling that can render graphs showing how everything |
|
is wired up - that may be all you need. Also, your Java IDE can easily find all |
|
declarations and uses of the <literal>AccountRepository</literal> type, and will |
|
quickly show you the location of <literal>@Bean</literal> methods that return that |
|
type.</para> |
|
|
|
<para>In cases where this ambiguity is not acceptable and you wish to have |
|
direct navigation from within your IDE from one <literal>@Configuration</literal> |
|
class to another, consider autowiring the configuration classes themselves: |
|
<programlisting language="java">@Configuration |
|
public class ServiceConfig { |
|
private @Autowired RepositoryConfig repositoryConfig; |
|
|
|
public @Bean TransferService transferService() { |
|
// navigate 'through' the config class to the @Bean method! |
|
return new TransferServiceImpl(repositoryConfig.accountRepository()); |
|
} |
|
}</programlisting> |
|
|
|
In the situation above, it is completely explicit where |
|
<literal>AccountRepository</literal> is defined. However, |
|
<literal>ServiceConfig</literal> is now tightly coupled to |
|
<literal>RepositoryConfig</literal>; that's the tradeoff. This tight |
|
coupling can be somewhat mitigated by using interface-based or abstract |
|
class-based <literal>@Configuration</literal> classes. Consider the following: |
|
<programlisting language="java">@Configuration |
|
public class ServiceConfig { |
|
private @Autowired RepositoryConfig repositoryConfig; |
|
|
|
public @Bean TransferService transferService() { |
|
return new TransferServiceImpl(repositoryConfig.accountRepository()); |
|
} |
|
} |
|
|
|
@Configuration |
|
public interface RepositoryConfig { |
|
@Bean AccountRepository accountRepository(); |
|
} |
|
|
|
@Configuration |
|
public class DefaultRepositoryConfig implements RepositoryConfig { |
|
public @Bean AccountRepository accountRepository() { |
|
return new JdbcAccountRepository(...); |
|
} |
|
} |
|
|
|
@Configuration |
|
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config! |
|
public class SystemTestConfig { |
|
public @Bean DataSource dataSource() { /* return DataSource */ } |
|
} |
|
|
|
public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class); |
|
TransferService transferService = ctx.getBean(TransferService.class); |
|
transferService.transfer(100.00, "A123", "C456"); |
|
}</programlisting> |
|
|
|
Now <literal>ServiceConfig</literal> is loosely coupled with respect |
|
to the concrete <literal>DefaultRepositoryConfig</literal>, and built-in IDE |
|
tooling is still useful: it will be easy for the developer to get a type hierarchy |
|
of <literal>RepositoryConfig</literal> implementations. In this way, navigating |
|
<literal>@Configuration</literal> classes and their dependencies becomes no |
|
different than the usual process of navigating interface-based code.</para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java-combining"> |
|
<title>Combining Java and XML configuration</title> |
|
<para>Spring's <literal>@Configuration</literal> class support does not aim to be a 100% |
|
complete replacement for Spring XML. Some facilities such as Spring XML namespaces remain |
|
an ideal way to configure the container. In cases where XML is convenient or necessary, |
|
you have a choice: either instantiate the container in an "XML-centric" way using, for |
|
example, <literal>ClassPathXmlApplicationContext</literal>, or in a "Java-centric" fashion |
|
using <literal>AnnotationConfigApplicationContext</literal> and the |
|
<literal>@ImportResource</literal> annotation to import XML as needed.</para> |
|
|
|
<section id="beans-java-combining-xml-centric"> |
|
<title>XML-centric use of <literal>@Configuration</literal> classes</title> |
|
<para>It may be preferable to bootstrap the Spring container from XML and |
|
include <literal>@Configuration</literal> classes in an ad-hoc fashion. |
|
For example, in a large existing codebase that uses Spring XML, it will be |
|
easier to create <literal>@Configuration</literal> classes on an as-needed |
|
basis and include them from the existing XML files. Below you'll find the |
|
options for using <literal>@Configuration</literal> classes in this kind |
|
of "XML-centric" situation.</para> |
|
|
|
<section id="beans-java-combining-xml-centric-declare-as-bean"> |
|
<title>Declaring <literal>@Configuration</literal> classes as plain Spring |
|
<literal><bean/></literal> elements</title> |
|
<para>Remember that <literal>@Configuration</literal> classes are ultimately |
|
just bean definitions in the container. In this example, we create a |
|
<literal>@Configuration</literal> class named <literal>AppConfig</literal> |
|
and include it within <literal>system-test-config.xml</literal> as a |
|
<literal><bean/></literal>definition. Because |
|
<literal><context:annotation-config/></literal> is switched on, the |
|
container will recognize the <literal>@Configuration</literal> annotation, |
|
and process the <literal>@Bean</literal> methods declared in |
|
<literal>AppConfig</literal> properly.<programlisting language="java">@Configuration |
|
public class AppConfig { |
|
private @Autowired DataSource dataSource; |
|
|
|
public @Bean AccountRepository accountRepository() { |
|
return new JdbcAccountRepository(dataSource); |
|
} |
|
|
|
public @Bean TransferService transferService() { |
|
return new TransferService(accountRepository()); |
|
} |
|
}</programlisting> |
|
<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation> |
|
<beans> |
|
<!-- enable processing of annotations such as @Autowired and @Configuration --> |
|
<context:annotation-config/> |
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> |
|
|
|
<bean class="com.acme.AppConfig"/> |
|
|
|
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> |
|
<property name="url" value="${jdbc.url}"/> |
|
<property name="username" value="${jdbc.username}"/> |
|
<property name="password" value="${jdbc.password}"/> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation> |
|
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb |
|
jdbc.username=sa |
|
jdbc.password=</programlisting> |
|
|
|
<programlisting language="java">public static void main(String[] args) { |
|
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); |
|
TransferService transferService = ctx.getBean(TransferService.class); |
|
// ... |
|
}</programlisting></para> |
|
|
|
<note> |
|
<para>In <literal>system-test-config.xml</literal> above, the |
|
<literal>AppConfig<bean/></literal> does not declare an |
|
<literal>id</literal> element. While it would be acceptable to do |
|
so, it is unnecessary given that no other bean will ever refer to it, |
|
and it is unlikely that it will be explicitly fetched from the container |
|
by name. Likewise with the <literal>DataSource</literal> bean - it is |
|
only ever autowired by type, so an explicit bean id is not strictly |
|
required.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="beans-java-combining-xml-centric-component-scan"> |
|
<title>Using <literal><context:component-scan/></literal> to pick up |
|
<literal>@Configuration</literal> classes</title> |
|
<para>Because <literal>@Configuration</literal> is meta-annotated with |
|
<literal>@Component</literal>, <literal>@Configuration</literal>-annotated |
|
classes are automatically candidates for component scanning. Using the same |
|
scenario as above, we can redefine <literal>system-test-config.xml</literal> |
|
to take advantage of component-scanning. Note that in this case, we don't |
|
need to explicitly declare <literal><context:annotation-config/></literal>, |
|
because <literal><context:component-scan/></literal> enables all the same |
|
functionality.<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation> |
|
<beans> |
|
<!-- picks up and registers AppConfig as a bean definition --> |
|
<context:component-scan base-package="com.acme"/> |
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> |
|
|
|
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> |
|
<property name="url" value="${jdbc.url}"/> |
|
<property name="username" value="${jdbc.username}"/> |
|
<property name="password" value="${jdbc.password}"/> |
|
</bean> |
|
</beans></programlisting> |
|
</para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java-combining-java-centric"> |
|
<title><literal>@Configuration</literal> class-centric use of XML with |
|
<literal>@ImportResource</literal></title> |
|
<para>In applications where <literal>@Configuration</literal> classes are |
|
the primary mechanism for configuring the container, it will still |
|
likely be necessary to use at least some XML. In these scenarios, |
|
simply use <literal>@ImportResource</literal> and define only as much |
|
XML as is needed. Doing so achieves a "Java-centric" approach to |
|
configuring the container and keeps XML to a bare minimum. |
|
<programlisting language="java">@Configuration |
|
@ImportResource("classpath:/com/acme/properties-config.xml") |
|
public class AppConfig { |
|
private @Value("${jdbcProperties.url}") String url; |
|
private @Value("${jdbcProperties.username}") String username; |
|
private @Value("${jdbcProperties.password}") String password; |
|
|
|
public @Bean DataSource dataSource() { |
|
return new DriverManagerDataSource(url, username, password); |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="xml"><lineannotation role="listingtitle">properties-config.xml</lineannotation> |
|
<beans> |
|
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> |
|
</beans></programlisting> |
|
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation> |
|
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb |
|
jdbc.username=sa |
|
jdbc.password=</programlisting> |
|
<programlisting language="java">public static void main(String[] args) { |
|
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); |
|
TransferService transferService = ctx.getBean(TransferService.class); |
|
// ... |
|
}</programlisting></para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java-bean-annotation"> |
|
<title>Using the <interfacename>@Bean</interfacename> annotation</title> |
|
|
|
<para><interfacename>@Bean</interfacename> is a method-level annotation |
|
and a direct analog of the XML <code><bean/></code> element. The |
|
annotation supports some of the attributes offered by |
|
<code><bean/></code>, such as: <code><link |
|
linkend="beans-factory-lifecycle-initializingbean">init-method</link></code>, |
|
<code><link |
|
linkend="beans-factory-lifecycle-disposablebean">destroy-method</link></code>, |
|
<code><link linkend="beans-factory-autowire">autowiring</link></code> |
|
and <code>name</code>.</para> |
|
|
|
<para>You can use the <interfacename>@Bean</interfacename> annotation in |
|
a <interfacename>@Configuration</interfacename>-annotated or in a |
|
<interfacename>@Component</interfacename>-annotated class.</para> |
|
|
|
<section id="beans-java-declaring-a-bean"> |
|
<title>Declaring a bean</title> |
|
|
|
<para>To declare a bean, simply annotate a method with the |
|
<interfacename>@Bean</interfacename> annotation. You use this method |
|
to register a bean definition within an |
|
<code>ApplicationContext</code> of the type specified as the method's |
|
return value. By default, the bean name will be the same as the method |
|
name. The following is a simple example of a |
|
<interfacename>@Bean</interfacename> method declaration: |
|
<programlisting language="java">@Configuration |
|
public class AppConfig { |
|
|
|
@Bean |
|
public TransferService transferService() { |
|
return new TransferServiceImpl(); |
|
} |
|
|
|
}</programlisting></para> |
|
|
|
<para>The preceding configuration is exactly equivalent to the |
|
following Spring XML: <programlisting language="xml"><beans> |
|
<bean id="transferService" class="com.acme.TransferServiceImpl"/> |
|
</beans> </programlisting></para> |
|
|
|
<para>Both declarations make a bean named <code>transferService</code> |
|
available in the <code>ApplicationContext</code>, bound to an object |
|
instance of type <code>TransferServiceImpl</code>: <programlisting> |
|
transferService -> com.acme.TransferServiceImpl |
|
</programlisting></para> |
|
</section> |
|
|
|
<section id="beans-java-injecting-dependencies"> |
|
<title>Injecting dependencies</title> |
|
|
|
<para>When <interfacename>@Bean</interfacename>s have dependencies on |
|
one another, expressing that dependency is as simple as having one |
|
bean method call another: <programlisting language="java">@Configuration |
|
public class AppConfig { |
|
|
|
@Bean |
|
public Foo foo() { |
|
return new Foo(bar()); |
|
} |
|
|
|
@Bean |
|
public Bar bar() { |
|
return new Bar(); |
|
} |
|
|
|
} </programlisting></para> |
|
|
|
<para>In the example above, the <code>foo</code> bean receives a |
|
reference to <code> bar</code> via constructor injection.</para> |
|
</section> |
|
|
|
<section id="beans-java-lifecycle-callbacks"> |
|
<title>Receiving lifecycle callbacks</title> |
|
|
|
<para>Beans declared in a |
|
<interfacename>@Configuration</interfacename>-annotated class support |
|
the regular lifecycle callbacks. Any classes defined with the |
|
<literal>@Bean</literal> annotation can use the |
|
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal> |
|
annotations from JSR-250, see <link |
|
linkend="beans-postconstruct-and-predestroy-annotations">JSR-250 |
|
annotations</link> for further details.</para> |
|
|
|
<para>The regular Spring <link |
|
linkend="beans-factory-nature">lifecycle</link> callbacks are fully |
|
supported as well. If a bean implements <code>InitializingBean</code>, |
|
<code>DisposableBean</code>, or <code>Lifecycle</code>, their |
|
respective methods are called by the container.</para> |
|
|
|
<para>The standard set of <code>*Aware</code> interfaces such as |
|
<code><link |
|
linkend="beans-beanfactory">BeanFactoryAware</link></code>, |
|
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>, |
|
<code><link |
|
linkend="context-functionality-messagesource">MessageSourceAware</link></code>, |
|
<code><link |
|
linkend="beans-factory-aware">ApplicationContextAware</link></code>, |
|
and so on are also fully supported.</para> |
|
|
|
<para>The <interfacename>@Bean</interfacename> annotation supports |
|
specifying arbitrary initialization and destruction callback methods, |
|
much like Spring XML's <code>init-method</code> and |
|
<code>destroy-method</code> attributes on the <code>bean</code> |
|
element: <programlisting language="java">public class Foo { |
|
public void init() { |
|
// initialization logic |
|
} |
|
} |
|
|
|
public class Bar { |
|
public void cleanup() { |
|
// destruction logic |
|
} |
|
} |
|
|
|
@Configuration |
|
public class AppConfig { |
|
@Bean(initMethod = "init") |
|
public Foo foo() { |
|
return new Foo(); |
|
} |
|
@Bean(destroyMethod = "cleanup") |
|
public Bar bar() { |
|
return new Bar(); |
|
} |
|
} |
|
</programlisting></para> |
|
|
|
<para>Of course, in the case of <code>Foo</code> above, it would be |
|
equally as valid to call the <code>init()</code> method directly |
|
during construction: <programlisting language="java">@Configuration |
|
public class AppConfig { |
|
@Bean |
|
public Foo foo() { |
|
Foo foo = new Foo(); |
|
foo.init(); |
|
return foo; |
|
} |
|
|
|
// ... |
|
} </programlisting></para> |
|
|
|
<tip> |
|
<para>When you work directly in Java, you can do anything you like |
|
with your objects and do not always need to rely on the |
|
container lifecycle!</para> |
|
</tip> |
|
</section> |
|
|
|
<section id="beans-java-specifying-bean-scope"> |
|
<title>Specifying bean scope</title> |
|
|
|
<section id="beans-java-available-scopes"> |
|
<title>Using the <interfacename>@Scope</interfacename> |
|
annotation</title> |
|
|
|
<!-- MLP: Beverly, did not apply your edit as it changed meaning --> |
|
|
|
<para>You can specify that your beans defined with the |
|
<interfacename>@Bean</interfacename> annotation should have a |
|
specific scope. You can use any of the standard scopes specified in |
|
the <link linkend="beans-factory-scopes">Bean Scopes</link> |
|
section.</para> |
|
|
|
<para>The default scope is <literal>singleton</literal>, but you can |
|
override this with the <interfacename>@Scope</interfacename> |
|
annotation: <programlisting language="java">@Configuration |
|
public class MyConfiguration { |
|
@Bean |
|
<emphasis role="bold">@Scope("prototype")</emphasis> |
|
public Encryptor encryptor() { |
|
// ... |
|
} |
|
}</programlisting></para> |
|
</section> |
|
|
|
<section id="beans-java-scoped-proxy"> |
|
<title><code>@Scope and scoped-proxy</code></title> |
|
|
|
<para>Spring offers a convenient way of working with scoped |
|
dependencies through <link |
|
linkend="beans-factory-scopes-other-injection">scoped |
|
proxies</link>. The easiest way to create such a proxy when using |
|
the XML configuration is the <code><aop:scoped-proxy/></code> |
|
element. Configuring your beans in Java with a @Scope annotation |
|
offers equivalent support with the proxyMode attribute. The default |
|
is no proxy (<varname>ScopedProxyMode.NO</varname>), but you can |
|
specify <classname>ScopedProxyMode.TARGET_CLASS</classname> or |
|
<classname>ScopedProxyMode.INTERFACES</classname>.</para> |
|
|
|
<para>If you port the scoped proxy example from the XML reference |
|
documentation (see preceding link) to our |
|
<interfacename>@Bean</interfacename> using Java, it would look like |
|
the following: <programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy |
|
@Bean |
|
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis> |
|
public UserPreferences userPreferences() { |
|
return new UserPreferences(); |
|
} |
|
|
|
@Bean |
|
public Service userService() { |
|
UserService service = new SimpleUserService(); |
|
// a reference to the proxied userPreferences bean |
|
service.setUserPreferences(userPreferences()); |
|
return service; |
|
} </programlisting></para> |
|
</section> |
|
|
|
<section id="beans-java-method-injection"> |
|
<title>Lookup method injection</title> |
|
|
|
<para>As noted earlier, <link |
|
linkend="beans-factory-method-injection">lookup method |
|
injection</link> is an advanced feature that you should use rarely. |
|
It is useful in cases where a singleton-scoped bean has a dependency |
|
on a prototype-scoped bean. Using Java for this type of |
|
configuration provides a natural means for implementing this |
|
pattern. <programlisting language="java">public abstract class CommandManager { |
|
public Object process(Object commandState) { |
|
// grab a new instance of the appropriate Command interface |
|
Command command = createCommand(); |
|
|
|
// set the state on the (hopefully brand new) Command instance |
|
command.setState(commandState); |
|
return command.execute(); |
|
} |
|
|
|
// okay... but where is the implementation of this method? |
|
protected abstract Command createCommand(); |
|
} </programlisting></para> |
|
|
|
<para>Using Java-configuration support , you can create a subclass |
|
of <code>CommandManager</code> where the abstract |
|
<code>createCommand()</code> method is overridden in such a way that |
|
it looks up a new (prototype) command object: <programlisting |
|
language="java">@Bean |
|
@Scope("prototype") |
|
public AsyncCommand asyncCommand() { |
|
AsyncCommand command = new AsyncCommand(); |
|
// inject dependencies here as required |
|
return command; |
|
} |
|
|
|
@Bean |
|
public CommandManager commandManager() { |
|
// return new anonymous implementation of CommandManager with command() overridden |
|
// to return a new prototype Command object |
|
return new CommandManager() { |
|
protected Command createCommand() { |
|
return asyncCommand(); |
|
} |
|
} |
|
} </programlisting></para> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-java-customizing-bean-naming"> |
|
<title>Customizing bean naming</title> |
|
|
|
<para>By default, configuration classes use a |
|
<interfacename>@Bean</interfacename> method's name as the name of the |
|
resulting bean. This functionality can be overridden, however, with |
|
the <code>name</code> attribute. <programlisting language="java">@Configuration |
|
public class AppConfig { |
|
|
|
@Bean(name = "myFoo") |
|
public Foo foo() { |
|
return new Foo(); |
|
} |
|
|
|
} </programlisting></para> |
|
</section> |
|
|
|
<section id="beans-java-bean-aliasing"> |
|
<title>Bean aliasing</title> |
|
|
|
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes desirable |
|
to give a single bean multiple names, otherwise known as <emphasis>bean aliasing</emphasis>. |
|
The <literal>name</literal> attribute of the <literal>@Bean</literal> annotation accepts |
|
a String array for this purpose. <programlisting language="java">@Configuration |
|
public class AppConfig { |
|
|
|
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" }) |
|
public DataSource dataSource() { |
|
// instantiate, configure and return DataSource bean... |
|
} |
|
|
|
} </programlisting></para> |
|
</section> |
|
</section> |
|
</section> |
|
|
|
<section id="context-load-time-weaver"> |
|
<title>Registering a <interfacename>LoadTimeWeaver</interfacename></title> |
|
|
|
<para>The <literal>context</literal> namespace introduced in Spring 2.5 |
|
provides a <literal>load-time-weaver</literal> element.<!--Need to explain purpose of LoadTimeWeaver? Is this section ok here? --></para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<context:load-time-weaver/> |
|
|
|
</beans></programlisting> |
|
|
|
<para>Adding this element to an XML-based Spring configuration file |
|
activates a Spring <interfacename>LoadTimeWeaver</interfacename> for the |
|
<interfacename>ApplicationContext</interfacename>. Any bean within that |
|
<interfacename>ApplicationContext</interfacename> may implement |
|
<interfacename>LoadTimeWeaverAware</interfacename>, thereby receiving a |
|
reference to the load-time weaver instance. This is particularly useful in |
|
combination with <link linkend="orm-jpa">Spring's JPA support</link> where |
|
load-time weaving may be necessary for JPA class transformation. Consult |
|
the <classname>LocalContainerEntityManagerFactoryBean</classname> Javadoc |
|
for more detail. For more on AspectJ load-time weaving, see <xref |
|
linkend="aop-aj-ltw" />.</para> |
|
</section> |
|
|
|
<section id="context-introduction"> |
|
<title>Additional Capabilities of the |
|
<interfacename>ApplicationContext</interfacename></title> |
|
|
|
<!-- MLP: Beverly to review paragraph and list --> |
|
|
|
<para>As was discussed in the chapter introduction, the |
|
<literal>org.springframework.beans.factory</literal> package provides |
|
basic functionality for managing and manipulating beans, including in a |
|
programmatic way. The <literal>org.springframework.context</literal> |
|
package adds the <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html"><interfacename>ApplicationContext</interfacename></ulink> |
|
interface, which implements the <interfacename>BeanFactory</interfacename> |
|
interface, in addition to extending other interfaces to provide additional |
|
functionality in a more <emphasis>application framework-oriented |
|
style</emphasis>. Many people use the |
|
<interfacename>ApplicationContext</interfacename> in a completely |
|
declarative fashion, not even creating it programmatically, but instead |
|
relying on support classes such as <classname>ContextLoader</classname> to |
|
automatically instantiate an |
|
<interfacename>ApplicationContext</interfacename> as part of the normal |
|
startup process of a J2EE web application.</para> |
|
|
|
<para>To enhance <interfacename>BeanFactory</interfacename> functionality |
|
in a more framework-oriented style the context package also provides the |
|
following functionality:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para><emphasis>Access to messages in i18n-style</emphasis>, through |
|
the <interfacename>MessageSource</interfacename> interface.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><emphasis>Access to resources</emphasis>, such as URLs and |
|
files, through the <interfacename>ResourceLoader</interfacename> |
|
interface.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><emphasis>Event publication</emphasis> to beans implementing the |
|
<interfacename>ApplicationListener</interfacename> interface, through |
|
the use of the |
|
<interfacename>ApplicationEventPublisher</interfacename> |
|
interface.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><emphasis>Loading of multiple (hierarchical) |
|
contexts</emphasis>, allowing each to be focused on one particular |
|
layer, such as the web layer of an application, through the |
|
<interfacename>HierarchicalBeanFactory</interfacename> |
|
interface.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<section id="context-functionality-messagesource"> |
|
<title>Internationalization using |
|
<interfacename>MessageSource</interfacename></title> |
|
|
|
<!-- MLP: Beverly to review this paragraph --> |
|
|
|
<para>The <interfacename>ApplicationContext</interfacename> interface |
|
extends an interface called |
|
<interfacename>MessageSource</interfacename>, and therefore provides |
|
internationalization (i18n) functionality. Spring also provides the |
|
interface <classname>HierarchicalMessageSource</classname>, which can |
|
resolve messages hierarchically. Together these interfaces provide the |
|
foundation upon which Spring effects message resolution. The methods |
|
defined on these interfaces include:</para> |
|
|
|
<itemizedlist> |
|
<listitem> |
|
<para><methodname>String getMessage(String code, Object[] args, |
|
String default, Locale loc)</methodname>: The basic method used to |
|
retrieve a message from the |
|
<interfacename>MessageSource</interfacename>. When no message is |
|
found for the specified locale, the default message is used. Any |
|
arguments passed in become replacement values, using the |
|
<interfacename>MessageFormat</interfacename> functionality provided |
|
by the standard library.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><methodname>String getMessage(String code, Object[] args, |
|
Locale loc)</methodname>: Essentially the same as the previous |
|
method, but with one difference: no default message can be |
|
specified; if the message cannot be found, a |
|
<classname>NoSuchMessageException</classname> is thrown.</para> |
|
</listitem> |
|
|
|
<listitem> |
|
<para><methodname>String getMessage(MessageSourceResolvable |
|
resolvable, Locale locale)</methodname>: All properties used in the |
|
preceding methods are also wrapped in a class named |
|
<interfacename>MessageSourceResolvable</interfacename>, which you |
|
can use with this method.</para> |
|
</listitem> |
|
</itemizedlist> |
|
|
|
<para>When an <interfacename>ApplicationContext</interfacename> is |
|
loaded, it automatically searches for a |
|
<interfacename>MessageSource</interfacename> bean defined in the |
|
context. The bean must have the name <literal>messageSource</literal>. |
|
If such a bean is found, all calls to the preceding methods are |
|
delegated to the message source. If no message source is found, the |
|
<interfacename>ApplicationContext</interfacename> attempts to find a |
|
parent containing a bean with the same name. If it does, it uses that |
|
bean as the <interfacename>MessageSource</interfacename>. If the |
|
<interfacename>ApplicationContext</interfacename> cannot find any source |
|
for messages, an empty <classname>DelegatingMessageSource</classname> is |
|
instantiated in order to be able to accept calls to the methods defined |
|
above.</para> |
|
|
|
<para>Spring provides two <interfacename>MessageSource</interfacename> |
|
implementations, <classname>ResourceBundleMessageSource</classname> and |
|
<classname>StaticMessageSource</classname>. Both implement |
|
<interfacename>HierarchicalMessageSource</interfacename> in order to do |
|
nested messaging. The <classname>StaticMessageSource</classname> is |
|
rarely used but provides programmatic ways to add messages to the |
|
source. The <classname>ResourceBundleMessageSource</classname> is shown |
|
in the following example:</para> |
|
|
|
<programlisting language="xml"><beans> |
|
<bean id="messageSource" |
|
class="org.springframework.context.support.ResourceBundleMessageSource"> |
|
<property name="basenames"> |
|
<list> |
|
<value>format</value> |
|
<value>exceptions</value> |
|
<value>windows</value> |
|
</list> |
|
</property> |
|
</bean> |
|
</beans></programlisting> |
|
|
|
<para>In the example it is assumed you have three resource bundles |
|
defined in your classpath called <literal>format</literal>, |
|
<literal>exceptions</literal> and <literal>windows</literal>. Any |
|
request to resolve a message will be handled in the JDK standard way of |
|
resolving messages through ResourceBundles. For the purposes of the |
|
example, assume the contents of two of the above resource bundle files |
|
are...</para> |
|
|
|
<programlisting language="java"><lineannotation># in format.properties</lineannotation> |
|
message=Alligators rock!</programlisting> |
|
|
|
<programlisting language="java"><lineannotation># in exceptions.properties</lineannotation> |
|
argument.required=The '{0}' argument is required.</programlisting> |
|
|
|
<para>A program to execute the <classname>MessageSource</classname> |
|
functionality is shown in the next example. Remember that all |
|
<classname>ApplicationContext</classname> implementations are also |
|
<classname>MessageSource</classname> implementations and so can be cast |
|
to the <classname>MessageSource</classname> interface.</para> |
|
|
|
<programlisting language="java">public static void main(String[] args) { |
|
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); |
|
String message = resources.getMessage("message", null, "Default", null); |
|
System.out.println(message); |
|
}</programlisting> |
|
|
|
<para>The resulting output from the above program will be...</para> |
|
|
|
<programlisting>Alligators rock!</programlisting> |
|
|
|
<para>So to summarize, the <classname>MessageSource</classname> is |
|
defined in a file called <literal>beans.xml</literal>, which exists at |
|
the root of your classpath. The <literal>messageSource</literal> bean |
|
definition refers to a number of resource bundles through its |
|
<literal>basenames</literal> property. The three files that are passed |
|
in the list to the <literal>basenames</literal> property exist as files |
|
at the root of your classpath and are called |
|
<literal>format.properties</literal>, |
|
<literal>exceptions.properties</literal>, and |
|
<literal>windows.properties</literal> respectively.</para> |
|
|
|
<para>The next example shows arguments passed to the message lookup; |
|
these arguments will be converted into Strings and inserted into |
|
placeholders in the lookup message.</para> |
|
|
|
<programlisting language="xml"><beans> |
|
|
|
<lineannotation><!-- this <interfacename>MessageSource</interfacename> is being used in a web application --></lineannotation> |
|
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> |
|
<property name="basename" value="test-messages"/> |
|
</bean> |
|
|
|
<lineannotation><!-- lets inject the above <interfacename>MessageSource</interfacename> into this POJO --></lineannotation> |
|
<bean id="example" class="com.foo.Example"> |
|
<property name="messages" ref="messageSource"/> |
|
</bean> |
|
|
|
</beans></programlisting> |
|
|
|
<programlisting language="java">public class Example { |
|
|
|
private MessageSource messages; |
|
|
|
public void setMessages(MessageSource messages) { |
|
this.messages = messages; |
|
} |
|
|
|
public void execute() { |
|
String message = this.messages.getMessage("argument.required", |
|
new Object [] {"userDao"}, "Required", null); |
|
System.out.println(message); |
|
} |
|
|
|
}</programlisting> |
|
|
|
<para>The resulting output from the invocation of the |
|
<methodname>execute()</methodname> method will be...</para> |
|
|
|
<programlisting>The userDao argument is required.</programlisting> |
|
|
|
<para>With regard to internationalization (i18n), Spring's various |
|
<classname>MessageResource</classname> implementations follow the same |
|
locale resolution and fallback rules as the standard JDK |
|
<classname>ResourceBundle</classname>. In short, and continuing with the |
|
example <literal>messageSource</literal> defined previously, if you want |
|
to resolve messages against the British (en-GB) locale, you would create |
|
files called <literal>format_en_GB.properties</literal>, |
|
<literal>exceptions_en_GB.properties</literal>, and |
|
<literal>windows_en_GB.properties</literal> respectively.</para> |
|
|
|
<para>Typically, locale resolution is managed by the surrounding |
|
environment of the application. In this example, the locale against |
|
which (British) messages will be resolved is specified manually.</para> |
|
|
|
<programlisting><lineannotation># in exceptions_en_GB.properties</lineannotation> |
|
argument.required=Ebagum lad, the '{0}' argument is required, I say, required.</programlisting> |
|
|
|
<programlisting language="java">public static void main(final String[] args) { |
|
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml"); |
|
String message = resources.getMessage("argument.required", |
|
new Object [] {"userDao"}, "Required", Locale.UK); |
|
System.out.println(message); |
|
}</programlisting> |
|
|
|
<para>The resulting output from the running of the above program will |
|
be...</para> |
|
|
|
<programlisting>Ebagum lad, the 'userDao' argument is required, I say, required.</programlisting> |
|
|
|
<para>You can also use the <classname>MessageSourceAware</classname> |
|
interface to acquire a reference to any |
|
<classname>MessageSource</classname> that has been defined. Any bean |
|
that is defined in an <classname>ApplicationContext</classname> that |
|
implements the <classname>MessageSourceAware</classname> interface is |
|
injected with the application context's |
|
<classname>MessageSource</classname> when the bean is created and |
|
configured.</para> |
|
|
|
<note> |
|
<para><emphasis>As an alternative to |
|
<classname>ResourceBundleMessageSource</classname>, Spring provides a |
|
<classname>ReloadableResourceBundleMessageSource</classname> class. |
|
This variant supports the same bundle file format but is more flexible |
|
than the standard JDK based |
|
<classname>ResourceBundleMessageSource</classname> |
|
implementation.</emphasis> In particular, it allows for reading files |
|
from any Spring resource location (not just from the classpath) and |
|
supports hot reloading of bundle property files (while efficiently |
|
caching them in between). Check out the |
|
<classname>ReloadableResourceBundleMessageSource</classname> javadoc |
|
for details.</para> |
|
</note> |
|
</section> |
|
|
|
<section id="context-functionality-events"> |
|
<title>Standard and Custom Events</title> |
|
|
|
<para>Event handling in the |
|
<interfacename>ApplicationContext</interfacename> is provided through |
|
the <classname>ApplicationEvent</classname> class and |
|
<interfacename>ApplicationListener</interfacename> interface. If a bean |
|
that implements the <interfacename>ApplicationListener</interfacename> |
|
interface is deployed into the context, every time an |
|
<classname>ApplicationEvent</classname> gets published to the |
|
<interfacename>ApplicationContext</interfacename>, that bean is |
|
notified. Essentially, this is the standard |
|
<emphasis>Observer</emphasis> design pattern. Spring provides the |
|
following standard events:</para> |
|
|
|
<table id="beans-ctx-events-tbl"> |
|
<title>Built-in Events</title> |
|
|
|
<tgroup cols="2"> |
|
<colspec colname="c1" colwidth="2*" /> |
|
|
|
<colspec colname="c2" colwidth="5*" /> |
|
|
|
<thead> |
|
<row> |
|
<entry>Event</entry> |
|
|
|
<entry>Explanation</entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry><classname>ContextRefreshedEvent</classname></entry> |
|
|
|
<entry>Published when the |
|
<interfacename>ApplicationContext</interfacename> is initialized |
|
or refreshed, for example, using the |
|
<methodname>refresh()</methodname> method on the |
|
<interfacename>ConfigurableApplicationContext</interfacename> |
|
interface. "Initialized" here means that all beans are loaded, |
|
post-processor beans are detected and activated, singletons are |
|
pre-instantiated, and the |
|
<interfacename>ApplicationContext</interfacename> object is |
|
ready for use. As long as the context has not been closed, a |
|
refresh can be triggered multiple times, provided that the |
|
chosen <interfacename>ApplicationContext</interfacename> |
|
actually supports such "hot" refreshes. For example, |
|
<classname>XmlWebApplicationContext</classname> supports hot |
|
refreshes, but <classname>GenericApplicationContext</classname> |
|
does not.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry><classname>ContextStartedEvent</classname></entry> |
|
|
|
<entry>Published when the |
|
<interfacename>ApplicationContext</interfacename> is started, |
|
using the <methodname>start()</methodname> method on the |
|
<interfacename>ConfigurableApplicationContext</interfacename> |
|
interface. "Started" here means that all |
|
<interfacename>Lifecycle</interfacename> beans receive an |
|
explicit start signal. Typically this signal is used to restart |
|
beans after an explicit stop, but it may also be used to start |
|
components that have not been configured for autostart , for |
|
example, components that have not already started on |
|
initialization.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry><classname>ContextStoppedEvent</classname></entry> |
|
|
|
<entry>Published when the |
|
<interfacename>ApplicationContext</interfacename> is stopped, |
|
using the <methodname>stop()</methodname> method on the |
|
<interfacename>ConfigurableApplicationContext</interfacename> |
|
interface. "Stopped" here means that all |
|
<interfacename>Lifecycle</interfacename> beans receive an |
|
explicit stop signal. A stopped context may be restarted through |
|
a <methodname>start()</methodname> call.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry><classname>ContextClosedEvent</classname></entry> |
|
|
|
<entry>Published when the |
|
<interfacename>ApplicationContext</interfacename> is closed, |
|
using the <methodname>close()</methodname> method on the |
|
<interfacename>ConfigurableApplicationContext</interfacename> |
|
interface. "Closed" here means that all singleton beans are |
|
destroyed. A closed context reaches its end of life; it cannot |
|
be refreshed or restarted.</entry> |
|
</row> |
|
|
|
<row> |
|
<entry><classname>RequestHandledEvent</classname></entry> |
|
|
|
<entry>A web-specific event telling all beans that an HTTP |
|
request has been serviced. This event is published |
|
<emphasis>after</emphasis> the request is complete. This event |
|
is only applicable to web applications using Spring's |
|
<classname>DispatcherServlet</classname>.</entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>You can also implement custom events. Simply call the |
|
<methodname>publishEvent()</methodname> method on the |
|
<interfacename>ApplicationContext</interfacename>, specifying a |
|
parameter that is an instance of your custom event class that implements |
|
<classname>ApplicationEvent</classname>. Event listeners receive events |
|
synchronously. This means the <methodname>publishEvent()</methodname> |
|
method blocks until all listeners have finished processing the event. |
|
(It is possible to supply an alternate event publishing strategy through |
|
an <interfacename>ApplicationEventMulticaster</interfacename> |
|
implementation). Furthermore, when a listener receives an event, it |
|
operates inside the transaction context of the publisher, if a |
|
transaction context is available.<!--Explain what is showing in the first and second examples?--></para> |
|
|
|
<para>This example shows the bean definitions used to configure an |
|
<interfacename>ApplicationContext</interfacename>:</para> |
|
|
|
<programlisting language="xml"><bean id="emailer" class="example.EmailBean"> |
|
<property name="blackList"> |
|
<list> |
|
<value>black@list.org</value> |
|
<value>white@list.org</value> |
|
<value>john@doe.org</value> |
|
</list> |
|
</property> |
|
</bean> |
|
|
|
<bean id="blackListListener" class="example.BlackListNotifier"> |
|
<property name="notificationAddress" value="spam@list.org"/> |
|
</bean></programlisting> |
|
|
|
<para>This example shows the implementation of the classes refered to in |
|
the previous bean definitions:</para> |
|
|
|
<programlisting language="java">public class EmailBean implements ApplicationContextAware { |
|
|
|
private List blackList; |
|
private ApplicationContext ctx; |
|
|
|
public void setBlackList(List blackList) { |
|
this.blackList = blackList; |
|
} |
|
|
|
public void setApplicationContext(ApplicationContext ctx) { |
|
this.ctx = ctx; |
|
} |
|
|
|
public void sendEmail(String address, String text) { |
|
if (blackList.contains(address)) { |
|
BlackListEvent event = new BlackListEvent(address, text); |
|
ctx.publishEvent(event); |
|
return; |
|
} |
|
<lineannotation>// send email...</lineannotation> |
|
} |
|
}</programlisting> |
|
|
|
<programlisting language="java">public class BlackListNotifier implements ApplicationListener { |
|
|
|
private String notificationAddress; |
|
|
|
public void setNotificationAddress(String notificationAddress) { |
|
this.notificationAddress = notificationAddress; |
|
} |
|
|
|
public void onApplicationEvent(ApplicationEvent event) { |
|
if (event instanceof BlackListEvent) { |
|
<lineannotation>// notify appropriate person...</lineannotation> |
|
} |
|
} |
|
}</programlisting> |
|
|
|
<!-- MLP: Beverly to review paragraph --> |
|
|
|
<para>When the sendEmail method is called, if there are any emails that |
|
should be blacklisted, a custom event of the type BlackListEvent is |
|
published to the application context. The BlackListNotifier class which |
|
implements the interface ApplicationListener is registered as a |
|
subscriber to the application context and will receive the |
|
BlackListEvent. In order to access properties specific to |
|
BlackListEvent, the listener must perform a downcast.</para> |
|
</section> |
|
|
|
<section id="context-functionality-resources"> |
|
<title>Convenient access to low-level resources</title> |
|
|
|
<para>For optimal usage and understanding of application contexts, users |
|
should generally familiarize themselves with Spring's |
|
<interfacename>Resource</interfacename> abstraction, as described in the |
|
chapter <xref linkend="resources" />.</para> |
|
|
|
<para>An application context is a |
|
<interfacename>ResourceLoader</interfacename>, which can be used to load |
|
<interfacename>Resource</interfacename>s. A |
|
<interfacename>Resource</interfacename> is essentially a more feature |
|
rich version of the JDK class <literal>java.net.URL</literal>, in fact, |
|
the implementations of the <interfacename>Resource</interfacename> wrap |
|
an instance of <literal>java.net.URL</literal> where appropriate. A |
|
<interfacename>Resource</interfacename> can obtain low-level resources |
|
from almost any location in a transparent fashion, including from the |
|
classpath, a filesystem location, anywhere describable with a standard |
|
URL, and some other variations. If the resource location string is a |
|
simple path without any special prefixes, where those resources come |
|
from is specific and appropriate to the actual application context |
|
type.</para> |
|
|
|
<para>You can configure a bean deployed into the application context to |
|
implement the special callback interface, |
|
<interfacename>ResourceLoaderAware</interfacename>, to be automatically |
|
called back at initialization time with the application context itself |
|
passed in as the <interfacename>ResourceLoader</interfacename>. You can |
|
also expose properties of type <interfacename>Resource</interfacename>, |
|
to be used to access static resources; they will be injected into it |
|
like any other properties. You can specify those |
|
<interfacename>Resource</interfacename> properties as simple String |
|
paths, and rely on a special JavaBean |
|
<interfacename>PropertyEditor</interfacename> that is automatically |
|
registered by the context, to convert those text strings to actual |
|
<interfacename>Resource</interfacename> objects when the bean is |
|
deployed.</para> |
|
|
|
<para>The location path or paths supplied to an |
|
<interfacename>ApplicationContext</interfacename> constructor are |
|
actually resource strings, and in simple form are treated appropriately |
|
to the specific context implementation. |
|
<classname>ClassPathXmlApplicationContext</classname> treats a simple |
|
location path as a classpath location. You can also use location paths |
|
(resource strings) with special prefixes to force loading of definitions |
|
from the classpath or a URL, regardless of the actual context |
|
type.</para> |
|
</section> |
|
|
|
<section id="context-create"> |
|
<title>Convenient <interfacename>ApplicationContext</interfacename> |
|
instantiation for web applications</title> |
|
|
|
<para>You can create <interfacename>ApplicationContext</interfacename> |
|
instances declaratively by using, for example, a |
|
<classname>ContextLoader</classname>. Of course you can also create |
|
<interfacename>ApplicationContext</interfacename> instances |
|
programmatically by using one of the |
|
<interfacename>ApplicationContext</interfacename> |
|
implementations.</para> |
|
|
|
<para>The <classname>ContextLoader</classname> mechanism comes in two |
|
flavors: the <classname>ContextLoaderListener</classname> and the |
|
<classname>ContextLoaderServlet</classname>. They have the same |
|
functionality but differ in that the listener version is not reliable in |
|
Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet |
|
context listeners must execute immediately after the Servlet context for |
|
the web application is created and is available to service the first |
|
request (and also when the Servlet context is about to be shut down). As |
|
such a Servlet context listener is an ideal place to initialize the |
|
Spring <interfacename>ApplicationContext</interfacename>. All things |
|
being equal, you should probably prefer |
|
<classname>ContextLoaderListener</classname>; for more information on |
|
compatibility, have a look at the Javadoc for the |
|
<classname>ContextLoaderServlet</classname>.</para> |
|
|
|
<para>You can register an |
|
<interfacename>ApplicationContext</interfacename> using the |
|
<classname>ContextLoaderListener</classname> as follows:</para> |
|
|
|
<programlisting language="xml"><context-param> |
|
<param-name>contextConfigLocation</param-name> |
|
<param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value> |
|
</context-param> |
|
|
|
<listener> |
|
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> |
|
</listener> |
|
|
|
<lineannotation><!-- or use the <classname>ContextLoaderServlet</classname> instead of the above listener</lineannotation><emphasis> |
|
<servlet> |
|
<servlet-name>context</servlet-name> |
|
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> |
|
<load-on-startup>1</load-on-startup> |
|
</servlet> |
|
--</emphasis>></programlisting> |
|
|
|
<para>The listener inspects the <literal>contextConfigLocation</literal> |
|
parameter. If the parameter does not exist, the listener uses |
|
<literal>/WEB-INF/applicationContext.xml</literal> as a default. When |
|
the parameter <emphasis>does</emphasis> exist, the listener separates |
|
the String by using predefined delimiters (comma, semicolon and |
|
whitespace) and uses the values as locations where application contexts |
|
will be searched. Ant-style path patterns are supported as well. |
|
Examples are <literal>/WEB-INF/*Context.xml</literal> for all files with |
|
names ending with "Context.xml", residing in the "WEB-INF" directory, |
|
and <literal>/WEB-INF/**/*Context.xml</literal>, for all such files in |
|
any subdirectory of "WEB-INF".</para> |
|
|
|
<para>You can use <classname>ContextLoaderServlet</classname> instead of |
|
<classname>ContextLoaderListener</classname>. The Servlet uses the |
|
<literal>contextConfigLocation</literal> parameter just as the listener |
|
does.</para> |
|
</section> |
|
|
|
<section> |
|
<title>Deploying a Spring ApplicationContext as a J2EE RAR file</title> |
|
|
|
<para>In Spring 2.5 and later, it is possible to deploy a Spring |
|
ApplicationContext as a RAR file, encapsulating the context and all of |
|
its required bean classes and library JARs in a J2EE RAR deployment |
|
unit. This is the equivalent of bootstrapping a standalone |
|
ApplicationContext, just hosted in J2EE environment, being able to |
|
access the J2EE servers facilities. RAR deployment is a more natural |
|
alternative to scenario of deploying a headless WAR file, in effect, a |
|
WAR file without any HTTP entry points that is used only for |
|
bootstrapping a Spring ApplicationContext in a J2EE environment.</para> |
|
|
|
<para>RAR deployment is ideal for application contexts that do not need |
|
HTTP entry points but rather consist only of message endpoints and |
|
scheduled jobs. Beans in such a context can use application server |
|
resources such as the JTA transaction manager and JNDI-bound JDBC |
|
DataSources and JMS ConnectionFactory instances, and may also register |
|
with the platform's JMX server - all through Spring's standard |
|
transaction management and JNDI and JMX support facilities. Application |
|
components can also interact with the application server's JCA |
|
WorkManager through Spring's <interfacename>TaskExecutor</interfacename> |
|
abstraction.</para> |
|
|
|
<para>Check out the JavaDoc of the <ulink |
|
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html">SpringContextResourceAdapter</ulink> |
|
class for the configuration details involved in RAR deployment.</para> |
|
|
|
<para><emphasis>For a simple deployment of a Spring ApplicationContext |
|
as a J2EE RAR file:</emphasis> package all application classes into a |
|
RAR file, which is a standard JAR file with a different file extension. |
|
Add all required library JARs into the root of the RAR archive. Add a |
|
"META-INF/ra.xml" deployment descriptor (as shown in |
|
<classname>SpringContextResourceAdapter</classname>s JavaDoc) and the |
|
corresponding Spring XML bean definition file(s) (typically |
|
"META-INF/applicationContext.xml"), and drop the resulting RAR file into |
|
your application server's deployment directory.</para> |
|
|
|
<note> |
|
<para>Such RAR deployment units are usually self-contained; they do |
|
not expose components to the outside world, not even to other modules |
|
of the same application. Interaction with a RAR-based |
|
ApplicationContext usually occurs through JMS destinations that it |
|
shares with other modules. A RAR-based ApplicationContext may also, |
|
for example, schedule some jobs, reacting to new files in the file |
|
system (or the like). If it needs to allow synchronous access from the |
|
outside, it could for example export RMI endpoints, which of course |
|
may be used by other application modules on the same machine.</para> |
|
</note> |
|
</section> |
|
</section> |
|
|
|
<section id="beans-beanfactory"> |
|
<title>The BeanFactory</title> |
|
|
|
<para>The <classname>BeanFactory</classname> provides the underlying basis |
|
for Spring's IoC functionality but it is only used directly in integration |
|
with other third-party frameworks and is now largely historical in nature |
|
for most users of Spring. The <classname>BeanFactory</classname> and |
|
related interfaces, such as <classname>BeanFactoryAware</classname>, |
|
<classname>InitializingBean</classname>, |
|
<classname>DisposableBean</classname>, are still present in Spring for the |
|
purposes of backward compatibility with the large number of third-party |
|
frameworks that integrate with Spring. Often third-party components that |
|
can not use more modern equivalents such as <code>@PostConstruct</code> or |
|
<code>@PreDestroy</code> in order to remain compatible with JDK 1.4 or to |
|
avoid a dependency on JSR-250.</para> |
|
|
|
<para>This section provides additional background into the differences |
|
between the <interfacename>BeanFactory</interfacename> and |
|
<interfacename>ApplicationContext</interfacename> and how one might access |
|
the IoC container directly through a classic singleton lookup.</para> |
|
|
|
<section id="context-introduction-ctx-vs-beanfactory"> |
|
<title><interfacename>BeanFactory</interfacename> or |
|
<interfacename>ApplicationContext</interfacename>?</title> |
|
|
|
<para>Use an <interfacename>ApplicationContext</interfacename> unless |
|
you have a good reason for not doing so.</para> |
|
|
|
<para>Because the <interfacename>ApplicationContext</interfacename> |
|
includes all functionality of the |
|
<interfacename>BeanFactory</interfacename>, it is generally recommended |
|
over the <interfacename>BeanFactory</interfacename>, except for a few |
|
situations such as in an <classname>Applet</classname> where memory |
|
consumption might be critical and a few extra kilobytes might make a |
|
difference. However, for most typical enterprise applications and |
|
systems, the <interfacename>ApplicationContext</interfacename> is what |
|
you will want to use. Spring 2.0 and later makes |
|
<emphasis>heavy</emphasis> use of the <link |
|
linkend="beans-factory-extension-bpp"><interfacename>BeanPostProcessor</interfacename> |
|
extension point</link> (to effect proxying and so on). If you use only a |
|
plain <interfacename>BeanFactory</interfacename>, a fair amount of |
|
support such as transactions and AOP will not take effect, at least not |
|
without some extra steps on your part. This situation could be confusing |
|
because nothing is actually wrong with the configuration.</para> |
|
|
|
<para>The following table lists features provided by the |
|
<interfacename>BeanFactory</interfacename> and |
|
<interfacename>ApplicationContext</interfacename> interfaces and |
|
implementations.</para> |
|
|
|
<table id="context-introduction-ctx-vs-beanfactory-feature-matrix" |
|
pgwide="1"> |
|
<title>Feature Matrix</title> |
|
|
|
<tgroup cols="3"> |
|
<colspec align="left" /> |
|
|
|
<thead> |
|
<row> |
|
<entry align="center">Feature</entry> |
|
|
|
<entry |
|
align="center"><interfacename>BeanFactory</interfacename></entry> |
|
|
|
<entry |
|
align="center"><interfacename>ApplicationContext</interfacename></entry> |
|
</row> |
|
</thead> |
|
|
|
<tbody> |
|
<row> |
|
<entry><para>Bean instantiation/wiring</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para>Automatic |
|
<interfacename>BeanPostProcessor</interfacename> |
|
registration</para></entry> |
|
|
|
<entry align="center"><para>No</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para>Automatic |
|
<interfacename>BeanFactoryPostProcessor</interfacename> |
|
registration</para></entry> |
|
|
|
<entry align="center"><para>No</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para>Convenient |
|
<interfacename>MessageSource</interfacename> access (for |
|
i18n)</para></entry> |
|
|
|
<entry align="center"><para>No</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
</row> |
|
|
|
<row> |
|
<entry><para><interfacename>ApplicationEvent</interfacename> |
|
publication</para></entry> |
|
|
|
<entry align="center"><para>No</para></entry> |
|
|
|
<entry align="center"><para>Yes</para></entry> |
|
</row> |
|
</tbody> |
|
</tgroup> |
|
</table> |
|
|
|
<para>To explicitly register a bean post-processor with a |
|
<interfacename>BeanFactory</interfacename> implementation, you must |
|
write code like this:</para> |
|
|
|
<programlisting language="java">ConfigurableBeanFactory factory = new XmlBeanFactory(...); |
|
|
|
<lineannotation>// now register any needed <interfacename>BeanPostProcessor</interfacename> instances</lineannotation> |
|
MyBeanPostProcessor postProcessor = new MyBeanPostProcessor(); |
|
factory.addBeanPostProcessor(postProcessor); |
|
|
|
<lineannotation>// now start using the factory</lineannotation></programlisting> |
|
|
|
<para>To explicitly register a |
|
<classname>BeanFactoryPostProcessor</classname> when using a |
|
<interfacename>BeanFactory</interfacename> implementation, you must |
|
write code like this:</para> |
|
|
|
<programlisting language="java">XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml")); |
|
|
|
<lineannotation>// bring in some property values from a <classname>Properties</classname> file</lineannotation> |
|
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer(); |
|
cfg.setLocation(new FileSystemResource("jdbc.properties")); |
|
|
|
<lineannotation>// now actually do the replacement</lineannotation> |
|
cfg.postProcessBeanFactory(factory);</programlisting> |
|
|
|
<para>In both cases, the explicit registration step is inconvenient, |
|
which is one reason why the various |
|
<interfacename>ApplicationContext</interfacename> implementations are |
|
preferred above plain <interfacename>BeanFactory</interfacename> |
|
implementations in the vast majority of Spring-backed applications, |
|
especially when using <literal>BeanFactoryPostProcessors</literal> and |
|
<classname>BeanPostProcessors</classname>. These mechanisms implement |
|
important functionality such as property placeholder replacement and |
|
AOP.</para> |
|
</section> |
|
|
|
<section id="beans-servicelocator"> |
|
<title>Glue code and the evil singleton</title> |
|
|
|
<para>It is best to write most application code in a |
|
dependency-injection (DI) style, where that code is served out of a |
|
Spring IoC container, has its own dependencies supplied by the container |
|
when it is created, and is completely unaware of the container. However, |
|
for the small glue layers of code that are sometimes needed to tie other |
|
code together, you sometimes need a singleton (or quasi-singleton) style |
|
access to a Spring IoC container. For example, third-party code may try |
|
to construct new objects directly (<literal>Class.forName()</literal> |
|
style), without the ability to get these objects out of a Spring IoC |
|
container. <!--Can you reword the phrase singleton style access, above and next parragraph? Seems awkward.-->If |
|
the object constructed by the third-party code is a small stub or proxy, |
|
which then uses a singleton style access to a Spring IoC container to |
|
get a real object to delegate to, then inversion of control has still |
|
been achieved for the majority of the code (the object coming out of the |
|
container). Thus most code is still unaware of the container or how it |
|
is accessed, and remains decoupled from other code, with all ensuing |
|
benefits. EJBs may also use this stub/proxy approach to delegate to a |
|
plain Java implementation object, retrieved from a Spring IoC container. |
|
While the Spring IoC container itself ideally does not have to be a |
|
singleton, it may be unrealistic in terms of memory usage or |
|
initialization times (when using beans in the Spring IoC container such |
|
as a Hibernate <interfacename>SessionFactory</interfacename>) for each |
|
bean to use its own, non-singleton Spring IoC container.</para> |
|
|
|
<para>Looking up the application context in a service locator style is |
|
sometimes the only option for accessing shared Spring-managed |
|
components, such as in an EJB 2.1 environment, or when you want to share |
|
a single ApplicationContext as a parent to WebApplicationContexts across |
|
WAR files. In this case you should look into using the utility class |
|
<ulink |
|
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/access/ContextSingletonBeanFactoryLocator.html"><classname>ContextSingletonBeanFactoryLocator</classname></ulink> |
|
locator that is described in this <ulink |
|
url="http://blog.springsource.com/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/">SpringSource |
|
team blog entry</ulink>.</para> |
|
</section> |
|
</section> |
|
</chapter>
|
|
|