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