Split IoC chapter DocBook XML into multiple files (SPR-7467)

All <section/> elements in beans.xml >=~ 500 lines have been broken out
into separate documents with DOCTYPE 'section'. This refactoring makes
working with these files much easier in wysiwyg editors (namely
oXygen Author).

For consistency, this same refactoring should be applied to all other
chapters much larger than 1500 lines, such as aop.xml (3861), mvc.xml
(3466), jdbc.xml (3042), and so on.

beans.xml and the new section files have also been formatted for
consistency and to avoid whitespace diffs as much as possible into the
future.
This commit is contained in:
Chris Beams 2010-08-18 10:37:35 +00:00
parent 2f980d95ff
commit 9ab2c6628b
9 changed files with 6928 additions and 6980 deletions

View File

@ -0,0 +1,804 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-annotation-config">
<title>Annotation-based container configuration</title>
<sidebar>
<title>Are annotations better than XML for configuring Spring?</title>
<para>The introduction of annotation-based configurations raised the
question of whether this approach is 'better' than XML. The short answer
is <emphasis>it depends</emphasis>. The long answer is that each approach
has its pros and cons, and usually it is up to the developer to decide
which strategy suits her better. Due to the way they are defined,
annotations provide a lot of context in their declaration, leading to
shorter and more concise configuration. However, XML excels at wiring up
components without touching their source code or recompiling them. Some
developers prefer having the wiring close to the source while others argue
that annotated classes are no longer POJOs and, furthermore, that the
configuration becomes decentralized and harder to control.</para>
<para>No matter the choice, Spring can accommodate both styles and even mix
them together. It's worth pointing out that through its <link
linkend="beans-java">JavaConfig</link> option, Spring allows annotations
to be used in a non-invasive way, without touching the target components
source code and that in terms of tooling, all configuration styles are
supported by the <ulink url="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</ulink>.</para>
</sidebar>
<para>An alternative to XML setups is provided by annotation-based
configuration which rely on the bytecode metadata for wiring up components
instead of angle-bracket declarations. Instead of using XML to describe a
bean wiring, the developer moves the configuration into the component class
itself by using annotations on the relevant class, method, or field
declaration. As mentioned in <xref
linkend="beans-factory-extension-bpp-examples-rabpp"/>, using a
<interfacename>BeanPostProcessor</interfacename> in conjunction with
annotations is a common means of extending the Spring IoC container. For
example, Spring 2.0 introduced the possibility of enforcing required
properties with the <link linkend="beans-required-annotation"
>@Required</link> annotation. As of Spring 2.5, it is now possible to follow
that same general approach to drive Spring's dependency injection.
Essentially, the <interfacename>@Autowired</interfacename> annotation
provides the same capabilities as described in <xref
linkend="beans-factory-autowire"/> but with more fine-grained control and
wider applicability. Spring 2.5 also adds support for JSR-250 annotations
such as <interfacename>@Resource</interfacename>,
<interfacename>@PostConstruct</interfacename>, and
<interfacename>@PreDestroy</interfacename>. Spring 3.0 adds support for
JSR-330 (Dependency Injection for Java) annotations contained in the
javax.inject package such as <classname>@Inject</classname>,
<literal>@Qualifier, @Named, and @Provider</literal> if the JSR330 jar is
present on the classpath. Use of these annotations also requires that
certain <interfacename>BeanPostProcessors</interfacename> be registered
within the Spring container. <note> Annotation injection is performed
<emphasis>before</emphasis> XML injection, thus the latter configuration
will override the former for properties wired through both approaches.
</note> As always, you can register them as individual bean definitions, but
they can also be implicitly registered by including the following tag in an
XML-based Spring configuration (notice the inclusion of the
<literal>context</literal> namespace):</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
<lineannotation>&lt;context:annotation-config/&gt;</lineannotation>
&lt;/beans&gt;</programlisting>
<para>(The implicitly registered post-processors include <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"
><classname>AutowiredAnnotationBeanPostProcessor</classname></ulink>, <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"
><classname>CommonAnnotationBeanPostProcessor</classname></ulink>, <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html"
><classname>PersistenceAnnotationBeanPostProcessor</classname></ulink>, as
well as the aforementioned <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"
><classname>RequiredAnnotationBeanPostProcessor</classname></ulink>.)</para>
<note>
<para><literal>&lt;context:annotation-config/&gt;</literal> only looks for
annotations on beans in the same application context in which it is
defined. This means that, if you put
<literal>&lt;context:annotation-config/&gt;</literal> in a
<interfacename>WebApplicationContext</interfacename> for a
<classname>DispatcherServlet</classname>, it only checks for
<interfacename>@Autowired</interfacename> beans in your controllers, and
not your services. See <xref linkend="mvc-servlet"/> for more
information.</para>
</note>
<section id="beans-required-annotation">
<title><interfacename>@Required</interfacename></title>
<para>The <interfacename>@Required</interfacename> annotation applies to
bean property setter methods, as in the following example:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>This annotation simply indicates that the affected bean property must
be populated at configuration time, through an explicit property value in
a bean definition or through autowiring. The container throws an exception
if the affected bean property has not been populated; this allows for
eager and explicit failure, avoiding
<classname>NullPointerException</classname>s or the like later on. It is
still recommended that you put assertions into the bean class itself, for
example, into an init method. Doing so enforces those required references
and values even when you use the class outside of a container.</para>
</section>
<section id="beans-autowired-annotation">
<title><interfacename>@Autowired and @Inject</interfacename></title>
<para>As expected, you can apply the
<interfacename>@Autowired</interfacename> annotation to "traditional"
setter methods:</para>
<note>
<para>JSR 330's @Inject annotation can be used in place of Spring's
<interfacename>@Autowired</interfacename> in the examples below.
<interfacename>@Inject</interfacename> does not have a required property
unlike Spring's <interfacename>@Autowired</interfacename> annotation
which has a <literal>required</literal> property to indicate if the
value being injected is optional. This behavior is enabled automatically
if you have the JSR 330 JAR on the classpath.</para>
</note>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>You can also apply the annotation to methods with arbitrary names
and/or multiple arguments:</para>
<programlisting language="java">public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>You can apply <interfacename>@Autowired</interfacename> to
constructors and fields:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>It is also possible to provide <emphasis>all</emphasis> beans of a
particular type from the <interfacename>ApplicationContext</interfacename>
by adding the annotation to a field or method that expects an array of
that type:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The same applies for typed collections:</para>
<programlisting language="java">public class MovieRecommender {
private Set&lt;MovieCatalog&gt; movieCatalogs;
@Autowired
public void setMovieCatalogs(Set&lt;MovieCatalog&gt; movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Even typed Maps can be autowired as long as the expected key type is
<classname>String</classname>. The Map values will contain all beans of
the expected type, and the keys will contain the corresponding bean
names:</para>
<programlisting language="java">public class MovieRecommender {
private Map&lt;String, MovieCatalog&gt; movieCatalogs;
@Autowired
public void setMovieCatalogs(Map&lt;String, MovieCatalog&gt; movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>By default, the autowiring fails whenever <emphasis>zero</emphasis>
candidate beans are available; the default behavior is to treat annotated
methods, constructors, and fields as indicating
<emphasis>required</emphasis> dependencies. This behavior can be changed
as demonstrated below.</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required=false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>Only <emphasis>one annotated constructor per-class</emphasis> can be
marked as <emphasis>required</emphasis>, but multiple non-required
constructors can be annotated. In that case, each is considered among
the candidates and Spring uses the <emphasis>greediest</emphasis>
constructor whose dependencies can be satisfied, that is the constructor
that has the largest number of arguments.</para>
<para><interfacename>@Autowired</interfacename>'s
<emphasis>required</emphasis> attribute is recommended over the
<interfacename>@Required</interfacename> annotation. The
<emphasis>required</emphasis> attribute indicates that the property is
not required for autowiring purposes, the property is ignored if it
cannot be autowired. <interfacename>@Required</interfacename>, on the
other hand, is stronger in that it enforces the property that was set by
any means supported by the container. If no value is injected, a
corresponding exception is raised.</para>
</note>
<para>You can also use <interfacename>@Autowired</interfacename> for
interfaces that are well-known resolvable dependencies:
<interfacename>BeanFactory</interfacename>,
<interfacename>ApplicationContext</interfacename>,
<interfacename>ResourceLoader</interfacename>,
<interfacename>ApplicationEventPublisher</interfacename>, and
<interfacename>MessageSource</interfacename>. These interfaces and their
extended interfaces, such as
<interfacename>ConfigurableApplicationContext</interfacename> or
<interfacename>ResourcePatternResolver</interfacename>, are automatically
resolved, with no special setup necessary.</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</section>
<section id="beans-autowired-annotation-qualifiers">
<title>Fine-tuning annotation-based autowiring with qualifiers</title>
<para>Because autowiring by type may lead to multiple candidates, it is
often necessary to have more control over the selection process. One way
to accomplish this is with Spring's
<interfacename>@Qualifier</interfacename> annotation. You can associate
qualifier values with specific arguments, narrowing the set of type
matches so that a specific bean is chosen for each argument. In the
simplest case, this can be a plain descriptive value:</para>
<note>
<para>JSR 330's <interfacename>@Qualifier</interfacename> annotation can
only be applied as a meta-annotation unlike Spring's @Qualifier which
takes a string property to discriminate among multiple injection
candidates and can be placed on annotations as well as types, fields,
methods, constructors, and parameters.</para>
</note>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Qualifier("main")</emphasis>
private MovieCatalog movieCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The <interfacename>@Qualifier</interfacename> annotation can also be
specified on individual constructor arguments or method parameters:</para>
<programlisting language="java">public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(<emphasis role="bold">@Qualifier("main")</emphasis> MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>The corresponding bean definitions appear as follows. The bean with
qualifier value "main" is wired with the constructor argument that is
qualified with the same value.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier value="main"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier value="action"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean id="movieRecommender" class="example.MovieRecommender"/&gt;
&lt;/beans&gt;
</programlisting>
<para>For a fallback match, the bean name is considered a default qualifier
value. Thus you can define the bean with an id "main" instead of the
nested qualifier element, leading to the same matching result. However,
although you can use this convention to refer to specific beans by name,
<interfacename>@Autowired</interfacename> is fundamentally about
type-driven injection with optional semantic qualifiers. This means that
qualifier values, even with the bean name fallback, always have narrowing
semantics within the set of type matches; they do not semantically express
a reference to a unique bean id. Good qualifier values are "main" or
"EMEA" or "persistent", expressing characteristics of a specific component
that are independent from the bean id, which may be auto-generated in case
of an anonymous bean definition like the one in the preceding
example.</para>
<para>Qualifiers also apply to typed collections, as discussed above, for
example, to <literal>Set&lt;MovieCatalog&gt;</literal>. In this case, all
matching beans according to the declared qualifiers are injected as a
collection. This implies that qualifiers do not have to be unique; they
rather simply constitute filtering criteria. For example, you can define
multiple <classname>MovieCatalog</classname> beans with the same qualifier
value "action"; all of which would be injected into a
<literal>Set&lt;MovieCatalog&gt;</literal> annotated with
<literal>@Qualifier("action")</literal>.</para>
<tip>
<para>If you intend to express annotation-driven injection by name, do not
primarily use <interfacename>@Autowired</interfacename>, even if is
technically capable of referring to a bean name through
<interfacename>@Qualifier</interfacename> values. Instead, use the
JSR-250 <interfacename>@Resource</interfacename> annotation, which is
semantically defined to identify a specific target component by its
unique name, with the declared type being irrelevant for the matching
process.</para>
<para>As a specific consequence of this semantic difference, beans that
are themselves defined as a collection or map type cannot be injected
through <interfacename>@Autowired</interfacename>, because type matching
is not properly applicable to them. Use
<interfacename>@Resource</interfacename> for such beans, referring to
the specific collection or map bean by unique name.</para>
<para><interfacename>@Autowired</interfacename> applies to fields,
constructors, and multi-argument methods, allowing for narrowing through
qualifier annotations at the parameter level. By contrast,
<interfacename>@Resource</interfacename> is supported only for fields
and bean property setter methods with a single argument. As a
consequence, stick with qualifiers if your injection target is a
constructor or a multi-argument method.</para>
</tip>
<para>You can create your own custom qualifier annotations. Simply define an
annotation and provide the <interfacename>@Qualifier</interfacename>
annotation within your definition:</para>
<note>
<para>You can use JSR 330's <interfacename>@Qualifier
</interfacename>annotation in the manner described below in place of
Spring's <interfacename>@Qualifier</interfacename> annotation. This
behavior is enabled automatically if you have the JSR 330 jar on the
classpath.</para>
</note>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
<emphasis role="bold">@Qualifier</emphasis>
public @interface Genre {
String value();
}</programlisting>
<para>Then you can provide the custom qualifier on autowired fields and
parameters:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Genre("Action")</emphasis>
private MovieCatalog actionCatalog;
private MovieCatalog comedyCatalog;
@Autowired
public void setComedyCatalog(<emphasis role="bold">@Genre("Comedy")</emphasis> MovieCatalog comedyCatalog) {
this.comedyCatalog = comedyCatalog;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Next, provide the information for the candidate bean definitions. You
can add <literal>&lt;qualifier/&gt;</literal> tags as sub-elements of the
<literal>&lt;bean/&gt;</literal> tag and then specify the
<literal>type</literal> and <literal>value</literal> to match your custom
qualifier annotations. The type is matched against the fully-qualified
class name of the annotation. Or, as a convenience if no risk of
conflicting names exists, you can use the short class name. Both
approaches are demonstrated in the following example.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="Genre" value="Action"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="example.Genre" value="Comedy"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean id="movieRecommender" class="example.MovieRecommender"/&gt;
&lt;/beans&gt;
</programlisting>
<para>In <xref linkend="beans-classpath-scanning"/>, you will see an
annotation-based alternative to providing the qualifier metadata in XML.
Specifically, see <xref linkend="beans-scanning-qualifiers"/>.</para>
<para>In some cases, it may be sufficient to use an annotation without a
value. This may be useful when the annotation serves a more generic
purpose and can be applied across several different types of dependencies.
For example, you may provide an <emphasis>offline</emphasis> catalog that
would be searched when no Internet connection is available. First define
the simple annotation:</para>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}</programlisting>
<para>Then add the annotation to the field or property to be
autowired:</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
<emphasis role="bold">@Offline</emphasis>
private MovieCatalog offlineCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Now the bean definition only needs a qualifier
<literal>type</literal>:</para>
<programlisting language="xml">&lt;bean class="example.SimpleMovieCatalog"&gt;
<emphasis role="bold">&lt;qualifier type="Offline"/&gt;</emphasis>
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;</programlisting>
<para>You can also define custom qualifier annotations that accept named
attributes in addition to or instead of the simple
<literal>value</literal> attribute. If multiple attribute values are then
specified on a field or parameter to be autowired, a bean definition must
match <emphasis>all</emphasis> such attribute values to be considered an
autowire candidate. As an example, consider the following annotation
definition:</para>
<programlisting language="java">@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
String genre();
Format format();
}</programlisting>
<para>In this case <literal>Format</literal> is an enum:</para>
<programlisting language="java">public enum Format {
VHS, DVD, BLURAY
}</programlisting>
<para>The fields to be autowired are annotated with the custom qualifier and
include values for both attributes: <literal>genre</literal> and
<literal>format</literal>.</para>
<programlisting language="java">public class MovieRecommender {
@Autowired
@MovieQualifier(format=Format.VHS, genre="Action")
private MovieCatalog actionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS, genre="Comedy")
private MovieCatalog comedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD, genre="Action")
private MovieCatalog actionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY, genre="Comedy")
private MovieCatalog comedyBluRayCatalog;
<lineannotation>// ...</lineannotation>
}</programlisting>
<para>Finally, the bean definitions should contain matching qualifier
values. This example also demonstrates that bean <emphasis>meta</emphasis>
attributes may be used instead of the
<literal>&lt;qualifier/&gt;</literal> sub-elements. If available, the
<literal>&lt;qualifier/&gt;</literal> and its attributes take precedence,
but the autowiring mechanism falls back on the values provided within the
<literal>&lt;meta/&gt;</literal> tags if no such qualifier is present, as
in the last two bean definitions in the following example.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;context:annotation-config/&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;qualifier type="MovieQualifier"&gt;
&lt;attribute key="format" value="VHS"/&gt;
&lt;attribute key="genre" value="Action"/&gt;
&lt;/qualifier&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;qualifier type="MovieQualifier"&gt;
&lt;attribute key="format" value="VHS"/&gt;
&lt;attribute key="genre" value="Comedy"/&gt;
&lt;/qualifier&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;meta key="format" value="DVD"/&gt;
&lt;meta key="genre" value="Action"/&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;bean class="example.SimpleMovieCatalog"&gt;
&lt;meta key="format" value="BLURAY"/&gt;
&lt;meta key="genre" value="Comedy"/&gt;
<lineannotation>&lt;!-- inject any dependencies required by this bean --&gt;</lineannotation>
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
</section>
<section id="beans-custom-autowire-configurer">
<title><classname>CustomAutowireConfigurer</classname></title>
<para>The <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"
><classname>CustomAutowireConfigurer</classname></ulink> is a
<interfacename>BeanFactoryPostProcessor</interfacename> that enables you
to register your own custom qualifier annotation types even if they are
not annotated with Spring's <interfacename>@Qualifier</interfacename>
annotation.</para>
<programlisting language="xml">&lt;bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer"&gt;
&lt;property name="customQualifierTypes"&gt;
&lt;set&gt;
&lt;value&gt;example.CustomQualifier&lt;/value&gt;
&lt;/set&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>The particular implementation of
<interfacename>AutowireCandidateResolver</interfacename> that is activated
for the application context depends on the Java version. In versions
earlier than Java 5, the qualifier annotations are not supported, and
therefore autowire candidates are solely determined by the
<literal>autowire-candidate</literal> value of each bean definition as
well as by any <literal>default-autowire-candidates</literal> pattern(s)
available on the <literal>&lt;beans/&gt;</literal> element. In Java 5 or
later, the presence of <interfacename>@Qualifier</interfacename>
annotations and any custom annotations registered with the
<classname>CustomAutowireConfigurer</classname> will also play a
role.</para>
<para>Regardless of the Java version, when multiple beans qualify as
autowire candidates, the determination of a "primary" candidate is the
same: if exactly one bean definition among the candidates has a
<literal>primary</literal> attribute set to <literal>true</literal>, it
will be selected.</para>
</section>
<section id="beans-resource-annotation">
<title><interfacename>@Resource</interfacename></title>
<para>Spring also supports injection using the JSR-250
<interfacename>@Resource</interfacename> annotation on fields or bean
property setter methods. This is a common pattern in Java EE 5 and 6, for
example in JSF 1.2 managed beans or JAX-WS 2.0 endpoints. Spring supports
this pattern for Spring-managed objects as well.</para>
<para><interfacename>@Resource</interfacename> takes a name attribute, and
by default Spring interprets that value as the bean name to be injected.
In other words, it follows <emphasis>by-name</emphasis> semantics, as
demonstrated in this example:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
<emphasis role="bold">@Resource(name="myMovieFinder")</emphasis>
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<para>If no name is specified explicitly, the default name is derived from
the field name or setter method. In case of a field, it takes the field
name; in case of a setter method, it takes the bean property name. So the
following example is going to have the bean with name "movieFinder"
injected into its setter method:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
<emphasis role="bold">@Resource</emphasis>
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<note>
<para>The name provided with the annotation is resolved as a bean name by
the <interfacename>ApplicationContext</interfacename> of which the
<classname>CommonAnnotationBeanPostProcessor</classname> is aware. The
names can be resolved through JNDI if you configure Spring's <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"
><classname>SimpleJndiBeanFactory</classname></ulink> explicitly.
However, it is recommended that you rely on the default behavior and
simply use Spring's JNDI lookup capabilities to preserve the level of
indirection.</para>
</note>
<para>In the exclusive case of <interfacename>@Resource</interfacename>
usage with no explicit name specified, and similar to
<interfacename>@Autowired</interfacename>,
<interfacename>@Resource</interfacename> finds a primary type match
instead of a specific named bean and resolves well-known resolvable
dependencies: the
<interfacename>BeanFactory</interfacename><interfacename>,
ApplicationContext,</interfacename><interfacename> ResourceLoader,
ApplicationEventPublisher</interfacename>, and
<interfacename>MessageSource</interfacename> interfaces.</para>
<para>Thus in the following example, the
<literal>customerPreferenceDao</literal> field first looks for a bean
named customerPreferenceDao, then falls back to a primary type match for
the type <classname>CustomerPreferenceDao</classname>. The "context" field
is injected based on the known resolvable dependency type
<interfacename>ApplicationContext</interfacename>.</para>
<programlisting language="java">public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</section>
<section id="beans-postconstruct-and-predestroy-annotations">
<title><interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename></title>
<para>The <classname>CommonAnnotationBeanPostProcessor</classname> not only
recognizes the <interfacename>@Resource</interfacename> annotation but
also the JSR-250 <emphasis>lifecycle</emphasis> annotations. Introduced in
Spring 2.5, the support for these annotations offers yet another
alternative to those described in <link
linkend="beans-factory-lifecycle-initializingbean">initialization
callbacks</link> and <link
linkend="beans-factory-lifecycle-disposablebean">destruction
callbacks</link>. Provided that the
<classname>CommonAnnotationBeanPostProcessor</classname> is registered
within the Spring <interfacename>ApplicationContext</interfacename>, a
method carrying one of these annotations is invoked at the same point in
the lifecycle as the corresponding Spring lifecycle interface method or
explicitly declared callback method. In the example below, the cache will
be pre-populated upon initialization and cleared upon destruction.</para>
<programlisting language="java">public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
<lineannotation>// populates the movie cache upon initialization...</lineannotation>
}
@PreDestroy
public void clearMovieCache() {
<lineannotation>// clears the movie cache upon destruction...</lineannotation>
}
}</programlisting>
<note>
<para>For details about the effects of combining various lifecycle
mechanisms, see <xref linkend="beans-factory-lifecycle-combined-effects"
/>.</para>
</note>
</section>
</section>

View File

@ -0,0 +1,510 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-classpath-scanning">
<title>Classpath scanning and managed components</title>
<!-- MLP: Beverly to review paragraph -->
<para>Most examples foo bar in this chapter use XML to specify the
configuration metadata that produces each
<interfacename>BeanDefinition</interfacename> within the Spring container.
The previous section (<xref linkend="beans-annotation-config"/>)
demonstrates how to provide a lot of the configuration metadata through
source-level annotations. Even in those examples, however, the "base" bean
definitions are explicitly defined in the XML file, while the annotations
only drive the dependency injection. This section describes an option for
implicitly detecting the <emphasis>candidate components</emphasis> by
scanning the classpath. Candidate components are classes that match against
a filter criteria and have a corresponding bean definition registered with
the container. This removes the need to use XML to perform bean
registration, instead you can use annotations (for example @Component),
AspectJ type expressions, or your own custom filter criteria to select which
classes will have bean definitions registered with the container.</para>
<note>
<para>Starting with Spring 3.0, many features provided by the <ulink
url="http://www.springsource.org/javaconfig">Spring JavaConfig
project</ulink> are part of the core Spring Framework. This allows you to
define beans using Java rather than using the traditional XML files. Take
a look at the <interfacename>@Configuration</interfacename>,
<interfacename>@Bean</interfacename>,
<interfacename>@Import</interfacename>, and
<interfacename>@DependsOn</interfacename> annotations for examples of how
to use these new features.</para>
</note>
<section id="beans-stereotype-annotations">
<title><interfacename>@Component</interfacename> and further stereotype
annotations</title>
<para>In Spring 2.0 and later, the
<interfacename>@Repository</interfacename> annotation is a marker for any
class that fulfills the role or <emphasis>stereotype</emphasis> (also
known as Data Access Object or DAO) of a repository. Among the uses of
this marker is the automatic translation of exceptions as described in
<xref linkend="orm-exception-translation"/>.</para>
<para>Spring 2.5 introduces further stereotype annotations:
<interfacename>@Component</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename>.
<interfacename>@Component</interfacename> is a generic stereotype for any
Spring-managed component. <interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename> are specializations of
<interfacename>@Component</interfacename> for more specific use cases, for
example, in the persistence, service, and presentation layers,
respectively. Therefore, you can annotate your component classes with
<interfacename>@Component</interfacename>, but by annotating them with
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, or
<interfacename>@Controller</interfacename> instead, your classes are more
properly suited for processing by tools or associating with aspects. For
example, these stereotype annotations make ideal targets for pointcuts. It
is also possible that <interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename> may carry additional semantics
in future releases of the Spring Framework. Thus, if you are choosing
between using <interfacename>@Component</interfacename> or
<interfacename>@Service</interfacename> for your service layer,
<interfacename>@Service</interfacename> is clearly the better choice.
Similarly, as stated above, <interfacename>@Repository</interfacename> is
already supported as a marker for automatic exception translation in your
persistence layer.</para>
</section>
<section id="beans-scanning-autodetection">
<title>Automatically detecting classes and registering bean
definitions</title>
<para>Spring can automatically detect stereotyped classes and register
corresponding <interfacename>BeanDefinition</interfacename>s with the
<interfacename>ApplicationContext</interfacename>. For example, the
following two classes are eligible for such autodetection:</para>
<programlisting language="java">@Service
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}</programlisting>
<programlisting language="java">@Repository
public class JpaMovieFinder implements MovieFinder {
<lineannotation>// implementation elided for clarity</lineannotation>
}</programlisting>
<para>To autodetect these classes and register the corresponding beans, you
need to include the following element in XML, where the base-package
element is a common parent package for the two classes. (Alternatively,
you can specify a comma-separated list that includes the parent package of
each class.)</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;context:component-scan base-package="org.example"/&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do <emphasis>not</emphasis> activate the
files-only switch of the JAR task.</para>
</note>
<para>Furthermore, the
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> are both
included implicitly when you use the component-scan element. That means
that the two components are autodetected <emphasis>and</emphasis> wired
together - all without any bean configuration metadata provided in
XML.</para>
<note>
<para>You can disable the registration of
<interfacename>AutowiredAnnotationBeanPostProcessor</interfacename> and
<interfacename>CommonAnnotationBeanPostProcessor</interfacename> by
including the <emphasis>annotation-config</emphasis> attribute with a
value of false.</para>
</note>
<!--
<note>
<para>In Spring 3.0 RC1 you can use JSR 330's
<interfacename>@Named</interfacename> annotation in place of
stereotpye annotations and they will be automatically detected during
component-scanning. The value of the
<interfacename>@Named</interfacename> property will be used as the
Bean Name. At this time Spring defaults for bean scope will be applied
when using @Named. This behavior as well as mapping of JSR 330 and JSR
299 scopes is planned for Spring 3.0 GA assuming the JSRs are stable
at that time.</para>
</note>
-->
</section>
<section id="beans-scanning-filters">
<title>Using filters to customize scanning</title>
<para>By default, classes annotated with
<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>,
<interfacename>@Controller</interfacename>, or a custom annotation that
itself is annotated with <interfacename>@Component</interfacename> are the
only detected candidate components. However, you can modify and extend
this behavior simply by applying custom filters. Add them as
<emphasis>include-filter</emphasis> or <emphasis>exclude-filter</emphasis>
sub-elements of the <literal>component-scan</literal> element. Each filter
element requires the <literal>type</literal> and
<literal>expression</literal> attributes. The following table describes
the filtering options.</para>
<table id="beans-scanning-filters-tbl">
<title>Filter Types</title>
<tgroup cols="3">
<colspec colname="c1" colwidth="1*"/>
<colspec colname="c2" colwidth="3*"/>
<colspec colname="c" colwidth="4*"/>
<thead>
<row>
<entry>Filter Type</entry>
<entry>Example Expression</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>annotation</entry>
<entry><literal>org.example.SomeAnnotation</literal></entry>
<entry>An annotation to be present at the type level in target
components.</entry>
</row>
<row>
<entry>assignable</entry>
<entry><literal>org.example.SomeClass</literal></entry>
<entry>A class (or interface) that the target components are
assignable to (extend/implement).</entry>
</row>
<row>
<entry>aspectj</entry>
<entry><literal>org.example..*Service+</literal></entry>
<entry>An AspectJ type expression to be matched by the target
components.</entry>
</row>
<row>
<entry>regex</entry>
<entry><literal>org\.example\.Default.*</literal></entry>
<entry>A regex expression to be matched by the target components
class names.</entry>
</row>
<row>
<entry>custom</entry>
<entry><literal>org.example.MyTypeFilter</literal></entry>
<entry>A custom implementation of the
<interfacename>org.springframework.core.type
.TypeFilter</interfacename> interface.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>The following example shows the XML configuration ignoring all
<interfacename>@Repository</interfacename> annotations and using "stub"
repositories instead.</para>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"&gt;
&lt;context:include-filter type="regex" expression=".*Stub.*Repository"/&gt;
&lt;context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository"/&gt;
&lt;/context:component-scan&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>You can also disable the default filters by providing
<emphasis>use-default-filters="false"</emphasis> as an attribute of the
&lt;component-scan/&gt; element. This will in effect disable automatic
detection of classes annotated with
<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, or
<interfacename>@Controller</interfacename>.</para>
</note>
</section>
<section id="beans-factorybeans-annotations">
<title>Defining bean metadata within components</title>
<para>Spring components can also contribute bean definition metadata to the
container. You do this with the same <literal>@Bean</literal> annotation
used to define bean metadata within <literal>@Configuration</literal>
annotated classes. Here is a simple example:</para>
<programlisting language="java">@Component
public class FactoryMethodComponent {
@Bean @Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
public void doWork() {
// Component method implementation omitted
}
}</programlisting>
<para>This class is a Spring component that has application-specific code
contained in its <methodname>doWork()</methodname> method. However, it
also contributes a bean definition that has a factory method referring to
the method <methodname>publicInstance()</methodname>. The
<literal>@Bean</literal> annotation identifies the factory method and
other bean definition properties, such as a qualifier value through the
<classname>@Qualifier</classname> annotation. Other method level
annotations that can be specified are <literal>@Scope</literal>,
<literal>@Lazy</literal>, and custom qualifier annotations. Autowired
fields and methods are supported as previously discussed, with additional
support for autowiring of <literal>@Bean</literal> methods:</para>
<programlisting language="java">@Component
public class FactoryMethodComponent {
private static int i;
@Bean @Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
// use of a custom qualifier and autowiring of method parameters
@Bean @BeanAge(1)
protected TestBean protectedInstance(@Qualifier("public") TestBean spouse,
@Value("#{privateInstance.age}") String country) {
TestBean tb = new TestBean("protectedInstance", 1);
tb.setSpouse(tb);
tb.setCountry(country);
return tb;
}
@Bean @Scope(BeanDefinition.SCOPE_SINGLETON)
private TestBean privateInstance() {
return new TestBean("privateInstance", i++);
}
@Bean @Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public TestBean requestScopedInstance() {
return new TestBean("requestScopedInstance", 3);
}
}
</programlisting>
<para>The example autowires the <classname>String</classname> method
parameter <literal>country</literal> to the value of the
<literal>Age</literal> property on another bean named
<literal>privateInstance</literal>. A Spring Expression Language element
defines the value of the property through the notation <literal>#{
&lt;expression&gt; }</literal>. For <literal>@Value</literal> annotations,
an expression resolver is preconfigured to look for bean names when
resolving expression text.</para>
<para>The <literal>@Bean</literal> methods in a Spring component are
processed differently than their counterparts inside a Spring
<literal>@Configuration</literal> class. The difference is that
<literal>@Component</literal> classes are not enhanced with CGLIB to
intercept the invocation of methods and fields. CGLIB proxying is the
means by which invoking methods or fields within
<literal>@Configuration</literal> classes <literal>@Bean</literal> methods
create bean metadata references to collaborating objects. Methods are
<emphasis>not</emphasis> invoked with normal Java semantics. In contrast,
calling a method or field within a <literal>@Component</literal> classes
<literal>@Bean</literal> method <emphasis>has</emphasis> standard Java
semantics.</para>
</section>
<section id="beans-scanning-name-generator">
<title>Naming autodetected components</title>
<para>When a component is autodetected as part of the scanning process, its
bean name is generated by the
<interfacename>BeanNameGenerator</interfacename> strategy known to that
scanner. By default, any Spring stereotype annotation
(<interfacename>@Component</interfacename>,
<interfacename>@Repository</interfacename>,
<interfacename>@Service</interfacename>, and
<interfacename>@Controller</interfacename>) that contains a
<literal>name</literal> value will thereby provide that name to the
corresponding bean definition.</para>
<note>
<para>JSR 330's @Named annotation can be used as a means to both detect
components and to provide them with a name. This behavior is enabled
automatically if you have the JSR 330 JAR on the classpath.</para>
</note>
<para>If such an annotation contains no <literal>name</literal> value or for
any other detected component (such as those discovered by custom filters),
the default bean name generator returns the uncapitalized non-qualified
class name. For example, if the following two components were detected,
the names would be myMovieLister and movieFinderImpl:</para>
<programlisting language="java">@Service("myMovieLister")
public class SimpleMovieLister {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Repository
public class MovieFinderImpl implements MovieFinder {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>If you do not want to rely on the default bean-naming strategy, you
can provide a custom bean-naming strategy. First, implement the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/support/BeanNameGenerator.html"
><interfacename>BeanNameGenerator</interfacename></ulink> interface, and
be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:</para>
</note>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
name-generator="org.example.MyNameGenerator" /&gt;
&lt;/beans&gt;</programlisting>
<para>As a general rule, consider specifying the name with the annotation
whenever other components may be making explicit references to it. On the
other hand, the auto-generated names are adequate whenever the container
is responsible for wiring.</para>
</section>
<section id="beans-scanning-scope-resolver">
<title>Providing a scope for autodetected components</title>
<para>As with Spring-managed components in general, the default and most
common scope for autodetected components is singleton. However, sometimes
you need other scopes, which Spring 2.5 provides with a new
<interfacename>@Scope</interfacename> annotation. Simply provide the name
of the scope within the annotation:</para>
<programlisting language="java">@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>To provide a custom strategy for scope resolution rather than
relying on the annotation-based approach, implement the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html"
><interfacename>ScopeMetadataResolver</interfacename></ulink> interface,
and be sure to include a default no-arg constructor. Then, provide the
fully-qualified class name when configuring the scanner:</para>
</note>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
scope-resolver="org.example.MyScopeResolver" /&gt;
&lt;/beans&gt;</programlisting>
<para>When using certain non-singleton scopes, it may be necessary to
generate proxies for the scoped objects. The reasoning is described in
<xref linkend="beans-factory-scopes-other-injection"/>. For this purpose,
a <emphasis>scoped-proxy</emphasis> attribute is available on the
component-scan element. The three possible values are: no, interfaces, and
targetClass. For example, the following configuration will result in
standard JDK dynamic proxies:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"
scoped-proxy="interfaces" /&gt;
&lt;/beans&gt;</programlisting>
</section>
<section id="beans-scanning-qualifiers">
<title>Providing qualifier metadata with annotations</title>
<para>The <interfacename>@Qualifier</interfacename> annotation is discussed
in <xref linkend="beans-autowired-annotation-qualifiers"/>. The examples
in that section demonstrate the use of the
<interfacename>@Qualifier</interfacename> annotation and custom qualifier
annotations to provide fine-grained control when you resolve autowire
candidates. Because those examples were based on XML bean definitions, the
qualifier metadata was provided on the candidate bean definitions using
the <literal>qualifier</literal> or <literal>meta</literal> sub-elements
of the <literal>bean</literal> element in the XML. When relying upon
classpath scanning for autodetection of components, you provide the
qualifier metadata with type-level annotations on the candidate class. The
following three examples demonstrate this technique:</para>
<programlisting language="java">@Component
<emphasis role="bold">@Qualifier("Action")</emphasis>
public class ActionMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Component
<emphasis role="bold">@Genre("Action")</emphasis>
public class ActionMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<programlisting language="java">@Component
<emphasis role="bold">@Offline</emphasis>
public class CachingMovieCatalog implements MovieCatalog {
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>As with most annotation-based alternatives, keep in mind that the
annotation metadata is bound to the class definition itself, while the
use of XML allows for multiple beans <emphasis>of the same
type</emphasis> to provide variations in their qualifier metadata,
because that metadata is provided per-instance rather than
per-class.</para>
</note>
</section>
</section>

View File

@ -0,0 +1,663 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="context-introduction">
<title>Additional Capabilities of the
<interfacename>ApplicationContext</interfacename></title>
<!-- MLP: Beverly to review paragraph and list -->
<para>As was discussed in the chapter introduction, the
<literal>org.springframework.beans.factory</literal> package provides basic
functionality for managing and manipulating beans, including in a
programmatic way. The <literal>org.springframework.context</literal> package
adds the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/ApplicationContext.html"
><interfacename>ApplicationContext</interfacename></ulink> interface, which
extends the <interfacename>BeanFactory</interfacename> interface, in
addition to extending other interfaces to provide additional functionality
in a more <emphasis>application framework-oriented style</emphasis>. Many
people use the <interfacename>ApplicationContext</interfacename> in a
completely declarative fashion, not even creating it programmatically, but
instead relying on support classes such as
<classname>ContextLoader</classname> to automatically instantiate an
<interfacename>ApplicationContext</interfacename> as part of the normal
startup process of a J2EE web application.</para>
<para>To enhance <interfacename>BeanFactory</interfacename> functionality in a
more framework-oriented style the context package also provides the
following functionality:</para>
<itemizedlist>
<listitem>
<para><emphasis>Access to messages in i18n-style</emphasis>, through the
<interfacename>MessageSource</interfacename> interface.</para>
</listitem>
<listitem>
<para><emphasis>Access to resources</emphasis>, such as URLs and files,
through the <interfacename>ResourceLoader</interfacename>
interface.</para>
</listitem>
<listitem>
<para><emphasis>Event publication</emphasis> to beans implementing the
<interfacename>ApplicationListener</interfacename> interface, through
the use of the <interfacename>ApplicationEventPublisher</interfacename>
interface.</para>
</listitem>
<listitem>
<para><emphasis>Loading of multiple (hierarchical) contexts</emphasis>,
allowing each to be focused on one particular layer, such as the web
layer of an application, through the
<interfacename>HierarchicalBeanFactory</interfacename> interface.</para>
</listitem>
</itemizedlist>
<section id="context-functionality-messagesource">
<title>Internationalization using
<interfacename>MessageSource</interfacename></title>
<!-- MLP: Beverly to review this paragraph -->
<para>The <interfacename>ApplicationContext</interfacename> interface
extends an interface called <interfacename>MessageSource</interfacename>,
and therefore provides internationalization (i18n) functionality. Spring
also provides the interface
<classname>HierarchicalMessageSource</classname>, which can resolve
messages hierarchically. Together these interfaces provide the foundation
upon which Spring effects message resolution. The methods defined on these
interfaces include:</para>
<itemizedlist>
<listitem>
<para><methodname>String getMessage(String code, Object[] args, String
default, Locale loc)</methodname>: The basic method used to retrieve a
message from the <interfacename>MessageSource</interfacename>. When no
message is found for the specified locale, the default message is
used. Any arguments passed in become replacement values, using the
<interfacename>MessageFormat</interfacename> functionality provided by
the standard library.</para>
</listitem>
<listitem>
<para><methodname>String getMessage(String code, Object[] args, Locale
loc)</methodname>: Essentially the same as the previous method, but
with one difference: no default message can be specified; if the
message cannot be found, a
<classname>NoSuchMessageException</classname> is thrown.</para>
</listitem>
<listitem>
<para><methodname>String getMessage(MessageSourceResolvable resolvable,
Locale locale)</methodname>: All properties used in the preceding
methods are also wrapped in a class named
<interfacename>MessageSourceResolvable</interfacename>, which you can
use with this method.</para>
</listitem>
</itemizedlist>
<para>When an <interfacename>ApplicationContext</interfacename> is loaded,
it automatically searches for a
<interfacename>MessageSource</interfacename> bean defined in the context.
The bean must have the name <literal>messageSource</literal>. If such a
bean is found, all calls to the preceding methods are delegated to the
message source. If no message source is found, the
<interfacename>ApplicationContext</interfacename> attempts to find a
parent containing a bean with the same name. If it does, it uses that bean
as the <interfacename>MessageSource</interfacename>. If the
<interfacename>ApplicationContext</interfacename> cannot find any source
for messages, an empty <classname>DelegatingMessageSource</classname> is
instantiated in order to be able to accept calls to the methods defined
above.</para>
<para>Spring provides two <interfacename>MessageSource</interfacename>
implementations, <classname>ResourceBundleMessageSource</classname> and
<classname>StaticMessageSource</classname>. Both implement
<interfacename>HierarchicalMessageSource</interfacename> in order to do
nested messaging. The <classname>StaticMessageSource</classname> is rarely
used but provides programmatic ways to add messages to the source. The
<classname>ResourceBundleMessageSource</classname> is shown in the
following example:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"&gt;
&lt;property name="basenames"&gt;
&lt;list&gt;
&lt;value&gt;format&lt;/value&gt;
&lt;value&gt;exceptions&lt;/value&gt;
&lt;value&gt;windows&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<para>In the example it is assumed you have three resource bundles defined
in your classpath called <literal>format</literal>,
<literal>exceptions</literal> and <literal>windows</literal>. Any request
to resolve a message will be handled in the JDK standard way of resolving
messages through ResourceBundles. For the purposes of the example, assume
the contents of two of the above resource bundle files are...</para>
<programlisting language="java"><lineannotation># in format.properties</lineannotation>
message=Alligators rock!</programlisting>
<programlisting language="java"><lineannotation># in exceptions.properties</lineannotation>
argument.required=The '{0}' argument is required.</programlisting>
<para>A program to execute the <classname>MessageSource</classname>
functionality is shown in the next example. Remember that all
<classname>ApplicationContext</classname> implementations are also
<classname>MessageSource</classname> implementations and so can be cast to
the <classname>MessageSource</classname> interface.</para>
<programlisting language="java">public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}</programlisting>
<para>The resulting output from the above program will be...</para>
<programlisting>Alligators rock!</programlisting>
<para>So to summarize, the <classname>MessageSource</classname> is defined
in a file called <literal>beans.xml</literal>, which exists at the root of
your classpath. The <literal>messageSource</literal> bean definition
refers to a number of resource bundles through its
<literal>basenames</literal> property. The three files that are passed in
the list to the <literal>basenames</literal> property exist as files at
the root of your classpath and are called
<literal>format.properties</literal>,
<literal>exceptions.properties</literal>, and
<literal>windows.properties</literal> respectively.</para>
<para>The next example shows arguments passed to the message lookup; these
arguments will be converted into Strings and inserted into placeholders in
the lookup message.</para>
<programlisting language="xml">&lt;beans&gt;
<lineannotation>&lt;!-- this <interfacename>MessageSource</interfacename> is being used in a web application --&gt;</lineannotation>
&lt;bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"&gt;
&lt;property name="basename" value="test-messages"/&gt;
&lt;/bean&gt;
<lineannotation>&lt;!-- lets inject the above <interfacename>MessageSource</interfacename> into this POJO --&gt;</lineannotation>
&lt;bean id="example" class="com.foo.Example"&gt;
&lt;property name="messages" ref="messageSource"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class Example {
private MessageSource messages;
public void setMessages(MessageSource messages) {
this.messages = messages;
}
public void execute() {
String message = this.messages.getMessage("argument.required",
new Object [] {"userDao"}, "Required", null);
System.out.println(message);
}
}</programlisting>
<para>The resulting output from the invocation of the
<methodname>execute()</methodname> method will be...</para>
<programlisting>The userDao argument is required.</programlisting>
<para>With regard to internationalization (i18n), Spring's various
<classname>MessageResource</classname> implementations follow the same
locale resolution and fallback rules as the standard JDK
<classname>ResourceBundle</classname>. In short, and continuing with the
example <literal>messageSource</literal> defined previously, if you want
to resolve messages against the British (en-GB) locale, you would create
files called <literal>format_en_GB.properties</literal>,
<literal>exceptions_en_GB.properties</literal>, and
<literal>windows_en_GB.properties</literal> respectively.</para>
<para>Typically, locale resolution is managed by the surrounding environment
of the application. In this example, the locale against which (British)
messages will be resolved is specified manually.</para>
<programlisting><lineannotation># in exceptions_en_GB.properties</lineannotation>
argument.required=Ebagum lad, the '{0}' argument is required, I say, required.</programlisting>
<programlisting language="java">public static void main(final String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("argument.required",
new Object [] {"userDao"}, "Required", Locale.UK);
System.out.println(message);
}</programlisting>
<para>The resulting output from the running of the above program will
be...</para>
<programlisting>Ebagum lad, the 'userDao' argument is required, I say, required.</programlisting>
<para>You can also use the <classname>MessageSourceAware</classname>
interface to acquire a reference to any
<classname>MessageSource</classname> that has been defined. Any bean that
is defined in an <classname>ApplicationContext</classname> that implements
the <classname>MessageSourceAware</classname> interface is injected with
the application context's <classname>MessageSource</classname> when the
bean is created and configured.</para>
<note>
<para><emphasis>As an alternative to
<classname>ResourceBundleMessageSource</classname>, Spring provides a
<classname>ReloadableResourceBundleMessageSource</classname> class. This
variant supports the same bundle file format but is more flexible than
the standard JDK based
<classname>ResourceBundleMessageSource</classname>
implementation.</emphasis> In particular, it allows for reading files
from any Spring resource location (not just from the classpath) and
supports hot reloading of bundle property files (while efficiently
caching them in between). Check out the
<classname>ReloadableResourceBundleMessageSource</classname> javadoc for
details.</para>
</note>
</section>
<section id="context-functionality-events">
<title>Standard and Custom Events</title>
<para>Event handling in the
<interfacename>ApplicationContext</interfacename> is provided through the
<classname>ApplicationEvent</classname> class and
<interfacename>ApplicationListener</interfacename> interface. If a bean
that implements the <interfacename>ApplicationListener</interfacename>
interface is deployed into the context, every time an
<classname>ApplicationEvent</classname> gets published to the
<interfacename>ApplicationContext</interfacename>, that bean is notified.
Essentially, this is the standard <emphasis>Observer</emphasis> design
pattern. Spring provides the following standard events:</para>
<table id="beans-ctx-events-tbl">
<title>Built-in Events</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="2*"/>
<colspec colname="c2" colwidth="5*"/>
<thead>
<row>
<entry>Event</entry>
<entry>Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>ContextRefreshedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is initialized
or refreshed, for example, using the
<methodname>refresh()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Initialized" here means that all beans are loaded,
post-processor beans are detected and activated, singletons are
pre-instantiated, and the
<interfacename>ApplicationContext</interfacename> object is ready
for use. As long as the context has not been closed, a refresh can
be triggered multiple times, provided that the chosen
<interfacename>ApplicationContext</interfacename> actually
supports such "hot" refreshes. For example,
<classname>XmlWebApplicationContext</classname> supports hot
refreshes, but <classname>GenericApplicationContext</classname>
does not.</entry>
</row>
<row>
<entry><classname>ContextStartedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is started,
using the <methodname>start()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Started" here means that all
<interfacename>Lifecycle</interfacename> beans receive an explicit
start signal. Typically this signal is used to restart beans after
an explicit stop, but it may also be used to start components that
have not been configured for autostart , for example, components
that have not already started on initialization.</entry>
</row>
<row>
<entry><classname>ContextStoppedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is stopped,
using the <methodname>stop()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Stopped" here means that all
<interfacename>Lifecycle</interfacename> beans receive an explicit
stop signal. A stopped context may be restarted through a
<methodname>start()</methodname> call.</entry>
</row>
<row>
<entry><classname>ContextClosedEvent</classname></entry>
<entry>Published when the
<interfacename>ApplicationContext</interfacename> is closed, using
the <methodname>close()</methodname> method on the
<interfacename>ConfigurableApplicationContext</interfacename>
interface. "Closed" here means that all singleton beans are
destroyed. A closed context reaches its end of life; it cannot be
refreshed or restarted.</entry>
</row>
<row>
<entry><classname>RequestHandledEvent</classname></entry>
<entry>A web-specific event telling all beans that an HTTP request
has been serviced. This event is published
<emphasis>after</emphasis> the request is complete. This event is
only applicable to web applications using Spring's
<classname>DispatcherServlet</classname>.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>You can also create and publish your own custom events. This example
demonstrates a simple class that extends Spring's
<classname>ApplicationEvent</classname> base class:</para>
<programlisting language="java">public class BlackListEvent extends ApplicationEvent {
private final String address;
private final String test;
public BlackListEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}
<lineannotation>// accessor and other methods...</lineannotation>
}</programlisting>
<para>To publish a custom <classname>ApplicationEvent</classname>, call the
<methodname>publishEvent()</methodname> method on an
<interfacename>ApplicationEventPublisher</interfacename>. Typically this
is done by creating a class that implements
<interfacename>ApplicationEventPublisherAware</interfacename> and
registering it as a Spring bean. The following example demonstrates such a
class:</para>
<programlisting language="java"><![CDATA[public class EmailService implements ApplicationEventPublisherAware {
private List<String> blackList;
private ApplicationEventPublisher publisher;
public void setBlackList(List<String> blackList) {
this.blackList = blackList;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String text) {
if (blackList.contains(address)) {
BlackListEvent event = new BlackListEvent(this, address, text);
publisher.publishEvent(event);
return;
}
]]><lineannotation>// send email...</lineannotation><![CDATA[
}
}]]></programlisting>
<para>At configuration time, the Spring container will detect that
<classname>EmailService</classname> implements
<interfacename>ApplicationEventPublisherAware</interfacename> and will
automatically call
<methodname>setApplicationEventPublisher()</methodname>. In reality, the
parameter passed in will be the Spring container itself; you're simply
interacting with the application context via its
<interfacename>ApplicationEventPublisher</interfacename> interface.</para>
<para>To receive the custom <classname>ApplicationEvent</classname>, create
a class that implements <interfacename>ApplicationListener</interfacename>
and register it as a Spring bean. The following example demonstrates such
a class:</para>
<programlisting language="java"><![CDATA[public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlackListEvent event) {
]]><lineannotation> // notify appropriate parties via notificationAddress...</lineannotation><![CDATA[
}
}]]></programlisting>
<para>Notice that <interfacename>ApplicationListener</interfacename> is
generically parameterized with the type of your custom event,
<classname>BlackListEvent</classname>. This means that the
<methodname>onApplicationEvent()</methodname> method can remain type-safe,
avoiding any need for downcasting. You may register as many event
listeners as you wish, but note that by default event listeners receive
events synchronously. This means the
<methodname>publishEvent()</methodname> method blocks until all listeners
have finished processing the event. One advantage of this synchronous and
single-threaded approach is that when a listener receives an event, it
operates inside the transaction context of the publisher if a transaction
context is available. If another strategy for event publication becomes
necessary, refer to the JavaDoc for Spring's
<interfacename>ApplicationEventMulticaster</interfacename>
interface.</para>
<para>The following example demonstrates the bean definitions used to
register and configure each of the classes above:</para>
<programlisting language="xml"><![CDATA[<bean id="emailService" class="example.EmailService">
<property name="blackList">
<list>
<value>black@list.org</value>
<value>white@list.org</value>
<value>john@doe.org</value>
</list>
</property>
</bean>
<bean id="blackListNotifier" class="example.BlackListNotifier">
<property name="notificationAddress" value="spam@list.org"/>
</bean>]]></programlisting>
<para>Putting it all together, when the <methodname>sendEmail()</methodname>
method of the <literal>emailService</literal> bean is called, if there are
any emails that should be blacklisted, a custom event of type
<classname>BlackListEvent</classname> is published. The
<literal>blackListNotifier</literal> bean is registered as an
<interfacename>ApplicationListener</interfacename> and thus receives the
<classname>BlackListEvent</classname>, at which point it can notify
appropriate parties.</para>
<note>
<para>Spring's eventing mechanism is designed for simple communication
between Spring beans within the same application context. However, for
more sophisticated enterprise integration needs, the
separately-maintained <ulink
url="http://springsource.org/spring-integration">Spring
Integration</ulink> project provides complete support for building
lightweight, <ulink url="http://www.enterpriseintegrationpatterns.com"
>pattern-oriented</ulink>, event-driven architectures that build upon
the well-known Spring programming model.</para>
</note>
</section>
<section id="context-functionality-resources">
<title>Convenient access to low-level resources</title>
<para>For optimal usage and understanding of application contexts, users
should generally familiarize themselves with Spring's
<interfacename>Resource</interfacename> abstraction, as described in the
chapter <xref linkend="resources"/>.</para>
<para>An application context is a
<interfacename>ResourceLoader</interfacename>, which can be used to load
<interfacename>Resource</interfacename>s. A
<interfacename>Resource</interfacename> is essentially a more feature rich
version of the JDK class <literal>java.net.URL</literal>, in fact, the
implementations of the <interfacename>Resource</interfacename> wrap an
instance of <literal>java.net.URL</literal> where appropriate. A
<interfacename>Resource</interfacename> can obtain low-level resources
from almost any location in a transparent fashion, including from the
classpath, a filesystem location, anywhere describable with a standard
URL, and some other variations. If the resource location string is a
simple path without any special prefixes, where those resources come from
is specific and appropriate to the actual application context type.</para>
<para>You can configure a bean deployed into the application context to
implement the special callback interface,
<interfacename>ResourceLoaderAware</interfacename>, to be automatically
called back at initialization time with the application context itself
passed in as the <interfacename>ResourceLoader</interfacename>. You can
also expose properties of type <interfacename>Resource</interfacename>, to
be used to access static resources; they will be injected into it like any
other properties. You can specify those
<interfacename>Resource</interfacename> properties as simple String paths,
and rely on a special JavaBean
<interfacename>PropertyEditor</interfacename> that is automatically
registered by the context, to convert those text strings to actual
<interfacename>Resource</interfacename> objects when the bean is
deployed.</para>
<para>The location path or paths supplied to an
<interfacename>ApplicationContext</interfacename> constructor are actually
resource strings, and in simple form are treated appropriately to the
specific context implementation.
<classname>ClassPathXmlApplicationContext</classname> treats a simple
location path as a classpath location. You can also use location paths
(resource strings) with special prefixes to force loading of definitions
from the classpath or a URL, regardless of the actual context type.</para>
</section>
<section id="context-create">
<title>Convenient <interfacename>ApplicationContext</interfacename>
instantiation for web applications</title>
<para>You can create <interfacename>ApplicationContext</interfacename>
instances declaratively by using, for example, a
<classname>ContextLoader</classname>. Of course you can also create
<interfacename>ApplicationContext</interfacename> instances
programmatically by using one of the
<interfacename>ApplicationContext</interfacename> implementations.</para>
<para>The <classname>ContextLoader</classname> mechanism comes in two
flavors: the <classname>ContextLoaderListener</classname> and the
<classname>ContextLoaderServlet</classname>. They have the same
functionality but differ in that the listener version is not reliable in
Servlet 2.3 containers. In the Servlet 2.4 specification, Servlet context
listeners must execute immediately after the Servlet context for the web
application is created and is available to service the first request (and
also when the Servlet context is about to be shut down). As such a Servlet
context listener is an ideal place to initialize the Spring
<interfacename>ApplicationContext</interfacename>. All things being equal,
you should probably prefer <classname>ContextLoaderListener</classname>;
for more information on compatibility, have a look at the Javadoc for the
<classname>ContextLoaderServlet</classname>.</para>
<para>You can register an <interfacename>ApplicationContext</interfacename>
using the <classname>ContextLoaderListener</classname> as follows:</para>
<programlisting language="xml">&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
<lineannotation>&lt;!-- or use the <classname>ContextLoaderServlet</classname> instead of the above listener</lineannotation><emphasis>
&lt;servlet&gt;
&lt;servlet-name&gt;context&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.context.ContextLoaderServlet&lt;/servlet-class&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
--</emphasis>&gt;</programlisting>
<para>The listener inspects the <literal>contextConfigLocation</literal>
parameter. If the parameter does not exist, the listener uses
<literal>/WEB-INF/applicationContext.xml</literal> as a default. When the
parameter <emphasis>does</emphasis> exist, the listener separates the
String by using predefined delimiters (comma, semicolon and whitespace)
and uses the values as locations where application contexts will be
searched. Ant-style path patterns are supported as well. Examples are
<literal>/WEB-INF/*Context.xml</literal> for all files with names ending
with "Context.xml", residing in the "WEB-INF" directory, and
<literal>/WEB-INF/**/*Context.xml</literal>, for all such files in any
subdirectory of "WEB-INF".</para>
<para>You can use <classname>ContextLoaderServlet</classname> instead of
<classname>ContextLoaderListener</classname>. The Servlet uses the
<literal>contextConfigLocation</literal> parameter just as the listener
does.</para>
</section>
<section>
<title>Deploying a Spring ApplicationContext as a J2EE RAR file</title>
<para>In Spring 2.5 and later, it is possible to deploy a Spring
ApplicationContext as a RAR file, encapsulating the context and all of its
required bean classes and library JARs in a J2EE RAR deployment unit. This
is the equivalent of bootstrapping a standalone ApplicationContext, just
hosted in J2EE environment, being able to access the J2EE servers
facilities. RAR deployment is a more natural alternative to scenario of
deploying a headless WAR file, in effect, a WAR file without any HTTP
entry points that is used only for bootstrapping a Spring
ApplicationContext in a J2EE environment.</para>
<para>RAR deployment is ideal for application contexts that do not need HTTP
entry points but rather consist only of message endpoints and scheduled
jobs. Beans in such a context can use application server resources such as
the JTA transaction manager and JNDI-bound JDBC DataSources and JMS
ConnectionFactory instances, and may also register with the platform's JMX
server - all through Spring's standard transaction management and JNDI and
JMX support facilities. Application components can also interact with the
application server's JCA WorkManager through Spring's
<interfacename>TaskExecutor</interfacename> abstraction.</para>
<para>Check out the JavaDoc of the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html"
>SpringContextResourceAdapter</ulink> class for the configuration details
involved in RAR deployment.</para>
<para><emphasis>For a simple deployment of a Spring ApplicationContext as a
J2EE RAR file:</emphasis> package all application classes into a RAR file,
which is a standard JAR file with a different file extension. Add all
required library JARs into the root of the RAR archive. Add a
"META-INF/ra.xml" deployment descriptor (as shown in
<classname>SpringContextResourceAdapter</classname>s JavaDoc) and the
corresponding Spring XML bean definition file(s) (typically
"META-INF/applicationContext.xml"), and drop the resulting RAR file into
your application server's deployment directory.</para>
<note>
<para>Such RAR deployment units are usually self-contained; they do not
expose components to the outside world, not even to other modules of the
same application. Interaction with a RAR-based ApplicationContext
usually occurs through JMS destinations that it shares with other
modules. A RAR-based ApplicationContext may also, for example, schedule
some jobs, reacting to new files in the file system (or the like). If it
needs to allow synchronous access from the outside, it could for example
export RMI endpoints, which of course may be used by other application
modules on the same machine.</para>
</note>
</section>
</section>

View File

@ -0,0 +1,665 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-nature">
<title>Customizing the nature of a bean</title>
<section id="beans-factory-lifecycle">
<title>Lifecycle callbacks</title>
<!-- MLP Beverly to review: Old Text: The Spring Framework provides several callback interfaces to
change the behavior of your bean in the container; they include -->
<para>To interact with the container's management of the bean lifecycle, you
can implement the Spring <interfacename>InitializingBean</interfacename>
and <interfacename>DisposableBean</interfacename> interfaces. The
container calls <methodname>afterPropertiesSet()</methodname> for the
former and <methodname>destroy()</methodname> for the latter to allow the
bean to perform certain actions upon initialization and destruction of
your beans. You can also achieve the same integration with the container
without coupling your classes to Spring interfaces through the use of
init-method and destroy method object definition metadata.</para>
<para>Internally, the Spring Framework uses
<interfacename>BeanPostProcessor</interfacename> implementations to
process any callback interfaces it can find and call the appropriate
methods. If you need custom features or other lifecycle behavior Spring
does not offer out-of-the-box, you can implement a
<interfacename>BeanPostProcessor</interfacename> yourself. For more
information, see <xref linkend="beans-factory-extension"/>.</para>
<para>In addition to the initialization and destruction callbacks,
Spring-managed objects may also implement the
<interfacename>Lifecycle</interfacename> interface so that those objects
can participate in the startup and shutdown process as driven by the
container's own lifecycle.</para>
<para>The lifecycle callback interfaces are described in this
section.</para>
<section id="beans-factory-lifecycle-initializingbean">
<title>Initialization callbacks</title>
<para>The
<interfacename>org.springframework.beans.factory.InitializingBean</interfacename>
interface allows a bean to perform initialization work after all
necessary properties on the bean have been set by the container. The
<interfacename>InitializingBean</interfacename> interface specifies a
single method:</para>
<programlisting language="java">void afterPropertiesSet() throws Exception;</programlisting>
<para>It is recommended that you do not use the
<interfacename>InitializingBean</interfacename> interface because it
unnecessarily couples the code to Spring. Alternatively, specify a POJO
initialization method. In the case of XML-based configuration metadata,
you use the <literal>init-method</literal> attribute to specify the name
of the method that has a void no-argument signature. For example, the
following definition:</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/&gt;</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">&lt;bean id="exampleInitBean" class="examples.AnotherExampleBean"/&gt;</programlisting>
<programlisting language="java">public class AnotherExampleBean implements InitializingBean {
public void afterPropertiesSet() {
<lineannotation>// do some initialization work</lineannotation>
}
}</programlisting>
<para>... but does not couple the code to Spring.</para>
</section>
<section id="beans-factory-lifecycle-disposablebean">
<title>Destruction callbacks</title>
<para>Implementing the
<interfacename>org.springframework.beans.factory.DisposableBean</interfacename>
interface allows a bean to get a callback when the container containing
it is destroyed. The <interfacename>DisposableBean</interfacename>
interface specifies a single method:</para>
<programlisting language="java">void destroy() throws Exception;</programlisting>
<para>It is recommended that you do not use the
<interfacename>DisposableBean</interfacename> callback interface because
it unnecessarily couples the code to Spring. Alternatively, specify a
generic method that is supported by bean definitions. With XML-based
configuration metadata, you use the <literal>destroy-method</literal>
attribute on the <literal>&lt;bean/&gt;</literal>. For example, the
following definition:</para>
<programlisting language="xml">&lt;bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/&gt;</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">&lt;bean id="exampleInitBean" class="examples.AnotherExampleBean"/&gt;</programlisting>
<programlisting language="java">public class AnotherExampleBean implements DisposableBean {
public void destroy() {
<lineannotation>// do some destruction work (like releasing pooled connections)</lineannotation>
}
}</programlisting>
<para>... but does not couple the code to Spring.</para>
</section>
<section id="beans-factory-lifecycle-default-init-destroy-methods">
<title>Default initialization and destroy methods</title>
<para>When you write initialization and destroy method callbacks that do
not use the Spring-specific
<interfacename>InitializingBean</interfacename> and
<interfacename>DisposableBean</interfacename> callback interfaces, you
typically write methods with names such as <literal>init()</literal>,
<literal>initialize()</literal>, <literal>dispose()</literal>, and so
on. Ideally, the names of such lifecycle callback methods are
standardized across a project so that all developers use the same method
names and ensure consistency.</para>
<para>You can configure the Spring container to <literal>look</literal>
for named initialization and destroy callback method names on
<emphasis>every</emphasis> bean. This means that you, as an application
developer, can write your application classes and use an initialization
callback called <literal>init()</literal>, without having to configure
an <literal>init-method="init"</literal> attribute with each bean
definition. The Spring IoC container calls that method when the bean is
created (and in accordance with the standard lifecycle callback contract
described previously). This feature also enforces a consistent naming
convention for initialization and destroy method callbacks.</para>
<para>Suppose that your initialization callback methods are named
<literal>init()</literal> and destroy callback methods are named
<literal>destroy()</literal>. Your class will resemble the class in the
following example.</para>
<programlisting language="java">public class DefaultBlogService implements BlogService {
private BlogDao blogDao;
public void setBlogDao(BlogDao blogDao) {
this.blogDao = blogDao;
}
<lineannotation>// this is (unsurprisingly) the initialization callback method</lineannotation>
public void init() {
if (this.blogDao == null) {
throw new IllegalStateException("The [blogDao] property must be set.");
}
}
}</programlisting>
<programlisting language="xml">&lt;beans <emphasis role="bold">default-init-method="init"</emphasis>&gt;
&lt;bean id="blogService" class="com.foo.DefaultBlogService"&gt;
&lt;property name="blogDao" ref="blogDao" /&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<para>The presence of the <literal>default-init-method</literal> attribute
on the top-level <literal>&lt;beans/&gt;</literal> element attribute
causes the Spring IoC container to recognize a method called
<literal>init</literal> on beans as the initialization method callback.
When a bean is created and assembled, if the bean class has such a
method, it is invoked at the appropriate time.</para>
<para>You configure destroy method callbacks similarly (in XML, that is)
by using the <literal>default-destroy-method</literal> attribute on the
top-level <literal>&lt;beans/&gt;</literal> element.</para>
<para>Where existing bean classes already have callback methods that are
named at variance with the convention, you can override the default by
specifying (in XML, that is) the method name using the
<literal>init-method</literal> and <literal>destroy-method</literal>
attributes of the &lt;bean/&gt; itself.</para>
<para>The Spring container guarantees that a configured initialization
callback is called immediately after a bean is supplied with all
dependencies. Thus the initialization callback is called on the raw bean
reference, which means that AOP interceptors and so forth are not yet
applied to the bean. A target bean is fully created
<emphasis>first</emphasis>, <emphasis>then</emphasis> an AOP proxy (for
example) with its interceptor chain is applied. If the target bean and
the proxy are defined separately, your code can even interact with the
raw target bean, bypassing the proxy. Hence, it would be inconsistent to
apply the interceptors to the init method, because doing so would couple
the lifecycle of the target bean with its proxy/interceptors and leave
strange semantics when your code interacts directly to the raw target
bean.</para>
</section>
<section id="beans-factory-lifecycle-combined-effects">
<title>Combining lifecycle mechanisms</title>
<para>As of Spring 2.5, you have three options for controlling bean
lifecycle behavior: the <link
linkend="beans-factory-lifecycle-initializingbean"
><interfacename>InitializingBean</interfacename></link> and <link
linkend="beans-factory-lifecycle-disposablebean"
><interfacename>DisposableBean</interfacename></link> callback
interfaces; custom <literal>init()</literal> and
<literal>destroy()</literal> methods; and the <link
linkend="beans-postconstruct-and-predestroy-annotations"
><interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename> annotations</link>. You can
combine these mechanisms to control a given bean.</para>
<note>
<para>If multiple lifecycle mechanisms are configured for a bean, and
each mechanism is configured with a different method name, then each
configured method is executed in the order listed below. However, if
the same method name is configured - for example,
<literal>init()</literal> for an initialization method - for more than
one of these lifecycle mechanisms, that method is executed once, as
explained in the preceding section.</para>
</note>
<para>Multiple lifecycle mechanisms configured for the same bean, with
different initialization methods, are called as follows:</para>
<itemizedlist>
<listitem>
<para>Methods annotated with
<interfacename>@PostConstruct</interfacename></para>
</listitem>
<listitem>
<para><literal>afterPropertiesSet()</literal> as defined by the
<interfacename>InitializingBean</interfacename> callback
interface</para>
</listitem>
<listitem>
<para>A custom configured <literal>init()</literal> method</para>
</listitem>
</itemizedlist>
<para>Destroy methods are called in the same order:</para>
<itemizedlist>
<listitem>
<para>Methods annotated with
<interfacename>@PreDestroy</interfacename></para>
</listitem>
<listitem>
<para><literal>destroy()</literal> as defined by the
<interfacename>DisposableBean</interfacename> callback
interface</para>
</listitem>
<listitem>
<para>A custom configured <literal>destroy()</literal> method</para>
</listitem>
</itemizedlist>
</section>
<section id="beans-factory-lifecycle-processor">
<title>Startup and shutdown callbacks</title>
<para>The <interfacename>Lifecycle</interfacename> interface defines the
essential methods for any object that has its own lifecycle requirements
(e.g. starts and stops some background process):</para>
<programlisting language="java">public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}</programlisting>
<para>Any Spring-managed object may implement that interface. Then, when
the ApplicationContext itself starts and stops, it will cascade those
calls to all Lifecycle implementations defined within that context. It
does this by delegating to a
<interfacename>LifecycleProcessor</interfacename>:</para>
<programlisting language="java">public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}</programlisting>
<para>Notice that the <interfacename>LifecycleProcessor</interfacename> is
itself an extension of the <interfacename>Lifecycle</interfacename>
interface. It also adds two other methods for reacting to the context
being refreshed and closed.</para>
<para>The order of startup and shutdown invocations can be important. If a
"depends-on" relationship exists between any two objects, the dependent
side will start <emphasis>after</emphasis> its dependency, and it will
stop <emphasis>before</emphasis> its dependency. However, at times the
direct dependencies are unknown. You may only know that objects of a
certain type should start prior to objects of another type. In those
cases, the <interfacename>SmartLifecycle</interfacename> interface
defines another option, namely the <methodname>getPhase()</methodname>
method as defined on its super-interface,
<interfacename>Phased</interfacename>.</para>
<programlisting language="java">public interface Phased {
int getPhase();
}
public interface SmartLifecycle extends Lifecycle, Phased {
boolean isAutoStartup();
void stop(Runnable callback);
}</programlisting>
<para>When starting, the objects with the lowest phase start first, and
when stopping, the reverse order is followed. Therefore, an object that
implements <interfacename>SmartLifecycle</interfacename> and whose
getPhase() method returns <literal>Integer.MIN_VALUE</literal> would be
among the first to start and the last to stop. At the other end of the
spectrum, a phase value of <literal>Integer.MAX_VALUE</literal> would
indicate that the object should be started last and stopped first
(likely because it depends on other processes to be running). When
considering the phase value, it's also important to know that the
default phase for any "normal" <interfacename>Lifecycle</interfacename>
object that does not implement
<interfacename>SmartLifecycle</interfacename> would be 0. Therefore, any
negative phase value would indicate that an object should start before
those standard components (and stop after them), and vice versa for any
positive phase value.</para>
<para>As you can see the stop method defined by
<interfacename>SmartLifecycle</interfacename> accepts a callback. Any
implementation <emphasis>must</emphasis> invoke that callback's run()
method after that implementation's shutdown process is complete. That
enables asynchronous shutdown where necessary since the default
implementation of the <interfacename>LifecycleProcessor</interfacename>
interface, <classname>DefaultLifecycleProcessor</classname>, will wait
up to its timeout value for the group of objects within each phase to
invoke that callback. The default per-phase timeout is 30 seconds. You
can override the default lifecycle processor instance by defining a bean
named "lifecycleProcessor" within the context. If you only want to
modify the timeout, then defining the following would be
sufficient:</para>
<programlisting language="xml">&lt;bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"&gt;
&lt;!-- timeout value in milliseconds --&gt;
&lt;property name="timeoutPerShutdownPhase" value="10000"/&gt;
&lt;/bean&gt;</programlisting>
<para>As mentioned, the <interfacename>LifecycleProcessor</interfacename>
interface defines callback methods for the refreshing and closing of the
context as well. The latter will simply drive the shutdown process as if
stop() had been called explicitly, but it will happen when the context
is closing. The 'refresh' callback on the other hand enables another
feature of <interfacename>SmartLifecycle</interfacename> beans. When the
context is refreshed (after all objects have been instantiated and
initialized), that callback will be invoked, and at that point the
default lifecycle processor will check the boolean value returned by
each <interfacename>SmartLifecycle</interfacename> object's
<methodname>isAutoStartup()</methodname> method. If "true", then that
object will be started at that point rather than waiting for an explicit
invocation of the context's or its own start() method (unlike the
context refresh, the context start does not happen automatically for a
standard context implementation). The "phase" value as well as any
"depends-on" relationships will determine the startup order in the same
way as described above.</para>
</section>
<section id="beans-factory-shutdown">
<title>Shutting down the Spring IoC container gracefully in non-web
applications</title>
<note>
<para>This section applies only to non-web applications. Spring's
web-based <interfacename>ApplicationContext</interfacename>
implementations already have code in place to shut down the Spring IoC
container gracefully when the relevant web application is shut
down.</para>
</note>
<para>If you are using Spring's IoC container in a non-web application
environment; for example, in a rich client desktop environment; you
register a shutdown hook with the JVM. Doing so ensures a graceful
shutdown and calls the relevant destroy methods on your singleton beans
so that all resources are released. Of course, you must still configure
and implement these destroy callbacks correctly.</para>
<para>To register a shutdown hook, you call the
<methodname>registerShutdownHook()</methodname> method that is declared
on the <classname>AbstractApplicationContext</classname> class:</para>
<programlisting language="java">import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
AbstractApplicationContext ctx
= new ClassPathXmlApplicationContext(new String []{"beans.xml"});
<lineannotation>// add a shutdown hook for the above context... </lineannotation>
ctx.registerShutdownHook();
<lineannotation>// app runs here...</lineannotation>
<lineannotation>// main method exits, hook is called prior to the app shutting down...</lineannotation>
}
}</programlisting>
</section>
</section>
<section id="beans-factory-aware">
<title><interfacename>ApplicationContextAware</interfacename> and
<interfacename>BeanNameAware</interfacename></title>
<para>When an <interfacename>ApplicationContext</interfacename> creates a
class that implements the
<interfacename>org.springframework.context.ApplicationContextAware</interfacename>
interface, the class is provided with a reference to that
<interfacename>ApplicationContext</interfacename>.</para>
<programlisting language="java">public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}</programlisting>
<para>Thus beans can manipulate programmatically the
<interfacename>ApplicationContext</interfacename> that created them,
through the <interfacename>ApplicationContext</interfacename> interface,
or by casting the reference to a known subclass of this interface, such as
<classname>ConfigurableApplicationContext</classname>, which exposes
additional functionality. One use would be the programmatic retrieval of
other beans. Sometimes this capability is useful; however, in general you
should avoid it, because it couples the code to Spring and does not follow
the Inversion of Control style, where collaborators are provided to beans
as properties. Other methods of the ApplicationContext provide access to
file resources, publishing application events, and accessing a
MessageSource. These additional features are described in <xref
linkend="context-introduction"/></para>
<para>As of Spring 2.5, autowiring is another alternative to obtain
reference to the <interfacename>ApplicationContext</interfacename>. The
"traditional" <literal>constructor</literal> and <literal>byType</literal>
autowiring modes (as described in <xref linkend="beans-factory-autowire"
/>) can provide a dependency of type
<interfacename>ApplicationContext</interfacename> for a constructor
argument or setter method parameter, respectively. For more flexibility,
including the ability to autowire fields and multiple parameter methods,
use the new annotation-based autowiring features. If you do, the
<interfacename>ApplicationFactory</interfacename> is autowired into a
field, constructor argument, or method parameter that is expecting the
<interfacename>BeanFactory</interfacename> type if the field, constructor,
or method in question carries the
<interfacename>@Autowired</interfacename> annotation. For more
information, see <xref linkend="beans-autowired-annotation"/>.</para>
<para>When an ApplicationContext creates a class that implements the
<interfacename>org.springframework.beans.factory.BeanNameAware</interfacename>
interface, the class is provided with a reference to the name defined in
its associated object definition.</para>
<programlisting language="java">public interface BeanNameAware {
void setBeanName(string name) throws BeansException;
}</programlisting>
<para>The callback is invoked after population of normal bean properties but
before an initialization callback such as
<interfacename>InitializingBean</interfacename>s
<emphasis>afterPropertiesSet</emphasis> or a custom init-method.</para>
</section>
<section id="aware-list">
<title>Other <interfacename>Aware</interfacename> interfaces</title>
<para>Besides <interfacename>ApplicationContextAware</interfacename> and
<interfacename>BeanNameAware</interfacename> discussed above, Spring
offers a range of
<emphasis><interfacename>Aware</interfacename></emphasis> interfaces that
allow beans to indicate to the container that they require a certain
<emphasis>infrastructure</emphasis> dependency. The most important
<interfacename>Aware</interfacename> interfaces are summarized below - as
a general rule, the name is a good indication of the dependency
type:</para>
<table id="beans-factory-nature-aware-list" pgwide="1">
<title><interfacename>Aware</interfacename> interfaces</title>
<tgroup cols="3">
<colspec align="left"/>
<thead>
<row>
<entry>Name</entry>
<entry>Injected Dependency</entry>
<entry>Explained in...</entry>
</row>
</thead>
<tbody>
<row>
<entry><para><classname>ApplicationContextAware</classname></para></entry>
<entry><para>Declaring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>ApplicationEventPublisherAware</classname></para></entry>
<entry><para>Event publisher of the enclosing
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="context-introduction"/></para></entry>
</row>
<row>
<entry><para><classname>BeanClassLoaderAware</classname></para></entry>
<entry><para>Class loader used to load the bean
classes.</para></entry>
<entry><para><xref linkend="beans-factory-class"/></para></entry>
</row>
<row>
<entry><para><classname>BeanFactoryAware</classname></para></entry>
<entry><para>Declaring
<interfacename>BeanFactory</interfacename></para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>BeanNameAware</classname></para></entry>
<entry><para>Name of the declaring bean</para></entry>
<entry><para><xref linkend="beans-factory-aware"/></para></entry>
</row>
<row>
<entry><para><classname>BootstrapContextAware</classname></para></entry>
<entry><para>Resource adapter
<interfacename>BootstrapContext</interfacename> the container runs
in. Typically available only in JCA aware
<interfacename>ApplicationContext</interfacename>s</para></entry>
<entry><para><xref linkend="cci"/></para></entry>
</row>
<row>
<entry><para><classname>LoadTimeWeaverAware</classname></para></entry>
<entry><para>Defined <emphasis>weaver</emphasis> for processing
class definition at load time</para></entry>
<entry><para><xref linkend="aop-aj-ltw"/></para></entry>
</row>
<row>
<entry><para><classname>MessageSourceAware</classname></para></entry>
<entry><para>Configured strategy for resolving messages (with
support for parametrization and
internationalization)</para></entry>
<entry><para><xref linkend="context-introduction"/></para></entry>
</row>
<row>
<entry><para><classname>NotificationPublisherAware</classname></para></entry>
<entry><para>Spring JMX notification publisher</para></entry>
<entry><para><xref linkend="jmx-notifications"/></para></entry>
</row>
<row>
<entry><para><classname>PortletConfigAware</classname></para></entry>
<entry><para>Current <interfacename>PortletConfig</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="portlet"/></para></entry>
</row>
<row>
<entry><para><classname>PortletContextAware</classname></para></entry>
<entry><para>Current <interfacename>PortletContext</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="portlet"/></para></entry>
</row>
<row>
<entry><para><classname>ResourceLoaderAware</classname></para></entry>
<entry><para>Configured loader for low-level access to
resources</para></entry>
<entry><para><xref linkend="resources"/></para></entry>
</row>
<row>
<entry><para><classname>ServletConfigAware</classname></para></entry>
<entry><para>Current <interfacename>ServletConfig</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="mvc"/></para></entry>
</row>
<row>
<entry><para><classname>ServletContextAware</classname></para></entry>
<entry><para>Current <interfacename>ServletContext</interfacename>
the container runs in. Valid only in a web-aware Spring
<interfacename>ApplicationContext</interfacename></para></entry>
<entry><para><xref linkend="mvc"/></para></entry>
</row>
</tbody>
</tgroup>
</table>
<para>Note again that usage of these interfaces ties your code to the Spring
API and does not follow the Inversion of Control style. As such, they are
recommended for infrastructure beans that require programmatic access to
the container.</para>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,519 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-extension">
<title>Container extension points</title>
<para>Typically, an application developer does not need to subclass any
<interfacename>ApplicationContext</interfacename> implementation classes.
You can extend The Spring IoC container infinitely by plugging in
implementations of special integration interfaces. The next few sections
describe these integration interfaces.</para>
<section id="beans-factory-extension-bpp">
<title>Customizing beans using the
<interfacename>BeanPostProcessor</interfacename> Interface <literal>
</literal></title>
<para>The <interfacename>BeanPostProcessor</interfacename> interface defines
<firstterm>callback methods</firstterm> that you can implement to provide
your own (or override the container's default) instantiation logic,
dependency-resolution logic, and so forth. If you want to implement some
custom logic after the Spring container finishes instantiating,
configuring, and otherwise initializing a bean, you can plug in one or
more <interfacename>BeanPostProcessor</interfacename>
implementations.</para>
<para>You can configure multiple <literal>BeanPostProcessor</literal>
interfaces. You can control the order in which these
<literal>BeanPostProcessor</literal> interfaces execute by setting the
<literal>order</literal> property. You can set this property only if the
<interfacename>BeanPostProcessor</interfacename> implements the
<interfacename>Ordered</interfacename> interface; if you write your own
<interfacename>BeanPostProcessor</interfacename> you should consider
implementing the <interfacename>Ordered</interfacename> interface too. For
more details, consult the Javadoc for the
<interfacename>BeanPostProcessor</interfacename> and
<interfacename>Ordered</interfacename> interfaces.</para>
<note>
<para><literal>BeanPostProcessor</literal>s operate on bean (or object)
<emphasis>instances</emphasis>; that is to say, the Spring IoC container
instantiates a bean instance and <emphasis>then</emphasis>
<literal>BeanPostProcessor</literal> interfaces do their work.</para>
<para><literal>BeanPostProcessor</literal> interfaces are scoped
<emphasis>per-container</emphasis>. This is only relevant if you are
using container hierarchies. If you define a
<interfacename>BeanPostProcessor</interfacename> in one container, it
will <emphasis>only</emphasis> do its work on the beans in that
container. Beans that are defined in one container are not
post-processed by a <literal>BeanPostProcessor</literal> in another
container, even if both containers are part of the same
hierarchy.</para>
<para>To change the actual bean definition (that is, the recipe that
defines the bean), you instead need to use a
<interfacename>BeanFactoryPostProcessor</interfacename>, described below
in <xref linkend="beans-factory-extension-factory-postprocessors"
/>.</para>
</note>
<para>The
<interfacename>org.springframework.beans.factory.config.BeanPostProcessor</interfacename>
interface consists of exactly two callback methods. When such a class is
registered as a post-processor with the container, for each bean instance
that is created by the container, the post-processor gets a callback from
the container both <emphasis>before</emphasis> container initialization
methods (such as <emphasis>afterPropertiesSet</emphasis> and any declared
init method) are called, and also afterwards. The post-processor can take
any action with the bean instance, including ignoring the callback
completely. A bean post-processor typically checks for callback
interfaces, or may wrap a bean with a proxy. Some Spring AOP
infrastructure classes are implemented as bean post-processors and they do
this proxy-wrapping logic.</para>
<para>An <interfacename>ApplicationContext</interfacename>
<emphasis>automatically detects</emphasis> any beans that are defined in
the configuration metadata it receives that implement the
<interfacename>BeanPostProcessor</interfacename> interface. The
<interfacename>ApplicationContext</interfacename> registers these beans as
post-processors, to be then called appropriately by the container upon
bean creation. You can then deploy the post-processors as you would any
bean.</para>
<note>
<title><interfacename>BeanPostProcessors</interfacename> and AOP
auto-proxying</title>
<para>Classes that implement the
<interfacename>BeanPostProcessor</interfacename> interface are
<emphasis>special</emphasis>, and so they are treated differently by the
container. All <interfacename>BeanPostProcessors</interfacename>
<emphasis>and their directly referenced beans</emphasis> are
instantiated on startup, as part of the special startup phase of the
<interfacename>ApplicationContext</interfacename>. Next, all those
<interfacename>BeanPostProcessors</interfacename> are registered in a
sorted fashion - and applied to all further beans. Because AOP
auto-proxying is implemented as a
<interfacename>BeanPostProcessor</interfacename> itself, no
<interfacename>BeanPostProcessors</interfacename> or directly referenced
beans are eligible for auto-proxying, and thus do not have aspects woven
into them.</para>
<para>For any such bean, you should see an info log message:
<emphasis><quote>Bean foo is not eligible for getting processed by all
BeanPostProcessor interfaces (for example: not eligible for
auto-proxying)</quote>.</emphasis></para>
</note>
<para>The following examples show how to write, register, and use
<literal>BeanPostProcessors</literal> in the context of an
<interfacename>ApplicationContext</interfacename>.</para>
<section id="beans-factory-extension-bpp-examples-hw">
<title>Example: Hello World,
<interfacename>BeanPostProcessor</interfacename>-style</title>
<para>This first example illustrates basic usage. The example shows a
custom <interfacename>BeanPostProcessor</interfacename> implementation
that invokes the <methodname>toString()</methodname> method of each bean
as it is created by the container and prints the resulting string to the
system console.</para>
<para>Find below the custom
<interfacename>BeanPostProcessor</interfacename> implementation class
definition:</para>
<programlisting language="java">package scripting;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
<lineannotation>// simply return the instantiated bean as-is</lineannotation>
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean; <lineannotation>// we could potentially return <emphasis>any</emphasis> object reference here...</lineannotation>
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
return bean;
}
}</programlisting>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;lang:groovy id="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy"&gt;
&lt;lang:property name="message" value="Fiona Apple Is Just So Dreamy."/&gt;
&lt;/lang:groovy&gt;
<lineannotation>&lt;!--
when the above bean (messenger) is instantiated, this custom
<interfacename>BeanPostProcessor</interfacename> implementation will output the fact to the system console
--&gt;</lineannotation>
&lt;bean class="scripting.InstantiationTracingBeanPostProcessor"/&gt;
&lt;/beans&gt;</programlisting>
<para>Notice how the
<classname>InstantiationTracingBeanPostProcessor</classname> is simply
defined. It does not even have a name, and because it is a bean it can
be dependency-injected just like any other bean. (The preceding
configuration also defines a bean that is backed by a Groovy script. The
Spring 2.0 dynamic language support is detailed in the chapter entitled
<xref linkend="dynamic-language"/>.)</para>
<para>The following small driver script executes the preceding code and
configuration:</para>
<programlisting language="java">import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scripting.Messenger;
public final class Boot {
public static void main(final String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
Messenger messenger = (Messenger) ctx.getBean("messenger");
System.out.println(messenger);
}
}</programlisting>
<para>The output of the preceding execution resembles the
following:</para>
<programlisting>Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961</programlisting>
</section>
<section id="beans-factory-extension-bpp-examples-rabpp">
<title>Example: The
<classname>RequiredAnnotationBeanPostProcessor</classname></title>
<para>Using callback interfaces or annotations in conjunction with a
custom <interfacename>BeanPostProcessor</interfacename> implementation
is a common means of extending the Spring IoC container. An example is
Spring's <classname>RequiredAnnotationBeanPostProcessor</classname> -- a
<interfacename>BeanPostProcessor</interfacename> implementation that
ships with the Spring distribution which ensures that JavaBean
properties on beans that are marked with an (arbitrary) annotation are
actually (configured to be) dependency-injected with a value.</para>
</section>
</section>
<section id="beans-factory-extension-factory-postprocessors">
<title>Customizing configuration metadata with
<interfacename>BeanFactoryPostProcessor</interfacename> interface</title>
<para>The next extension point that we will look at is the
<interfacename>org.springframework.beans.factory.config.BeanFactoryPostProcessor</interfacename>.
The semantics of this interface are similar to the
<interfacename>BeanPostProcessor</interfacename>, with one major
difference: <literal>BeanFactoryPostProcessor</literal>s operate on the
<emphasis>bean configuration metadata</emphasis>; that is, the Spring IoC
container allows <literal>BeanFactoryPostProcessors</literal> to read the
configuration metadata and potentially change it
<emphasis>before</emphasis> the container instantiates any beans other
than <literal>BeanFactoryPostProcessors</literal>.</para>
<para>You can configure multiple
<literal>BeanFactoryPostProcessors</literal>. You can control the order in
which these <literal>BeanFactoryPostProcessors</literal> execute by
setting the <literal>order</literal> property. However, you can only set
this property if the
<interfacename>BeanFactoryPostProcessor</interfacename> implements the
<interfacename>Ordered</interfacename> interface. If you write your own
<interfacename>BeanFactoryPostProcessor,</interfacename> you should
consider implementing the <interfacename>Ordered</interfacename> interface
too; consult the Javadoc for the
<interfacename>BeanFactoryPostProcessor</interfacename> and
<interfacename>Ordered</interfacename> interfaces for more details.</para>
<note>
<para>If you want to change the actual bean <emphasis>instances</emphasis>
(the objects that are created from the configuration metadata), then you
instead need to use a <interfacename>BeanPostProcessor</interfacename>
(described above in <xref linkend="beans-factory-extension-bpp"/>. While
it is technically possible to work with bean instances within a
<interfacename>BeanFactoryPostProcessor</interfacename> (e.g. using
<methodname>BeanFactory.getBean()</methodname>), doing so causes
premature bean instantiation, violating the usual containter lifecycle.
This may cause negative side effects such as bypassing bean post
processing.</para>
<para>Also, <literal>BeanFactoryPostProcessors</literal> are scoped
<emphasis>per-container</emphasis>. This is only relevant if you are
using container hierarchies. If you define a
<interfacename>BeanFactoryPostProcessor</interfacename> in one
container, it will <emphasis>only</emphasis> do its stuff on the bean
definitions in that container. Bean definitions in another container
will not be post-processed by
<literal>BeanFactoryPostProcessors</literal> in another container, even
if both containers are part of the same hierarchy.</para>
</note>
<para>A bean factory post-processor is executed automatically when it is
declared inside of an <interfacename>ApplicationContext,</interfacename>
in order to apply changes to the configuration metadata that defines a
container. Spring includes a number of pre-existing bean factory
post-processors, such as <classname>PropertyOverrideConfigurer</classname>
and <classname>PropertyPlaceholderConfigurer. </classname>A custom
<interfacename>BeanFactoryPostProcessor</interfacename> can also be used,
for example, to register custom property editors.</para>
<anchor id="beans-factory-autodetect-beanfactorypostprocessors"/>
<para>An <interfacename>ApplicationContext</interfacename> detects any beans
that are deployed into it and that implement the
<interfacename>BeanFactoryPostProcessor</interfacename> interface. It
automatically uses these beans as bean factory post-processors, at the
appropriate time. You can then deploy these post-processor beans as you
would any other bean.</para>
<note>
<para>As with <literal>BeanPostProcessors</literal>, you typically do not
want <literal>BeanFactoryPostProcessors</literal> marked as
lazy-initialized. If they are marked as such, the Spring container never
instantiates them, and thus they cannot apply their custom logic. If you
use the <literal>default-lazy-init</literal> attribute on the
declaration of your <literal>&lt;beans/&gt;</literal> element, be sure
to mark your various
<interfacename>BeanFactoryPostProcessor</interfacename> bean definitions
with <literal>lazy-init="false"</literal>.</para>
</note>
<section id="beans-factory-placeholderconfigurer">
<title>Example: the
<interfacename>PropertyPlaceholderConfigurer</interfacename></title>
<para>You use the
<interfacename>PropertyPlaceholderConfigurer</interfacename> to
externalize property values from a bean definition into another separate
file in the standard Java <classname>Properties</classname> format.
Doing so enables the person deploying an application to customize
environment-specific properties such as database URLs and passwords,
without the complexity or risk of modifying the main XML definition file
or files for the container.</para>
<!-- MLP: Beverly to review following 2 paragraphs -->
<para>Consider the following XML-based configuration metadata fragment,
where a <interfacename>DataSource</interfacename> with placeholder
values is defined. The example shows properties configured from an
external <classname>Properties</classname> file. At runtime, a
<classname>PropertyPlaceholderConfigurer</classname> is applied to the
metadata that will replace some properties of the DataSource. The values
to replace are specified as 'placeholders' of the form ${property-name}
which follows the Ant / Log4J / JSP EL style.</para>
<programlisting language="xml">&lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
&lt;property name="locations" value="classpath:com/foo/jdbc.properties"/&gt;
&lt;/bean&gt;
&lt;bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource"&gt;
&lt;property name="driverClassName" value="<emphasis role="bold">${jdbc.driverClassName}</emphasis>"/&gt;
&lt;property name="url" value="<emphasis role="bold">${jdbc.url}</emphasis>"/&gt;
&lt;property name="username" value="<emphasis role="bold">${jdbc.username}</emphasis>"/&gt;
&lt;property name="password" value="<emphasis role="bold">${jdbc.password}</emphasis>"/&gt;
&lt;/bean&gt;</programlisting>
<para>The actual values come from another file in the standard Java
<classname>Properties</classname> format:</para>
<programlisting language="java">jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root</programlisting>
<para>Therefore, the string ${jdbc.username} is replaced at runtime with
the value 'sa' and similarly for other placeholder values that match to
keys in the property file. The PropertyPlaceholderConfigurer checks for
placeholders in most locations of a bean definition and the placeholder
prefix and suffix can be customized.</para>
<para>With the <literal>context</literal> namespace introduced in Spring
2.5, it is possible to configure property placeholders with a dedicated
configuration element. You can provide multiple locations as a
comma-separated list in the <literal>location</literal>
attribute.</para>
<programlisting language="xml">&lt;context:property-placeholder location="classpath:com/foo/jdbc.properties"/&gt;</programlisting>
<para>The <classname>PropertyPlaceholderConfigurer</classname> does not
look for properties only in the <classname>Properties</classname> file
you specify, but also checks against the Java
<classname>System</classname> properties if it cannot find a property
you are trying to use. You can customize this behavior by setting the
<literal>systemPropertiesMode</literal> property of the configurer. It
has three values that specify configurer behavior: always override,
<emphasis>never</emphasis> override, and override only if the property
is not found in the properties file specified.
<!--What property is it overriding and what will replace the overridden value?-->
<!--MLP: override a value in the Properties with one from the 'systemProperties' -->
Consult the Javadoc for the
<classname>PropertyPlaceholderConfigurer</classname> for more
information.</para>
<tip>
<title>Class name substitution</title>
<para>You can use the
<classname>PropertyPlaceholderConfigurer</classname> to substitute
class names, which is sometimes useful when you have to pick a
particular implementation class at runtime. For example:</para>
<programlisting language="xml">&lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
&lt;property name="locations"&gt;
&lt;value&gt;classpath:com/foo/strategy.properties&lt;/value&gt;
&lt;/property&gt;
&lt;property name="properties"&gt;
&lt;value&gt;custom.strategy.class=com.foo.DefaultStrategy&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="serviceStrategy" class="${custom.strategy.class}"/&gt;</programlisting>
<para>If the class cannot be resolved at runtime to a valid class,
resolution of the bean fails when it is about to be created, which is
during the <methodname>preInstantiateSingletons()</methodname> phase
of an <interfacename>ApplicationContext</interfacename> for a
non-lazy-init bean.</para>
</tip>
</section>
<section id="beans-factory-overrideconfigurer">
<title>Example: the
<classname>PropertyOverrideConfigurer</classname></title>
<para>The <classname>PropertyOverrideConfigurer</classname>, another bean
factory post-processor, resembles the
<interfacename>PropertyPlaceholderConfigurer</interfacename>, but unlike
the latter, the original definitions can have default values or no
values at all for bean properties. If an overriding
<classname>Properties</classname> file does not have an entry for a
certain bean property, the default context definition is used.</para>
<para>Note that the bean definition is <emphasis>not</emphasis> aware of
being overridden, so it is not immediately obvious from the XML
definition file that the override configurer is used. In case of
multiple <classname>PropertyOverrideConfigurer</classname> instances
that define different values for the same bean property, the last one
wins, due to the overriding mechanism.</para>
<para>Properties file configuration lines take this format:</para>
<programlisting language="java">beanName.property=value</programlisting>
<para>For example:</para>
<programlisting language="java">dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb</programlisting>
<para>This example file is usable against a container definition that
contains a bean called <emphasis>dataSource</emphasis>, which has
<emphasis>driver</emphasis> and <emphasis>url</emphasis>
properties.</para>
<para>Compound property names are also supported, as long as every
component of the path except the final property being overridden is
already non-null (presumably initialized by the constructors). In this
example...</para>
<programlisting language="java">foo.fred.bob.sammy=123</programlisting>
<para>... the <literal>sammy</literal> property of the
<literal>bob</literal> property of the <literal>fred</literal> property
of the <literal>foo</literal> bean is set to the scalar value
<literal>123</literal>.</para>
<para><note>
<para>Specified override values are always <emphasis>literal</emphasis>
values; they are not translated into bean references. This convention
also applies when the original value in the XML bean definition
specifies a bean reference.</para>
</note></para>
<para>With the <literal>context</literal> namespace introduced in Spring
2.5, it is possible to configure property overriding with a dedicated
configuration element:</para>
<programlisting language="xml">&lt;context:property-override location="classpath:override.properties"/&gt;</programlisting>
</section>
</section>
<section id="beans-factory-extension-factorybean">
<title>Customizing instantiation logic with the
<interfacename>FactoryBean</interfacename> Interface <literal>
</literal></title>
<para>You implement the
<interfacename>org.springframework.beans.factory.FactoryBean</interfacename>
interface for objects that <emphasis>are themselves
factories</emphasis>.</para>
<para>The <interfacename>FactoryBean</interfacename> interface is a point of
pluggability into the Spring IoC container's instantiation logic. If you
have complex initialization code that is better expressed in Java as
opposed to a (potentially) verbose amount of XML, you can create your own
<interfacename>FactoryBean</interfacename>, write the complex
initialization inside that class, and then plug your custom
<interfacename>FactoryBean</interfacename> into the container.</para>
<para>The <interfacename>FactoryBean</interfacename> interface provides
three methods:</para>
<itemizedlist>
<listitem>
<para><methodname>Object getObject()</methodname>: returns an instance
of the object this factory creates. The instance can possibly be
shared, depending on whether this factory returns singletons or
prototypes.</para>
</listitem>
<listitem>
<para><methodname>boolean isSingleton()</methodname>: returns
<literal>true</literal> if this
<interfacename>FactoryBean</interfacename> returns singletons,
<literal>false</literal> otherwise.</para>
</listitem>
<listitem>
<para><methodname>Class getObjectType()</methodname>: returns the object
type returned by the <methodname>getObject()</methodname> method or
<literal>null</literal> if the type is not known in advance</para>
</listitem>
</itemizedlist>
<para>The <interfacename>FactoryBean</interfacename> concept and interface
is used in a number of places within the Spring Framework; more than 50
implementations of the <interfacename>FactoryBean</interfacename>
interface ship with Spring itself.</para>
<para>When you need to ask a container for an actual
<interfacename>FactoryBean</interfacename> instance itself, not the bean
it produces, you preface the bean id with the ampersand symbol
<literal>&amp;</literal> (without quotes) when calling the
<methodname>getBean()</methodname> method of the
<interfacename>ApplicationContext</interfacename>. So for a given
<interfacename>FactoryBean</interfacename> with an id of
<literal>myBean</literal>, invoking <literal>getBean("myBean")</literal>
on the container returns the product of the
<interfacename>FactoryBean</interfacename>, and invoking
<literal>getBean("&amp;myBean")</literal> returns the
<interfacename>FactoryBean</interfacename> instance
itself.<!--Moved ApplicationContext section to almost the end of the doc, right before BeanFactory and renamed it Additional Capabilities of.--></para>
</section>
</section>

View File

@ -0,0 +1,908 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-java">
<title>Java-based container configuration</title>
<section id="beans-java-basic-concepts">
<title>Basic concepts: <literal>@Configuration</literal> and
<literal>@Bean</literal></title>
<para>The central artifact in Spring's new Java-configuration support is the
<interfacename>@Configuration</interfacename>-annotated class. These
classes consist principally of
<interfacename>@Bean</interfacename>-annotated methods that define
instantiation, configuration, and initialization logic for objects to be
managed by the Spring IoC container.</para>
<para>Annotating a class with the
<interfacename>@Configuration</interfacename> indicates that the class can
be used by the Spring IoC container as a source of bean definitions. The
simplest possible <interfacename>@Configuration</interfacename> class
would read as follows:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}</programlisting></para>
<para>For those more familiar with Spring <literal>&lt;beans/&gt;</literal>
XML, the <literal>AppConfig</literal> class above would be equivalent to:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myService" class="com.acme.services.MyServiceImpl"/&gt;
&lt;/beans&gt;</programlisting>
As you can see, the <literal>@Bean</literal> annotation plays the same
role as the <literal>&lt;bean/&gt;</literal> element. The
<literal>@Bean</literal> annotation will be discussed in depth in the
sections below. First, however, we'll cover the various ways of creating a
spring container using Java-based configuration.</para>
</section>
<section id="beans-java-instantiating-container">
<title>Instantiating the Spring container using
<literal>AnnotationConfigApplicationContext</literal></title>
<para>The sections below document Spring's
<literal>AnnotationConfigApplicationContext</literal>, new in Spring 3.0.
This versatile <literal>ApplicationContext</literal> implementation is
capable of accepting not only <literal>@Configuration</literal> classes as
input, but also plain <literal>@Component</literal> classes and classes
annotated with JSR-330 metadata.</para>
<para>When <literal>@Configuration</literal> classes are provided as input,
the <literal>@Configuration</literal> class itself is registered as a bean
definition, and all declared <literal>@Bean</literal> methods within the
class are also registered as bean definitions.</para>
<para>When <literal>@Component</literal> and JSR-330 classes are provided,
they are registered as bean definitions, and it is assumed that DI
metadata such as <literal>@Autowired</literal> or
<literal>@Inject</literal> are used within those classes where
necessary.</para>
<section id="beans-java-instantiating-container-contstructor">
<title>Simple construction</title>
<para>In much the same way that Spring XML files are used as input when
instantiating a <literal>ClassPathXmlApplicationContext</literal>,
<literal>@Configuration</literal> classes may be used as input when
instantiating an <literal>AnnotationConfigApplicationContext</literal>.
This allows for completely XML-free usage of the Spring container:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting>
As mentioned above,
<literal>AnnotationConfigApplicationContext</literal> is not limited to
working only with <literal>@Configuration</literal> classes. Any
<literal>@Component</literal> or JSR-330 annotated class may be supplied
as input to the constructor. For example:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting>
The above assumes that <literal>MyServiceImpl</literal>,
<literal>Dependency1</literal> and <literal>Dependency2</literal> use
Spring dependency injection annotations such as
<literal>@Autowired</literal>.</para>
</section>
<section id="beans-java-instantiating-container-register">
<title>Building the container programmatically using
<literal>register(Class&lt;?&gt;...)</literal></title>
<para>An <literal>AnnotationConfigApplicationContext</literal> may be
instantiated using a no-arg constructor and then configured using the
<literal>register()</literal> method. This approach is particularly
useful when programmatically building an
<literal>AnnotationConfigApplicationContext</literal>.
<programlisting language="java">public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}</programlisting></para>
</section>
<section id="beans-java-instantiating-container-scan">
<title>Enabling component scanning with
<literal>scan(String...)</literal></title>
<para>Experienced Spring users will be familiar with the following
commonly-used XML declaration from Spring's <literal>context:</literal>
namespace
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="com.acme"/&gt;
&lt;/beans&gt;</programlisting>
In the example above, the <literal>com.acme</literal> package will be
scanned, looking for any <literal>@Component</literal>-annotated
classes, and those classes will be registered as Spring bean definitions
within the container.
<literal>AnnotationConfigApplicationContext</literal> exposes the
<literal>scan(String...)</literal> method to allow for the same
component-scanning
functionality:<programlisting language="java">public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
}</programlisting></para>
<note>
<para>Remember that <literal>@Configuration</literal> classes are
meta-annotated with <literal>@Component</literal>, so they are
candidates for component-scanning! In the example above, assuming that
<literal>AppConfig</literal> is declared within the
<literal>com.acme</literal> package (or any package underneath), it
will be picked up during the call to <literal>scan()</literal>, and
upon <literal>refresh()</literal> all its <literal>@Bean</literal>
methods will be processed and registered as bean definitions within
the container.</para>
</note>
</section>
<section id="beans-java-instantiating-container-web">
<title>Support for web applications with
<literal>AnnotationConfigWebApplicationContext</literal></title>
<para>A <literal>WebApplicationContext</literal> variant of
<literal>AnnotationConfigApplicationContext</literal> is available with
<literal>AnnotationConfigWebApplicationContext</literal>. This
implementation may be used when configuring the Spring
<literal>ContextLoaderListener</literal> servlet listener, Spring MVC
<literal>DispatcherServlet</literal>, etc. What follows is a
<literal>web.xml</literal> snippet that configures a typical Spring MVC
web application. Note the use of the <literal>contextClass</literal>
context-param and init-param:
<programlisting language="xml">
&lt;web-app&gt;
&lt;!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext --&gt;
&lt;context-param&gt;
&lt;param-name&gt;contextClass&lt;/param-name&gt;
&lt;param-value&gt;
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes. Fully-qualified packages may also be
specified for component-scanning --&gt;
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;com.acme.AppConfig&lt;/param-value&gt;
&lt;/context-param&gt;
&lt;!-- Bootstrap the root application context as usual using ContextLoaderListener --&gt;
&lt;listener&gt;
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;
&lt;!-- Declare a Spring MVC DispatcherServlet as usual --&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
&lt;!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext --&gt;
&lt;init-param&gt;
&lt;param-name&gt;contextClass&lt;/param-name&gt;
&lt;param-value&gt;
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes --&gt;
&lt;init-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
&lt;param-value&gt;com.acme.web.MvcConfig&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/servlet&gt;
&lt;!-- map all requests for /main/* to the dispatcher servlet --&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
&lt;url-pattern&gt;/main/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/web-app&gt;</programlisting></para>
</section>
</section>
<section id="beans-java-composing-configuration-classes">
<title>Composing Java-based configurations</title>
<section id="beans-java-using-import">
<title>Using the <literal>@Import</literal> annotation</title>
<para>Much as the <literal>&lt;import/&gt;</literal> element is used
within Spring XML files to aid in modularizing configurations, the
<literal>@Import</literal> annotation allows for loading
<literal>@Bean</literal> definitions from another configuration
class:<programlisting language="java">@Configuration
public class ConfigA {
public @Bean A a() { return new A(); }
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
public @Bean B b() { return new B(); }
}</programlisting>
Now, rather than needing to specify both
<literal>ConfigA.class</literal> and <literal>ConfigB.class</literal>
when instantiating the context, only <literal>ConfigB</literal> needs to
be supplied
explicitly:<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}</programlisting>
This approach simplifies container instantiation, as only one class
needs to be dealt with, rather than requiring the developer to remember
a potentially large number of <literal>@Configuration</literal> classes
during construction.</para>
<section id="beans-java-injecting-imported-beans">
<title>Injecting dependencies on imported <literal>@Bean</literal>
definitions</title>
<para>The example above works, but is simplistic. In most practical
scenarios, beans will have dependencies on one another across
configuration classes. When using XML, this is not an issue, per se,
because there is no compiler involved, and one can simply declare
<literal>ref="someBean"</literal> and trust that Spring will work it
out during container initialization. Of course, when using
<literal>@Configuration</literal> classes, the Java compiler places
constraints on the configuration model, in that references to other
beans must be valid Java syntax.</para>
<para>Fortunately, solving this problem is simple. Remember that
<literal>@Configuration</literal> classes are ultimately just another
bean in the container - this means that they can take advantage of
<literal>@Autowired</literal> injection metadata just like any other
bean!</para>
<para>Let's consider a more real-world scenario with several
<literal>@Configuration</literal> classes, each depending on beans
declared in the
others:<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired AccountRepository accountRepository;
public @Bean TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
private @Autowired DataSource dataSource;
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
public @Bean DataSource dataSource() { /* return new DataSource */ }
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}</programlisting></para>
<section id="beans-java-injecting-imported-beans-fq">
<title>Fully-qualifying imported beans for ease of navigation</title>
<para>In the scenario above, using <literal>@Autowired</literal> works
well and provides the desired modularity, but determining exactly
where the autowired bean definitions are declared is still somewhat
ambiguous. For example, as a developer looking at
<literal>ServiceConfig</literal>, how do you know exactly where the
<literal>@Autowired AccountRepository</literal> bean is declared?
It's not explicit in the code, and this may be just fine. Remember
that the <ulink url="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</ulink> provides tooling that can render
graphs showing how everything is wired up - that may be all you
need. Also, your Java IDE can easily find all declarations and uses
of the <literal>AccountRepository</literal> type, and will quickly
show you the location of <literal>@Bean</literal> methods that
return that type.</para>
<para>In cases where this ambiguity is not acceptable and you wish to
have direct navigation from within your IDE from one
<literal>@Configuration</literal> class to another, consider
autowiring the configuration classes themselves:
<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired RepositoryConfig repositoryConfig;
public @Bean TransferService transferService() {
// navigate 'through' the config class to the @Bean method!
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}</programlisting>
In the situation above, it is completely explicit where
<literal>AccountRepository</literal> is defined. However,
<literal>ServiceConfig</literal> is now tightly coupled to
<literal>RepositoryConfig</literal>; that's the tradeoff. This tight
coupling can be somewhat mitigated by using interface-based or
abstract class-based <literal>@Configuration</literal> classes.
Consider the following:
<programlisting language="java">@Configuration
public class ServiceConfig {
private @Autowired RepositoryConfig repositoryConfig;
public @Bean TransferService transferService() {
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
@Configuration
public interface RepositoryConfig {
@Bean AccountRepository accountRepository();
}
@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(...);
}
}
@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
public @Bean DataSource dataSource() { /* return DataSource */ }
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}</programlisting>
Now <literal>ServiceConfig</literal> is loosely coupled with respect
to the concrete <literal>DefaultRepositoryConfig</literal>, and
built-in IDE tooling is still useful: it will be easy for the
developer to get a type hierarchy of
<literal>RepositoryConfig</literal> implementations. In this way,
navigating <literal>@Configuration</literal> classes and their
dependencies becomes no different than the usual process of
navigating interface-based code.</para>
</section>
</section>
</section>
<section id="beans-java-combining">
<title>Combining Java and XML configuration</title>
<para>Spring's <literal>@Configuration</literal> class support does not
aim to be a 100% complete replacement for Spring XML. Some facilities
such as Spring XML namespaces remain an ideal way to configure the
container. In cases where XML is convenient or necessary, you have a
choice: either instantiate the container in an "XML-centric" way using,
for example, <literal>ClassPathXmlApplicationContext</literal>, or in a
"Java-centric" fashion using
<literal>AnnotationConfigApplicationContext</literal> and the
<literal>@ImportResource</literal> annotation to import XML as
needed.</para>
<section id="beans-java-combining-xml-centric">
<title>XML-centric use of <literal>@Configuration</literal>
classes</title>
<para>It may be preferable to bootstrap the Spring container from XML
and include <literal>@Configuration</literal> classes in an ad-hoc
fashion. For example, in a large existing codebase that uses Spring
XML, it will be easier to create <literal>@Configuration</literal>
classes on an as-needed basis and include them from the existing XML
files. Below you'll find the options for using
<literal>@Configuration</literal> classes in this kind of
"XML-centric" situation.</para>
<section id="beans-java-combining-xml-centric-declare-as-bean">
<title>Declaring <literal>@Configuration</literal> classes as plain
Spring <literal>&lt;bean/&gt;</literal> elements</title>
<para>Remember that <literal>@Configuration</literal> classes are
ultimately just bean definitions in the container. In this example,
we create a <literal>@Configuration</literal> class named
<literal>AppConfig</literal> and include it within
<literal>system-test-config.xml</literal> as a
<literal>&lt;bean/&gt;</literal>definition. Because
<literal>&lt;context:annotation-config/&gt;</literal> is switched
on, the container will recognize the
<literal>@Configuration</literal> annotation, and process the
<literal>@Bean</literal> methods declared in
<literal>AppConfig</literal>
properly.<programlisting language="java">@Configuration
public class AppConfig {
private @Autowired DataSource dataSource;
public @Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
public @Bean TransferService transferService() {
return new TransferService(accountRepository());
}
}</programlisting>
<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
&lt;beans&gt;
&lt;!-- enable processing of annotations such as @Autowired and @Configuration --&gt;
&lt;context:annotation-config/&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;bean class="com.acme.AppConfig"/&gt;
&lt;bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
&lt;property name="url" value="${jdbc.url}"/&gt;
&lt;property name="username" value="${jdbc.username}"/&gt;
&lt;property name="password" value="${jdbc.password}"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=</programlisting>
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}</programlisting></para>
<note>
<para>In <literal>system-test-config.xml</literal> above, the
<literal>AppConfig&lt;bean/&gt;</literal> does not declare an
<literal>id</literal> element. While it would be acceptable to do
so, it is unnecessary given that no other bean will ever refer to
it, and it is unlikely that it will be explicitly fetched from the
container by name. Likewise with the <literal>DataSource</literal>
bean - it is only ever autowired by type, so an explicit bean id
is not strictly required.</para>
</note>
</section>
<section id="beans-java-combining-xml-centric-component-scan">
<title>Using <literal>&lt;context:component-scan/&gt;</literal> to
pick up <literal>@Configuration</literal> classes</title>
<para>Because <literal>@Configuration</literal> is meta-annotated with
<literal>@Component</literal>,
<literal>@Configuration</literal>-annotated classes are
automatically candidates for component scanning. Using the same
scenario as above, we can redefine
<literal>system-test-config.xml</literal> to take advantage of
component-scanning. Note that in this case, we don't need to
explicitly declare
<literal>&lt;context:annotation-config/&gt;</literal>, because
<literal>&lt;context:component-scan/&gt;</literal> enables all the
same
functionality.<programlisting language="xml"><lineannotation role="listingtitle">system-test-config.xml</lineannotation>
&lt;beans&gt;
&lt;!-- picks up and registers AppConfig as a bean definition --&gt;
&lt;context:component-scan base-package="com.acme"/&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
&lt;property name="url" value="${jdbc.url}"/&gt;
&lt;property name="username" value="${jdbc.username}"/&gt;
&lt;property name="password" value="${jdbc.password}"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting></para>
</section>
</section>
<section id="beans-java-combining-java-centric">
<title><literal>@Configuration</literal> class-centric use of XML with
<literal>@ImportResource</literal></title>
<para>In applications where <literal>@Configuration</literal> classes
are the primary mechanism for configuring the container, it will still
likely be necessary to use at least some XML. In these scenarios,
simply use <literal>@ImportResource</literal> and define only as much
XML as is needed. Doing so achieves a "Java-centric" approach to
configuring the container and keeps XML to a bare minimum.
<programlisting language="java">@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
private @Value("${jdbc.url}") String url;
private @Value("${jdbc.username}") String username;
private @Value("${jdbc.password}") String password;
public @Bean DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}</programlisting>
<programlisting language="xml"><lineannotation role="listingtitle">properties-config.xml</lineannotation>
&lt;beans&gt;
&lt;context:property-placeholder location="classpath:/com/acme/jdbc.properties"/&gt;
&lt;/beans&gt;</programlisting>
<programlisting><lineannotation role="listingtitle">jdbc.properties</lineannotation>
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=</programlisting>
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}</programlisting></para>
</section>
</section>
</section>
<section id="beans-java-bean-annotation">
<title>Using the <interfacename>@Bean</interfacename> annotation</title>
<para><interfacename>@Bean</interfacename> is a method-level annotation and
a direct analog of the XML <code>&lt;bean/&gt;</code> element. The
annotation supports some of the attributes offered by
<code>&lt;bean/&gt;</code>, such as: <code><link
linkend="beans-factory-lifecycle-initializingbean"
>init-method</link></code>, <code><link
linkend="beans-factory-lifecycle-disposablebean"
>destroy-method</link></code>, <code><link
linkend="beans-factory-autowire">autowiring</link></code> and
<code>name</code>.</para>
<para>You can use the <interfacename>@Bean</interfacename> annotation in a
<interfacename>@Configuration</interfacename>-annotated or in a
<interfacename>@Component</interfacename>-annotated class.</para>
<section id="beans-java-declaring-a-bean">
<title>Declaring a bean</title>
<para>To declare a bean, simply annotate a method with the
<interfacename>@Bean</interfacename> annotation. You use this method to
register a bean definition within an <code>ApplicationContext</code> of
the type specified as the method's return value. By default, the bean
name will be the same as the method name. The following is a simple
example of a <interfacename>@Bean</interfacename> method declaration:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}</programlisting></para>
<para>The preceding configuration is exactly equivalent to the following
Spring XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="transferService" class="com.acme.TransferServiceImpl"/&gt;
&lt;/beans&gt; </programlisting></para>
<para>Both declarations make a bean named <code>transferService</code>
available in the <code>ApplicationContext</code>, bound to an object
instance of type <code>TransferServiceImpl</code>:
<programlisting>
transferService -&gt; com.acme.TransferServiceImpl
</programlisting></para>
</section>
<section id="beans-java-injecting-dependencies">
<title>Injecting dependencies</title>
<para>When <interfacename>@Bean</interfacename>s have dependencies on one
another, expressing that dependency is as simple as having one bean
method call another:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
} </programlisting></para>
<para>In the example above, the <code>foo</code> bean receives a reference
to <code> bar</code> via constructor injection.</para>
</section>
<section id="beans-java-lifecycle-callbacks">
<title>Receiving lifecycle callbacks</title>
<para>Beans declared in a
<interfacename>@Configuration</interfacename>-annotated class support
the regular lifecycle callbacks. Any classes defined with the
<literal>@Bean</literal> annotation can use the
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal>
annotations from JSR-250, see <link
linkend="beans-postconstruct-and-predestroy-annotations">JSR-250
annotations</link> for further details.</para>
<para>The regular Spring <link linkend="beans-factory-nature"
>lifecycle</link> callbacks are fully supported as well. If a bean
implements <code>InitializingBean</code>, <code>DisposableBean</code>,
or <code>Lifecycle</code>, their respective methods are called by the
container.</para>
<para>The standard set of <code>*Aware</code> interfaces such as
<code><link linkend="beans-beanfactory">BeanFactoryAware</link></code>,
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>,
<code><link linkend="context-functionality-messagesource"
>MessageSourceAware</link></code>, <code><link
linkend="beans-factory-aware">ApplicationContextAware</link></code>, and
so on are also fully supported.</para>
<para>The <interfacename>@Bean</interfacename> annotation supports
specifying arbitrary initialization and destruction callback methods,
much like Spring XML's <code>init-method</code> and
<code>destroy-method</code> attributes on the <code>bean</code> element:
<programlisting language="java">public class Foo {
public void init() {
// initialization logic
}
}
public class Bar {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public Foo foo() {
return new Foo();
}
@Bean(destroyMethod = "cleanup")
public Bar bar() {
return new Bar();
}
}
</programlisting></para>
<para>Of course, in the case of <code>Foo</code> above, it would be
equally as valid to call the <code>init()</code> method directly during
construction:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.init();
return foo;
}
// ...
} </programlisting></para>
<tip>
<para>When you work directly in Java, you can do anything you like with
your objects and do not always need to rely on the container
lifecycle!</para>
</tip>
</section>
<section id="beans-java-specifying-bean-scope">
<title>Specifying bean scope</title>
<section id="beans-java-available-scopes">
<title>Using the <interfacename>@Scope</interfacename>
annotation</title>
<!-- MLP: Beverly, did not apply your edit as it changed meaning -->
<para>You can specify that your beans defined with the
<interfacename>@Bean</interfacename> annotation should have a specific
scope. You can use any of the standard scopes specified in the <link
linkend="beans-factory-scopes">Bean Scopes</link> section.</para>
<para>The default scope is <literal>singleton</literal>, but you can
override this with the <interfacename>@Scope</interfacename>
annotation:
<programlisting language="java">@Configuration
public class MyConfiguration {
@Bean
<emphasis role="bold">@Scope("prototype")</emphasis>
public Encryptor encryptor() {
// ...
}
}</programlisting></para>
</section>
<section id="beans-java-scoped-proxy">
<title><code>@Scope and scoped-proxy</code></title>
<para>Spring offers a convenient way of working with scoped dependencies
through <link linkend="beans-factory-scopes-other-injection">scoped
proxies</link>. The easiest way to create such a proxy when using the
XML configuration is the <code>&lt;aop:scoped-proxy/&gt;</code>
element. Configuring your beans in Java with a @Scope annotation
offers equivalent support with the proxyMode attribute. The default is
no proxy (<varname>ScopedProxyMode.NO</varname>), but you can specify
<classname>ScopedProxyMode.TARGET_CLASS</classname> or
<classname>ScopedProxyMode.INTERFACES</classname>.</para>
<para>If you port the scoped proxy example from the XML reference
documentation (see preceding link) to our
<interfacename>@Bean</interfacename> using Java, it would look like
the following:
<programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy
@Bean
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis>
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
} </programlisting></para>
</section>
<section id="beans-java-method-injection">
<title>Lookup method injection</title>
<para>As noted earlier, <link linkend="beans-factory-method-injection"
>lookup method injection</link> is an advanced feature that you should
use rarely. It is useful in cases where a singleton-scoped bean has a
dependency on a prototype-scoped bean. Using Java for this type of
configuration provides a natural means for implementing this pattern.
<programlisting language="java">public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
} </programlisting></para>
<para>Using Java-configuration support , you can create a subclass of
<code>CommandManager</code> where the abstract
<code>createCommand()</code> method is overridden in such a way that
it looks up a new (prototype) command object:
<programlisting language="java">@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
@Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
} </programlisting></para>
</section>
</section>
<section id="beans-java-customizing-bean-naming">
<title>Customizing bean naming</title>
<para>By default, configuration classes use a
<interfacename>@Bean</interfacename> method's name as the name of the
resulting bean. This functionality can be overridden, however, with the
<code>name</code> attribute.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = "myFoo")
public Foo foo() {
return new Foo();
}
} </programlisting></para>
</section>
<section id="beans-java-bean-aliasing">
<title>Bean aliasing</title>
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes
desirable to give a single bean multiple names, otherwise known as
<emphasis>bean aliasing</emphasis>. The <literal>name</literal>
attribute of the <literal>@Bean</literal> annotation accepts a String
array for this purpose.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
} </programlisting></para>
</section>
</section>
<section id="beans-java-further-information-java-config">
<title>Further information about how Java-based configuration works
internally</title>
<para>The following example shows a <literal>@Bean</literal> annotated
method being called twice:</para>
<programlisting language="java">
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
</programlisting>
<para> <methodname>clientDao()</methodname> has been called once in
<methodname>clientService1()</methodname> and once in
<methodname>clientService2()</methodname>. Since this method creates a new
instance of <classname>ClientDaoImpl</classname> and returns it, you would
normally expect having 2 instances (one for each service). That definitely
would be problematic: in Spring, instantiated beans have a
<literal>singleton</literal> scope by default. This is where the magic
comes in: All <literal>@Configuration</literal> classes are subclassed at
startup-time with <literal>CGLIB</literal>. In the subclass, the child
method checks the container first for any cached (scoped) beans before it
calls the parent method and creates a new instance. </para>
<note>
<para> The behavior could be different according to the scope of your
bean. We are talking about singletons here. </para>
</note>
<note>
<para> Beware that, in order for JavaConfig to work, you must include the
CGLIB jar in your list of dependencies. </para>
</note>
<note>
<para> There are a few restrictions due to the fact that CGLIB dynamically
adds features at startup-time: <itemizedlist>
<listitem>
<para>Configuration classes should not be final</para>
</listitem>
<listitem>
<para>They should have a constructor with no arguments</para>
</listitem>
</itemizedlist> </para>
</note>
</section>
</section>

View File

@ -0,0 +1,686 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<section id="beans-factory-scopes">
<title>Bean scopes</title>
<para>When you create a bean definition, you create a
<emphasis>recipe</emphasis> for creating actual instances of the class
defined by that bean definition. The idea that a bean definition is a recipe
is important, because it means that, as with a class, you can create many
object instances from a single recipe.</para>
<para>You can control not only the various dependencies and configuration
values that are to be plugged into an object that is created from a
particular bean definition, but also the <firstterm>scope</firstterm> of the
objects created from a particular bean definition. This approach is powerful
and flexible in that you can <emphasis>choose</emphasis> the scope of the
objects you create through configuration instead of having to bake in the
scope of an object at the Java class level. Beans can be defined to be
deployed in one of a number of scopes: out of the box, the Spring Framework
supports five scopes, three of which are available only if you use a
web-aware <interfacename>ApplicationContext</interfacename>.</para>
<para>The following scopes are supported out of the box. You can also create
<link linkend="beans-factory-scopes-custom">a custom scope.</link></para>
<table id="beans-factory-scopes-tbl">
<title>Bean scopes</title>
<tgroup cols="2">
<thead>
<row>
<entry align="center">Scope</entry>
<entry align="center">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><para> <link linkend="beans-factory-scopes-singleton"
>singleton</link> </para></entry>
<entry><para>(Default) Scopes a single bean definition to a single
object instance per Spring IoC container.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-prototype"
>prototype</link> </para></entry>
<entry><para>Scopes a single bean definition to any number of object
instances.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-request"
>request</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of a
single HTTP request; that is, each HTTP request has its own instance
of a bean created off the back of a single bean definition. Only
valid in the context of a web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-session"
>session</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of an
HTTP <interfacename>Session</interfacename>. Only valid in the
context of a web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
<row>
<entry><para> <link linkend="beans-factory-scopes-global-session"
>global session</link> </para></entry>
<entry><para>Scopes a single bean definition to the lifecycle of a
global HTTP <interfacename>Session</interfacename>. Typically only
valid when used in a portlet context. Only valid in the context of a
web-aware Spring
<interfacename>ApplicationContext</interfacename>.</para></entry>
</row>
</tbody>
</tgroup>
</table>
<note>
<title>Thread-scoped beans</title>
<para>As of Spring 3.0, a <emphasis>thread scope</emphasis> is available,
but is not registered by default. For more information, see the
documentation for <ulink
url="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/support/SimpleThreadScope.html"
>SimpleThreadScope</ulink>. For instructions on how to register this or
any other custom scope, see <xref
linkend="beans-factory-scopes-custom-using"/>.</para>
</note>
<section id="beans-factory-scopes-singleton">
<title>The singleton scope</title>
<para>Only one <emphasis>shared</emphasis> instance of a singleton bean is
managed, and all requests for beans with an id or ids matching that bean
definition result in that one specific bean instance being returned by the
Spring container.</para>
<para>To put it another way, when you define a bean definition and it is
scoped as a singleton, the Spring IoC container creates <emphasis>exactly
one</emphasis> instance of the object defined by that bean definition.
This single instance is stored in a cache of such singleton beans, and
<emphasis>all subsequent requests and references</emphasis> for that named
bean return the cached object.</para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/singleton.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/singleton.png" format="PNG"/>
</imageobject>
</mediaobject></para>
<para>Spring's concept of a singleton bean differs from the Singleton
pattern as defined in the Gang of Four (GoF) patterns book. The GoF
Singleton hard-codes the scope of an object such that one <emphasis>and
only one</emphasis> instance of a particular class is created<emphasis>
per <classname>ClassLoader</classname></emphasis>. The scope of the Spring
singleton is best described as <emphasis>per container and per
bean</emphasis>. This means that if you define one bean for a particular
class in a single Spring container, then the Spring container creates one
<emphasis>and only one</emphasis> instance of the class defined by that
bean definition. <emphasis>The singleton scope is the default scope in
Spring</emphasis>. To define a bean as a singleton in XML, you would
write, for example:</para>
<programlisting language="xml">&lt;bean id="accountService" class="com.foo.DefaultAccountService"/&gt;
<lineannotation>&lt;!-- the following is equivalent, though redundant (singleton scope is the default) --&gt;</lineannotation>
&lt;bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/&gt;</programlisting>
</section>
<section id="beans-factory-scopes-prototype">
<title>The prototype scope</title>
<para>The non-singleton, prototype scope of bean deployment results in the
<emphasis>creation of a new bean instance</emphasis> every time a request
for that specific bean is made. That is, the bean is injected into another
bean or you request it through a <literal>getBean()</literal> method call
on the container. As a rule, use the prototype scope for all stateful
beans and the singleton scope for stateless beans.</para>
<para>The following diagram illustrates the Spring prototype scope.
<emphasis>A data access object (DAO) is not typically configured as a
prototype, because a typical DAO does not hold any conversational state;
it was just easier for this author to reuse the core of the singleton
diagram.</emphasis><!--First it says diagram illustrates scope, but then says it's not typical of a prototype scope. Why not use realistic one? --></para>
<para><mediaobject>
<imageobject role="fo">
<imagedata align="center" fileref="images/prototype.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata align="center" fileref="images/prototype.png" format="PNG"/>
</imageobject>
</mediaobject></para>
<para>The following example defines a bean as a prototype in XML:</para>
<programlisting language="xml"><lineannotation>&lt;!-- using <literal>spring-beans-2.0.dtd</literal> --&gt;</lineannotation>
&lt;bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/&gt;</programlisting>
<para>In contrast to the other scopes, Spring does not manage the complete
lifecycle of a prototype bean: the container instantiates, configures, and
otherwise assembles a prototype object, and hands it to the client, with
no further record of that prototype instance. Thus, although
<emphasis>initialization</emphasis> lifecycle callback methods are called
on all objects regardless of scope, in the case of prototypes, configured
<emphasis>destruction</emphasis> lifecycle callbacks are
<emphasis>not</emphasis> called. The client code must clean up
prototype-scoped objects and release expensive resources that the
prototype bean(s) are holding. To get the Spring container to release
resources held by prototype-scoped beans, try using a custom <link
linkend="beans-factory-extension-bpp">bean post-processor</link>, which
holds a reference to beans that need to be cleaned up.</para>
<para>In some respects, the Spring container's role in regard to a
prototype-scoped bean is a replacement for the Java <literal>new</literal>
operator. All lifecycle management past that point must be handled by the
client. (For details on the lifecycle of a bean in the Spring container,
see <xref linkend="beans-factory-lifecycle"/>.)</para>
</section>
<section id="beans-factory-scopes-sing-prot-interaction">
<title>Singleton beans with prototype-bean dependencies</title>
<para>When you use singleton-scoped beans with dependencies on prototype
beans, be aware that <emphasis>dependencies are resolved at instantiation
time</emphasis>. Thus if you dependency-inject a prototype-scoped bean
into a singleton-scoped bean, a new prototype bean is instantiated and
then dependency-injected into the singleton bean. The prototype instance
is the sole instance that is ever supplied to the singleton-scoped
bean.</para>
<para>However, suppose you want the singleton-scoped bean to acquire a new
instance of the prototype-scoped bean repeatedly at runtime. You cannot
dependency-inject a prototype-scoped bean into your singleton bean,
because that injection occurs only <emphasis>once</emphasis>, when the
Spring container is instantiating the singleton bean and resolving and
injecting its dependencies. If you need a new instance of a prototype bean
at runtime more than once, see <xref
linkend="beans-factory-method-injection"/></para>
</section>
<section id="beans-factory-scopes-other">
<title>Request, session, and global session scopes</title>
<para>The <literal>request</literal>, <literal>session</literal>, and
<literal>global session</literal> scopes are <emphasis>only</emphasis>
available if you use a web-aware Spring
<interfacename>ApplicationContext</interfacename> implementation (such as
<classname>XmlWebApplicationContext</classname>). If you use these scopes
with regular Spring IoC containers such as the
<classname>ClassPathXmlApplicationContext</classname>, you get an
<classname>IllegalStateException</classname> complaining about an unknown
bean scope.</para>
<section id="beans-factory-scopes-other-web-configuration">
<title>Initial web configuration</title>
<para>To support the scoping of beans at the <literal>request</literal>,
<literal>session</literal>, and <literal>global session</literal> levels
(web-scoped beans), some minor initial configuration is required before
you define your beans. (This initial setup is <emphasis>not</emphasis>
required for the standard scopes, singleton and prototype.)</para>
<para>How you accomplish this initial setup depends on your particular
Servlet environment..</para>
<para>If you access scoped beans within Spring Web MVC, in effect, within
a request that is processed by the Spring
<classname>DispatcherServlet</classname>, or
<classname>DispatcherPortlet</classname>, then no special setup is
necessary: <classname>DispatcherServlet</classname> and
<classname>DispatcherPortlet</classname> already expose all relevant
state.</para>
<para>If you use a Servlet 2.4+ web container, with requests processed
outside of Spring's DispatcherServlet (for example, when using JSF or
Struts), you need to add the following
<interfacename>javax.servlet.ServletRequestListener</interfacename> to
the declarations in your web applications <literal>web.xml</literal>
file:</para>
<programlisting language="xml">&lt;web-app&gt;
...
&lt;listener&gt;
&lt;listener-class&gt;
org.springframework.web.context.request.RequestContextListener
&lt;/listener-class&gt;
&lt;/listener&gt;
...
&lt;/web-app&gt;</programlisting>
<para>If you use an older web container (Servlet 2.3), use the provided
<interfacename>javax.servlet.Filter</interfacename> implementation. The
following snippet of XML configuration must be included in the
<literal>web.xml</literal> file of your web application if you want to
access web-scoped beans in requests outside of Spring's
DispatcherServlet on a Servlet 2.3 container. (The filter mapping
depends on the surrounding web application configuration, so you must
change it as appropriate.)</para>
<programlisting language="xml">&lt;web-app&gt;
..
&lt;filter&gt;
&lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
&lt;filter-class&gt;org.springframework.web.filter.RequestContextFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;requestContextFilter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
...
&lt;/web-app&gt;</programlisting>
<para><classname>DispatcherServlet</classname>,
<classname>RequestContextListener</classname> and
<classname>RequestContextFilter</classname> all do exactly the same
thing, namely bind the HTTP request object to the
<classname>Thread</classname> that is servicing that request. This makes
beans that are request- and session-scoped available further down the
call chain.</para>
</section>
<section id="beans-factory-scopes-request">
<title>Request scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="loginAction" class="com.foo.LoginAction" scope="request"/&gt;</programlisting>
<para>The Spring container creates a new instance of the
<classname>LoginAction</classname> bean by using the
<literal>loginAction</literal> bean definition for each and every HTTP
request. That is, the <literal>loginAction</literal> bean is scoped at
the HTTP request level. You can change the internal state of the
instance that is created as much as you want, because other instances
created from the same <literal>loginAction</literal> bean definition
will not see these changes in state; they are particular to an
individual request. When the request completes processing, the bean that
is scoped to the request is discarded.</para>
</section>
<section id="beans-factory-scopes-session">
<title>Session scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/&gt;</programlisting>
<para>The Spring container creates a new instance of the
<classname>UserPreferences</classname> bean by using the
<literal>userPreferences</literal> bean definition for the lifetime of a
single HTTP <interfacename>Session</interfacename>. In other words, the
<literal>userPreferences</literal> bean is effectively scoped at the
HTTP <interfacename>Session</interfacename> level. As with
<literal>request-scoped</literal> beans, you can change the internal
state of the instance that is created as much as you want, knowing that
other HTTP <interfacename>Session</interfacename> instances that are
also using instances created from the same
<literal>userPreferences</literal> bean definition do not see these
changes in state, because they are particular to an individual HTTP
<interfacename>Session</interfacename>. When the HTTP
<interfacename>Session</interfacename> is eventually discarded, the bean
that is scoped to that particular HTTP
<interfacename>Session</interfacename> is also discarded.</para>
</section>
<section id="beans-factory-scopes-global-session">
<title>Global session scope</title>
<para>Consider the following bean definition:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/&gt;</programlisting>
<para>The <literal>global session</literal> scope is similar to the
standard HTTP <interfacename>Session</interfacename> scope (<link
linkend="beans-factory-scopes-session">described above</link>), and
applies only in the context of portlet-based web applications. The
portlet specification defines the notion of a global
<interfacename>Session</interfacename> that is shared among all portlets
that make up a single portlet web application. Beans defined at the
<literal>global session</literal> scope are scoped (or bound) to the
lifetime of the global portlet
<interfacename>Session</interfacename>.</para>
<para>If you write a standard Servlet-based web application and you define
one or more beans as having <literal>global session</literal> scope, the
standard HTTP <interfacename>Session</interfacename> scope is used, and
no error is raised.</para>
</section>
<section id="beans-factory-scopes-other-injection">
<title>Scoped beans as dependencies</title>
<para>The Spring IoC container manages not only the instantiation of your
objects (beans), but also the wiring up of collaborators (or
dependencies). If you want to inject (for example) an HTTP request
scoped bean into another bean, you must inject an AOP proxy in place of
the scoped bean. That is, you need to inject a proxy object that exposes
the same public interface as the scoped object but that can also
retrieve the real, target object from the relevant scope (for example,
an HTTP request) and delegate method calls onto the real object.</para>
<note>
<para>You <emphasis>do not</emphasis> need to use the
<literal>&lt;aop:scoped-proxy/&gt;</literal> in conjunction with beans
that are scoped as <literal>singletons</literal> or
<literal>prototypes</literal>. If you try to create a scoped proxy for
a singleton bean, the
<exceptionname>BeanCreationException</exceptionname> is raised.</para>
</note>
<para>The configuration in the following example is only one line, but it
is important to understand the <quote>why</quote> as well as the
<quote>how</quote> behind it.</para>
<!--What is this example supposed to show?-->
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
<lineannotation>&lt;!-- an HTTP <interfacename>Session</interfacename>-scoped bean exposed as a proxy --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.UserPreferences" <emphasis role="bold">scope="session"</emphasis>&gt;
<lineannotation>&lt;!-- this next element effects the proxying of the surrounding bean --&gt;</lineannotation>
<emphasis role="bold">&lt;aop:scoped-proxy/&gt;</emphasis>
&lt;/bean&gt;
<lineannotation>&lt;!-- a singleton-scoped bean <emphasis role="bold">injected with a proxy to the above bean</emphasis> --&gt;</lineannotation>
&lt;bean id="userService" class="com.foo.SimpleUserService"&gt;
<lineannotation>&lt;!-- a reference to the <emphasis role="bold">proxied</emphasis> <literal>userPreferences</literal> bean --&gt;</lineannotation>
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</programlisting>
<para>To create such a proxy, you insert a child
<literal>&lt;aop:scoped-proxy/&gt;</literal> element into a scoped bean
definition.
<!--To create what such proxy? Is the proxy created above? Also, below added an x-ref that seems relevant.-->(If
you choose class-based proxying, you also need the CGLIB library in your
classpath. See <xref
linkend="beans-factory-scopes-other-injection-proxies"/> and <xref
linkend="xsd-config"/>.) Why do definitions of beans scoped at the
<literal>request</literal>, <literal>session</literal>,
<literal>globalSession</literal> and custom-scope levels require the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element ? Let's examine the
following singleton bean definition and contrast it with what you need
to define for the aforementioned scopes. (The following
<literal>userPreferences</literal> bean definition as it stands is
<emphasis>incomplete.)</emphasis></para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<para>In the preceding example, the singleton bean
<literal>userManager</literal> is injected with a reference to the HTTP
<interfacename>Session</interfacename>-scoped bean
<literal>userPreferences</literal>. The salient point here is that the
<literal>userManager</literal> bean is a singleton: it will be
instantiated <emphasis>exactly once</emphasis> per container, and its
dependencies (in this case only one, the
<literal>userPreferences</literal> bean) are also injected only once.
This means that the <literal>userManager</literal> bean will only
operate on the exact same <literal>userPreferences</literal> object,
that is, the one that it was originally injected with.</para>
<!-- MLP: Beverly to review paragraph -->
<para>This is <emphasis>not</emphasis> the behavior you want when
injecting a shorter-lived scoped bean into a longer-lived scoped bean,
for example injecting an HTTP
<interfacename>Session</interfacename>-scoped collaborating bean as a
dependency into singleton bean. Rather, you need a single
<literal>userManager</literal> object, and for the lifetime of an HTTP
<interfacename>Session</interfacename>, you need a
<literal>userPreferences</literal> object that is specific to said HTTP
<interfacename>Session</interfacename>. Thus the container creates an
object that exposes the exact same public interface as the
<classname>UserPreferences</classname> class (ideally an object that
<emphasis>is a</emphasis> <classname>UserPreferences</classname>
instance) which can fetch the real
<classname>UserPreferences</classname> object from the scoping mechanism
(HTTP request, <interfacename>Session</interfacename>, etc.). The
container injects this proxy object into the
<literal>userManager</literal> bean, which is unaware that this
<classname>UserPreferences</classname> reference is a proxy. In this
example, when a <interfacename>UserManager</interfacename> instance
invokes a method on the dependency-injected
<classname>UserPreferences</classname> object, it actually is invoking a
method on the proxy. The proxy then fetches the real
<classname>UserPreferences</classname> object from (in this case) the
HTTP <interfacename>Session</interfacename>, and delegates the method
invocation onto the retrieved real
<classname>UserPreferences</classname> object.</para>
<para>Thus you need the following, correct and complete, configuration
when injecting <literal>request-</literal>, <literal>session-</literal>,
and <literal>globalSession-scoped</literal> beans into collaborating
objects:</para>
<programlisting language="xml">&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"&gt;
<emphasis role="bold"><literal>&lt;aop:scoped-proxy/&gt;</literal></emphasis>
&lt;/bean&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<section id="beans-factory-scopes-other-injection-proxies">
<title>Choosing the type of proxy to create</title>
<para>By default, when the Spring container creates a proxy for a bean
that is marked up with the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element, <emphasis>a
CGLIB-based class proxy is created</emphasis>. This means that you
need to have the CGLIB library in the classpath of your
application.</para>
<para><emphasis>Note: CGLIB proxies only intercept public method
calls!</emphasis> Do not call non-public methods on such a proxy; they
will not be delegated to the scoped target object.</para>
<para>Alternatively, you can configure the Spring container to create
standard JDK interface-based proxies for such scoped beans, by
specifying <literal>false</literal> for the value of the
<literal>proxy-target-class</literal> attribute of the
<literal>&lt;aop:scoped-proxy/&gt;</literal> element. Using JDK
interface-based proxies means that you do not need additional
libraries in your application classpath to effect such proxying.
However, it also means that the class of the scoped bean must
implement at least one interface, and <emphasis>that all</emphasis>
collaborators into which the scoped bean is injected must reference
the bean through one of its interfaces.</para>
<programlisting language="xml"><lineannotation>&lt;!-- <classname>DefaultUserPreferences</classname> implements the <interfacename>UserPreferences</interfacename> interface --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"&gt;
&lt;aop:scoped-proxy <emphasis role="bold">proxy-target-class="false"<literal/></emphasis>/&gt;
&lt;/bean&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<para>For more detailed information about choosing class-based or
interface-based proxying, see <xref linkend="aop-proxying"/>.</para>
</section>
</section>
</section>
<section id="beans-factory-scopes-custom">
<title>Custom scopes</title>
<para>As of Spring 2.0, the bean scoping mechanism is extensible. You can
define your own scopes, or even redefine existing scopes, although the
latter is considered bad practice and you <emphasis>cannot</emphasis>
override the built-in <literal>singleton</literal> and
<literal>prototype</literal> scopes.</para>
<section id="beans-factory-scopes-custom-creating">
<title>Creating a custom scope</title>
<para>To integrate your custom scope(s) into the Spring container, you
need to implement the
<interfacename>org.springframework.beans.factory.config.Scope</interfacename>
interface, which is described in this section. For an idea of how to
implement your own scopes, see the <interfacename>Scope</interfacename>
implementations that are supplied with the Spring Framework itself and
the <ulink
url="http://static.springframework.org/spring/docs/3.0.x/javadoc-api/org/springframework/beans/factory/config/Scope.html"
>Scope Javadoc</ulink>, which explains the methods you need to implement
in more detail.</para>
<para>The <literal>Scope</literal> interface has four methods to get
objects from the scope, remove them from the scope, and allow them to be
destroyed.</para>
<para>The following method returns the object from the underlying scope.
The session scope implementation, for example, returns the
session-scoped bean (and if it does not exist, the method returns a new
instance of the bean, after having bound it to the session for future
reference).<!--How can it return a a new instance of a bean that doesn't exist? Revise to clarify.--></para>
<programlisting language="java">Object get(String name, ObjectFactory objectFactory)</programlisting>
<para>The following method removes the object from the underlying scope.
The session scope implementation for example, removes the session-scoped
bean from the underlying session. The object should be returned, but you
can return null if the object with the specified name is not
found.</para>
<programlisting language="java">Object remove(String name)</programlisting>
<para>The following method registers the callbacks the scope should
execute when it is destroyed or when the specified object in the scope
is destroyed. Refer to the Javadoc or a Spring scope implementation for
more information on destruction callbacks.</para>
<programlisting language="java">void registerDestructionCallback(String name, Runnable destructionCallback)</programlisting>
<para>The following method obtains the conversation identifier for the
underlying scope. This identifier is different for each scope. For a
session scoped implementation, this identifier can be the session
identifier.</para>
<programlisting language="java">String getConversationId()</programlisting>
</section>
<section id="beans-factory-scopes-custom-using">
<title>Using a custom scope</title>
<para>After you write and test one or more custom
<interfacename>Scope</interfacename> implementations, you need to make
the Spring container aware of your new scope(s). The following method is
the central method to register a new
<interfacename>Scope</interfacename> with the Spring container:</para>
<programlisting language="java">void registerScope(String scopeName, Scope scope);</programlisting>
<para>This method is declared on the
<interfacename>ConfigurableBeanFactory</interfacename> interface, which
is available on most of the concrete
<interfacename>ApplicationContext</interfacename> implementations that
ship with Spring via the BeanFactory property.</para>
<para>The first argument to the <methodname>registerScope(..)</methodname>
method is the unique name associated with a scope; examples of such
names in the Spring container itself are <literal>singleton</literal>
and <literal>prototype</literal>. The second argument to the
<methodname>registerScope(..)</methodname> method is an actual instance
of the custom <interfacename>Scope</interfacename> implementation that
you wish to register and use.</para>
<para>Suppose that you write your custom
<interfacename>Scope</interfacename> implementation, and then register
it as below.</para>
<note>
<para>The example below uses <literal>SimpleThreadScope</literal> which
is included with Spring, but not registered by default. The
instructions would be the same for your own custom
<literal>Scope</literal> implementations.</para>
</note>
<programlisting language="java">
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("<emphasis role="bold">thread</emphasis>", threadScope);</programlisting>
<para>You then create bean definitions that adhere to the scoping rules of
your custom <interfacename>Scope</interfacename>:</para>
<programlisting language="xml">&lt;bean id="..." class="..." scope="thread"&gt;</programlisting>
<para>With a custom <interfacename>Scope</interfacename> implementation,
you are not limited to programmatic registration of the scope. You can
also do the <interfacename>Scope</interfacename> registration
declaratively, using the <classname>CustomScopeConfigurer</classname>
class:</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"&gt;
&lt;property name="scopes"&gt;
&lt;map&gt;<emphasis role="bold">
&lt;entry key="thread"&gt;
&lt;bean class="org.springframework.context.support.SimpleThreadScope"/&gt;
&lt;/entry&gt;</emphasis>
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="bar" class="x.y.Bar" scope="thread"&gt;
&lt;property name="name" value="Rick"/&gt;
&lt;aop:scoped-proxy/&gt;
&lt;/bean&gt;
&lt;bean id="foo" class="x.y.Foo"&gt;
&lt;property name="bar" ref="bar"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<note>
<para>When you place &lt;aop:scoped-proxy/&gt; 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>

File diff suppressed because it is too large Load Diff