Poish asciidoctor

Issues: SPR-10960
grate documentation to #	deleted:    src/reference/docbook/index.xml
This commit is contained in:
Rob Winch 2013-11-05 11:01:30 -06:00
parent 2e57cf8bfc
commit 3476d11fb8
50 changed files with 16 additions and 63720 deletions

View File

@ -1,7 +1,7 @@
= Spring Framework Reference Documentation
Rod Johnson; Juergen Hoeller; Keith Donald; Colin Sampaleanu; Rob Harrop; Thomas Risberg; Alef Arendsen; Darren Davison; Dmitriy Kopylenko; Mark Pollack; Thierry Templier; Erwin Vervaet; Portia Tung; Ben Hale; Adrian Colyer; John Lewis; Costin Leau; Mark Fisher; Sam Brannen; Ramnivas Laddad; Arjen Poutsma; Chris Beams; Tareq Abedrabbo; Andy Clement; Dave Syer; Oliver Gierke; Rossen Stoyanchev; Phillip Webb; Rob Winch
Core support for dependency injection, transaction management, web applications, data access, messaging, testing and more.
rCore support for dependency injection, transaction management, web applications, data access, messaging, testing and more.
__Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.__
@ -17,7 +17,7 @@ This document is a reference guide to Spring Framework features. If you have any
== Introduction to Spring Framework
Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.
Spring enables you to build applications from “plain old Java objects” (POJOs) and to apply enterprise services non-invasively to POJOs. This capability applies to the Java SE programming model and to full and partial Java EE.
Spring enables you to build applications from "plain old Java objects" (POJOs) and to apply enterprise services non-invasively to POJOs. This capability applies to the Java SE programming model and to full and partial Java EE.
Examples of how you, as an application developer, can use the Spring platform advantage:
@ -1005,7 +1005,7 @@ Finally, the adoption of the test-driven-development (TDD) approach to software
=== Introduction to the Spring IoC container and beans
This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) footnote:[See pass:specialcharacters,macros[<<background-ioc>>] ] principle. IoC is also known as __dependency injection__ (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then __injects__ those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name __Inversion of Control__ (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the __Service Locator__ pattern.
The `org.springframework.beans` and `org.springframework.context` packages are the basis for Spring Framework's IoC container. The `http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html[BeanFactory]` interface provides an advanced configuration mechanism capable of managing any type of object. `http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html[ApplicationContext]` is a sub-interface of `BeanFactory`. It adds easier integration with Spring's AOP features; message resource handling (for use in internationalization), event publication; and application-layer specific contexts such as the `WebApplicationContext` for use in web applications.
The `org.springframework.beans` and `org.springframework.context` packages are the basis for Spring Framework's IoC container. The http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html[BeanFactory] interface provides an advanced configuration mechanism capable of managing any type of object. http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html[ApplicationContext] is a sub-interface of `BeanFactory`. It adds easier integration with Spring's AOP features; message resource handling (for use in internationalization), event publication; and application-layer specific contexts such as the `WebApplicationContext` for use in web applications.
In short, the `BeanFactory` provides the configuration framework and basic functionality, and the `ApplicationContext` adds more enterprise-specific functionality. The `ApplicationContext` is a complete superset of the `BeanFactory`, and is used exclusively in this chapter in descriptions of Spring's IoC container.For more information on using the `BeanFactory` instead of the `ApplicationContext,` refer to <<beans-beanfactory>>.
@ -1410,7 +1410,7 @@ public class DefaultServiceLocator {
}
----
This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See <<beans-factory-properties-detailed,<<beans-factory-properties-detailed,Dependencies and configuration in detail>>.>>
This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See <<beans-factory-properties-detailed,Dependencies and configuration in detail>>.
[NOTE]
====
@ -1549,7 +1549,7 @@ As of Spring 3.0 you can also use the constructor parameter name for value disam
</bean>
----
Keep in mind that to make this work out of the box your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you can't compile your code with debug flag (or don't want to) you can use `http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties]` JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:
Keep in mind that to make this work out of the box your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you can't compile your code with debug flag (or don't want to) you can use http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties] JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:
[source,java]
[subs="verbatim,quotes"]
@ -4896,7 +4896,7 @@ A `WebApplicationContext` variant of `AnnotationConfigApplicationContext` is ava
[[beans-java-bean-annotation]]
==== Using the @Bean annotation
`@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element. The annotation supports some of the attributes offered by `<bean/>`, such as: `<<beans-factory-lifecycle-initializingbean,init-method>>`, `<<beans-factory-lifecycle-disposablebean,destroy-method>>`, `<<beans-factory-autowire,autowiring>>` and `name`.
`@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element. The annotation supports some of the attributes offered by `<bean/>`, such as: <<beans-factory-lifecycle-initializingbean,init-method>>, <<beans-factory-lifecycle-disposablebean,destroy-method>>, <<beans-factory-autowire,autowiring>> and `name`.
You can use the `@Bean` annotation in a `@Configuration`-annotated or in a `@Component`-annotated class.
@ -4942,7 +4942,7 @@ Any classes defined with the `@Bean` annotation support the regular lifecycle ca
The regular Spring <<beans-factory-nature,lifecycle>> callbacks are fully supported as well. If a bean implements `InitializingBean`, `DisposableBean`, or `Lifecycle`, their respective methods are called by the container.
The standard set of `*Aware` interfaces such as `<<beans-beanfactory,BeanFactoryAware>>`, `<<beans-factory-aware,BeanNameAware>>`, `<<context-functionality-messagesource,MessageSourceAware>>`, `<<beans-factory-aware,ApplicationContextAware>>`, and so on are also fully supported.
The standard set of `*Aware` interfaces such as <<beans-beanfactory,BeanFactoryAware>>, <<beans-factory-aware,BeanNameAware>>, <<context-functionality-messagesource,MessageSourceAware>>, <<beans-factory-aware,ApplicationContextAware>>, and so on are also fully supported.
The `@Bean` annotation supports specifying arbitrary initialization and destruction callback methods, much like Spring XML's `init-method` and `destroy-method` attributes on the `bean` element:
@ -15257,15 +15257,15 @@ The `@Transactional` annotation is metadata that specifies that an interface, cl
These default settings can be changed; the various properties of the `@Transactional` annotation are summarized in the following table:
[[tx-attransactional-properties]]
.@Transactional properties
.@
|===
| Property| Type| Description
a| `<<tx-multiple-tx-mgrs-with-attransactional,value>>`
a| <<tx-multiple-tx-mgrs-with-attransactional,value>>
| String
| Optional qualifier specifying the transaction manager to be used.
a| `<<tx-propagation,propagation>>`
a| <<tx-propagation,propagation>>
| enum: `Propagation`
| Optional propagation setting.
@ -25256,7 +25256,7 @@ This can be very valuable since you can then use interceptors to pre-process and
=== Handler mappings
Using a handler mapping you can map incoming portlet requests to appropriate handlers. There are some handler mappings you can use out of the box, for example, the `PortletModeHandlerMapping`, but let's first examine the general concept of a `HandlerMapping`.
Note: We are intentionally using the term “Handler” here instead of “Controller”. `DispatcherPortlet` is designed to be used with other ways to process requests than just Spring Portlet MVCs own Controllers. A Handler is any Object that can handle portlet requests. Controllers are an example of Handlers, and they are of course the default. To use some other framework with `DispatcherPortlet`, a corresponding implementation of `HandlerAdapter` is all that is needed.
Note: We are intentionally using the term "Handler" here instead of "Controller". `DispatcherPortlet` is designed to be used with other ways to process requests than just Spring Portlet MVCs own Controllers. A Handler is any Object that can handle portlet requests. Controllers are an example of Handlers, and they are of course the default. To use some other framework with `DispatcherPortlet`, a corresponding implementation of `HandlerAdapter` is all that is needed.
The functionality a basic `HandlerMapping` provides is the delivering of a `HandlerExecutionChain`, which must contain the handler that matches the incoming request, and may also contain a list of handler interceptors that are applied to the request. When a request comes in, the `DispatcherPortlet` will hand it over to the handler mapping to let it inspect the request and come up with an appropriate `HandlerExecutionChain`. Then the `DispatcherPortlet` will execute the handler and interceptors in the chain (if any). These concepts are all exactly the same as in Spring Web MVC.
@ -25302,7 +25302,7 @@ The bean configuration for this mapping will look something like this:
[source,xml]
[subs="verbatim,quotes"]
----
<bean class="org.springframework.web.portlet.handler.ParameterHandlerMapping>
<bean class="org.springframework.web.portlet.handler.ParameterHandlerMapping">
<property name="parameterMap">
<map>
<entry key="add" value-ref="addItemHandler"/>
@ -25432,7 +25432,7 @@ After the `PortletMultipartResolver` has finished doing its job, the request wil
</form>
----
As you can see, we've created a field named “file” that matches the property of the bean that holds the `byte[]` array. Furthermore we've added the encoding attribute ( `enctype="multipart/form-data"`), which is necessary to let the browser know how to encode the multipart fields (do not forget this!).
As you can see, we've created a field named "file" that matches the property of the bean that holds the `byte[]` array. Furthermore we've added the encoding attribute ( `enctype="multipart/form-data"`), which is necessary to let the browser know how to encode the multipart fields (do not forget this!).
Just as with any other property that's not automagically convertible to a string or primitive type, to be able to put binary data in your objects you have to register a custom editor with the `PortletRequestDataBinder`. There are a couple of editors available for handling files and setting the results on an object. There's a `StringMultipartFileEditor` capable of converting files to Strings (using a user-defined character set), and there is a `ByteArrayMultipartFileEditor` which converts files to byte arrays. They function analogous to the `CustomDateEditor`.
@ -25877,7 +25877,7 @@ The process of deploying a Spring Portlet MVC application is no different than d
Generally, the portal/portlet container runs in one webapp in your servlet container and your portlets run in another webapp in your servlet container. In order for the portlet container webapp to make calls into your portlet webapp it must make cross-context calls to a well-known servlet that provides access to the portlet services defined in your `portlet.xml` file.
The JSR-168 specification does not specify exactly how this should happen, so each portlet container has its own mechanism for this, which usually involves some kind of “deployment process” that makes changes to the portlet webapp itself and then registers the portlets within the portlet container.
The JSR-168 specification does not specify exactly how this should happen, so each portlet container has its own mechanism for this, which usually involves some kind of "deployment process" that makes changes to the portlet webapp itself and then registers the portlets within the portlet container.
At a minimum, the `web.xml` file in your portlet webapp is modified to inject the well-known servlet that the portlet container will call. In some cases a single servlet will service all portlets in the webapp, in other cases there will be an instance of the servlet for each portlet.
@ -31256,7 +31256,7 @@ Please note that in order to effect the automatic 'pickup' of any changes to dyn
Find below an example of a Spring `org.springframework.validation.Validator` implemented using the Groovy dynamic language. (See <<validator>> for a discussion of the `Validator` interface.)
[source,grovy]
[source,groovy]
[subs="verbatim,quotes"]
----
import org.springframework.validation.Validator
@ -31628,7 +31628,7 @@ The caching abstraction allows one to use her own annotations to identify what m
----
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(value=“books”, key="#isbn")
@Cacheable(value="books", key="#isbn")
public @interface SlowService {
}
----

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,806 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-annotation-config"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<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 <link xl:href="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</link>.</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. Spring 2.5 made it 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 added support for JSR-250 annotations
such as <interfacename>@PostConstruct</interfacename>, and
<interfacename>@PreDestroy</interfacename>. Spring 3.0 added support for
JSR-330 (Dependency Injection for Java) annotations contained in the
javax.inject package such as <classname>@Inject</classname> and
<literal> @Named</literal>. Details about those annotations can be found in the <link linkend="beans-standard-annotations"
>relevant section</link>. <note><para>Annotation injection is performed
<emphasis>before</emphasis> XML injection, thus the latter configuration
will override the former for properties wired through both approaches.
</para></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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"&gt;
<lineannotation>&lt;context:annotation-config/&gt;</lineannotation>
&lt;/beans&gt;</programlisting>
<para>(The implicitly registered post-processors include <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html"
><classname>AutowiredAnnotationBeanPostProcessor</classname></link>, <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html"
><classname>CommonAnnotationBeanPostProcessor</classname></link>, <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.html"
><classname>PersistenceAnnotationBeanPostProcessor</classname></link>, as
well as the aforementioned <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/RequiredAnnotationBeanPostProcessor.html"
><classname>RequiredAnnotationBeanPostProcessor</classname></link>.)</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 xml: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 xml:id="beans-autowired-annotation">
<title><interfacename>@Autowired</interfacename></title>
<para>As expected, you can apply the
<interfacename>@Autowired</interfacename> annotation to "traditional"
setter methods:</para>
<programlisting language="java">public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
<note>
<para>JSR 330's @Inject annotation can be used in place of Spring's
<interfacename>@Autowired</interfacename> annotation in the examples below. See <link linkend="beans-standard-annotations"
>here</link> for more details</para>
</note>
<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>Environment</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>
<note>
<para>
<interfacename>@Autowired</interfacename>,
<interfacename>@Inject</interfacename>,
<interfacename>@Resource</interfacename>, and
<interfacename>@Value</interfacename> annotations are handled by a
Spring <interfacename>BeanPostProcessor</interfacename> implementations
which in turn means that you <emphasis>cannot</emphasis>
apply these annotations within your own
<classname>BeanPostProcessor</classname> or
<classname>BeanFactoryPostProcessor</classname> types (if any). These
types must be 'wired up' explicitly via XML or using a Spring
<interfacename>@Bean</interfacename> method.</para>
</note>
</section>
<section xml: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>
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.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>
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.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 xml:id="beans-custom-autowire-configurer">
<title><classname>CustomAutowireConfigurer</classname></title>
<para>The <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/CustomAutowireConfigurer.html"
><classname>CustomAutowireConfigurer</classname></link> 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 xml: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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/jndi/support/SimpleJndiBeanFactory.html"
><classname>SimpleJndiBeanFactory</classname></link> 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 xml: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

@ -1,514 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-classpath-scanning"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Classpath scanning and managed components</title>
<para>Most examples in this chapter use XML to specify the configuration
metadata that produces each <interfacename>BeanDefinition</interfacename>
within the Spring container. The previous section
(<xref linkend="beans-annotation-config"/>) demonstrates how to provide a
lot of the configuration metadata through source-level annotations. Even
in those examples, however, the "base" bean definitions are explicitly
defined in the XML file, while the annotations only drive the dependency
injection. This section describes an option for implicitly detecting the
<emphasis>candidate components</emphasis> by scanning the classpath.
Candidate components are classes that match against a filter criteria and
have a corresponding bean definition registered with the container. This
removes the need to use XML to perform bean registration, instead you can
use annotations (for example @Component), AspectJ type expressions, or your
own custom filter criteria to select which classes will have bean
definitions registered with the container.</para>
<note>
<para>Starting with Spring 3.0, many features provided by the <link
xl:href="http://www.springsource.org/javaconfig">Spring JavaConfig
project</link> 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 xml: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 xml: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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"&gt;
&lt;context:component-scan base-package="org.example"/&gt;
&lt;/beans&gt;</programlisting>
<tip>
<para>The use of <literal>&lt;context:component-scan&gt;</literal> implicitly
enables the functionality of <literal>&lt;context:annotation-config&gt;</literal>.
There is usually no need to include the <literal>&lt;context:annotation-config&gt;</literal>
element when using <literal>&lt;context:component-scan&gt;</literal>.
</para>
</tip>
<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
stereotype 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 xml: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 xml: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 xml: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
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 xml: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>
<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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/support/BeanNameGenerator.html"
><interfacename>BeanNameGenerator</interfacename></link> 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 xml: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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html"
><interfacename>ScopeMetadataResolver</interfacename></link> 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 xml: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

@ -1,668 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="context-introduction"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html"
><interfacename>ApplicationContext</interfacename></link> 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 xml: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 MessageSource 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="exceptions"/&gt;
&lt;/bean&gt;
<lineannotation>&lt;!-- lets inject the above MessageSource 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 xml: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 xml: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 shows 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>known.spammer@example.org</value>
<value>known.hacker@example.org</value>
<value>john.doe@example.org</value>
</list>
</property>
</bean>
<bean id="blackListNotifier" class="example.BlackListNotifier">
<property name="notificationAddress" value="blacklist@example.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 <link
xl:href="http://springsource.org/spring-integration">Spring
Integration</link> project provides complete support for building
lightweight, <link xl:href="http://www.enterpriseintegrationpatterns.com"
>pattern-oriented</link>, event-driven architectures that build upon
the well-known Spring programming model.</para>
</note>
</section>
<section xml: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 xml: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 ContextLoaderServlet 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 xml:id="context-deploy-rar">
<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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/jca/context/SpringContextResourceAdapter.html"
>SpringContextResourceAdapter</link> 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

@ -1,682 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-factory-nature"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xl="http://www.w3.org/1999/xlink"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Customizing the nature of a bean</title>
<section xml:id="beans-factory-lifecycle">
<title>Lifecycle callbacks</title>
<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.</para>
<tip>
<para>The JSR-250 <interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename> annotations are generally
considered best practice for receiving lifecycle callbacks in a modern
Spring application. Using these annotations means that your beans are not
coupled to Spring specific interfaces. For details see
<xref linkend="beans-postconstruct-and-predestroy-annotations"/>.</para>
<para>If you don't want to use the JSR-250 annotations but you are still
looking to remove coupling consider the use of init-method and destroy-method
object definition metadata.</para>
</tip>
<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 xml: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, use the
<link linkend="beans-postconstruct-and-predestroy-annotations">
<interfacename>@PostConstruct</interfacename> annotation</link> or 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 xml: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, use the
<link linkend="beans-postconstruct-and-predestroy-annotations">
<interfacename>@PreDestroy</interfacename> annotation</link> or 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 xml: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 default-init-method="init"&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 xml: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 xml: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 xml: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 xml: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>ApplicationContext</interfacename> is autowired into a
field, constructor argument, or method parameter that is expecting the
<interfacename>ApplicationContext</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 xml: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 xml: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

@ -1,568 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-factory-extension"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Container Extension Points</title>
<para>Typically, an application developer does not need to subclass
<interfacename>ApplicationContext</interfacename> implementation classes.
Instead, the Spring IoC container can be extended by plugging in
implementations of special integration interfaces. The next few sections
describe these integration interfaces.</para>
<section xml:id="beans-factory-extension-bpp">
<title>Customizing beans using a
<interfacename>BeanPostProcessor</interfacename></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 initializing a bean, you can plug in one or
more <interfacename>BeanPostProcessor</interfacename>
implementations.</para>
<para>You can configure multiple <literal>BeanPostProcessor</literal>
instances, and you can control the order in which these
<literal>BeanPostProcessor</literal>s 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
further details, consult the Javadoc for the
<interfacename>BeanPostProcessor</interfacename> and
<interfacename>Ordered</interfacename> interfaces. See also the note below on
<link linkend="beans-factory-programmatically-registering-beanpostprocessors">
programmatic registration of <interfacename>BeanPostProcessors</interfacename>
</link></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>s do their work.</para>
<para><literal>BeanPostProcessor</literal>s 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> post-process the beans in that
container. In other words, beans that are defined in one container are not
post-processed by a <literal>BeanPostProcessor</literal> defined in another
container, even if both containers are part of the same hierarchy.</para>
<para>To change the actual bean definition (i.e., the
<emphasis>blueprint</emphasis> that defines the bean), you instead need to use a
<interfacename>BeanFactoryPostProcessor</interfacename> as described
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 InitializingBean's <emphasis>afterPropertiesSet()</emphasis>
and any declared init method) are called as well as <emphasis>after</emphasis>
any bean initialization callbacks. 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 in order
to provide proxy-wrapping logic.</para>
<para>An <interfacename>ApplicationContext</interfacename>
<emphasis>automatically detects</emphasis> any beans that are defined in
the configuration metadata which implement the
<interfacename>BeanPostProcessor</interfacename> interface. The
<interfacename>ApplicationContext</interfacename> registers these beans as
post-processors so that they can be called later upon bean creation.
Bean post-processors can be deployed in the container just like any other
beans.</para>
<anchor xml:id="beans-factory-programmatically-registering-beanpostprocessors"/>
<note>
<title>Programmatically registering <interfacename>BeanPostProcessors
</interfacename></title>
<para>While the recommended approach for <interfacename>BeanPostProcessor
</interfacename> registration is through <interfacename>ApplicationContext
</interfacename> auto-detection (as described above), it is also
possible to register them <emphasis>programmatically</emphasis>
against a <interfacename>ConfigurableBeanFactory</interfacename> using the
<methodname>addBeanPostProcessor</methodname> method. This can be useful
when needing to evaluate conditional logic before registration, or even
for copying bean post processors across contexts in a hierarchy. Note
however that <interfacename>BeanPostProcessors</interfacename> added
programmatically <emphasis>do not respect the <interfacename>Ordered
</interfacename> interface</emphasis>. Here it is the <emphasis>order of
registration</emphasis> that dictates the order of execution. Note also
that <interfacename>BeanPostProcessors</interfacename> registered
programmatically are always processed before those registered through
auto-detection, regardless of any explicit ordering.</para>
</note>
<note>
<title><interfacename>BeanPostProcessors</interfacename> and AOP
auto-proxying</title>
<para>Classes that implement the
<interfacename>BeanPostProcessor</interfacename> interface are
<emphasis>special</emphasis> and are treated differently by the
container. All <interfacename>BeanPostProcessors</interfacename>
<emphasis>and beans that they reference directly</emphasis> are
instantiated on startup, as part of the special startup phase of the
<interfacename>ApplicationContext</interfacename>. Next, all
<interfacename>BeanPostProcessors</interfacename> are registered in a
sorted fashion and applied to all further beans in the container.
Because AOP auto-proxying is implemented as a
<interfacename>BeanPostProcessor</interfacename> itself, neither
<interfacename>BeanPostProcessors</interfacename> nor the beans they reference
directly are eligible for auto-proxying, and thus do not have aspects woven
into them.</para>
<para>For any such bean, you should see an informational log message:
<quote><emphasis>Bean foo is not eligible for getting processed by all
BeanPostProcessor interfaces (for example: not eligible for
auto-proxying)</emphasis></quote>.</para>
<para>Note that if you have beans wired into your <interfacename>BeanPostProcessor</interfacename>
using autowiring or <interfacename>@Resource</interfacename> (which may fall back to autowiring),
Spring might access unexpected beans when searching for type-matching dependency candidates,
and therefore make them ineligible for auto-proxying or other kinds of bean post-processing.
For example, if you have a dependency annotated with <interfacename>@Resource</interfacename>
where the field/setter name does not directly correspond to the declared name of a bean and
no name attribute is used, then Spring will access other beans for matching them by type.</para>
</note>
<para>The following examples show how to write, register, and use
<literal>BeanPostProcessors</literal> in an
<interfacename>ApplicationContext</interfacename>.</para>
<section xml: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 any 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.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.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
BeanPostProcessor 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 simple Java application 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 application resembles the
following:</para>
<programlisting>Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961</programlisting>
</section>
<section xml: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> &#151; 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 xml:id="beans-factory-extension-factory-postprocessors">
<title>Customizing configuration metadata with a
<interfacename>BeanFactoryPostProcessor</interfacename></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 those of 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>, and 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>
(i.e., 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 standard container 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> be applied to the bean
definitions in that container. Bean definitions in one 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 an <interfacename>ApplicationContext</interfacename>,
in order to apply changes to the configuration metadata that define the
container. Spring includes a number of predefined 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 xml:id="beans-factory-autodetect-beanfactorypostprocessors"/>
<para>An <interfacename>ApplicationContext</interfacename> automatically
detects any beans that are deployed into it that implement the
<interfacename>BeanFactoryPostProcessor</interfacename> interface. It
uses these beans as bean factory post-processors, at the
appropriate time. You can deploy these post-processor beans as you
would any other bean.</para>
<note>
<para>As with <interfacename>BeanPostProcessor</interfacename>s, you typically
do not want to configure <interfacename>BeanFactoryPostProcessor</interfacename>s
for lazy initialization. If no other bean references a
<interfacename>Bean(Factory)PostProcessor</interfacename>,
that post-processor will not get instantiated at all. Thus, marking it for
lazy initialization will be ignored, and the
<interfacename>Bean(Factory)PostProcessor</interfacename> will be
instantiated eagerly even if you set the <literal>default-lazy-init</literal>
attribute to <literal>true</literal> on the declaration of your
<code>&lt;beans /&gt;</code> element.</para>
</note>
<section xml: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 in a separate
file using 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 <emphasis>placeholders</emphasis> 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="${jdbc.driverClassName}"/&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;</programlisting>
<para>The actual values come from another file in the standard Java
<classname>Properties</classname> format:</para>
<programlisting>jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root</programlisting>
<para>Therefore, the string <literal>${jdbc.username}</literal> is replaced
at runtime with the value 'sa', and the same applies for other placeholder
values that match keys in the properties file. The
<classname>PropertyPlaceholderConfigurer</classname> checks for
placeholders in most properties and attributes of a bean definition.
Furthermore, 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. One or more locations can be provided 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> not only
looks for properties in the <classname>Properties</classname> file
you specify. By default it also checks against the Java
<classname>System</classname> properties if it cannot find a property
in the specified properties files. You can customize this behavior by setting the
<literal>systemPropertiesMode</literal> property of the configurer with
one of the following three supported integer values:
<!--What property is it overriding and what will replace the overridden value?-->
<!--MLP: override a value in the Properties with one from the 'systemProperties' -->
</para>
<itemizedlist>
<listitem>
<para><emphasis>never</emphasis> (0): Never check system properties</para>
</listitem>
<listitem>
<para><emphasis>fallback</emphasis> (1): Check system properties if not resolvable in the specified properties files. This is the default.</para>
</listitem>
<listitem>
<para><emphasis>override</emphasis> (2): Check system properties first, before trying the specified properties files. This allows system properties to override any other property source.</para>
</listitem>
</itemizedlist>
<para>
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 xml: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 being 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 can be used with 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>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>
<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>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 xml:id="beans-factory-extension-factorybean">
<title>Customizing instantiation logic with a
<interfacename>FactoryBean</interfacename></title>
<para>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 instead of the bean
it produces, preface the bean's id with the ampersand symbol
(<literal>&amp;</literal>) 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>; whereas, 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

@ -1,955 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-java"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Java-based container configuration</title>
<section xml:id="beans-java-basic-concepts">
<title>Basic concepts: <literal>@Bean</literal> and <literal>@Configuration</literal></title>
<sidebar>
<title>Full @Configuration vs 'lite' @Beans mode?</title>
<para>When <interfacename>@Bean</interfacename> methods are declared within
classes that are <emphasis>not</emphasis> annotated with
<interfacename>@Configuration</interfacename> they are referred to as being
processed in a 'lite' mode. For example, bean methods declared in a
<interfacename>@Component</interfacename> or even in a <emphasis>plain old
class</emphasis> will be considered 'lite'.</para>
<para>Unlike full <interfacename>@Configuration</interfacename>, lite
<interfacename>@Bean</interfacename> methods cannot easily declare inter-bean
dependencies. Usually one <interfacename>@Bean</interfacename> method should not
invoke another <interfacename>@Bean</interfacename> method when operating in
'lite' mode.</para>
<para>Only using <interfacename>@Bean</interfacename> methods within
<interfacename>@Configuration</interfacename> classes is a recommended approach
of ensuring that 'full' mode is always used. This will prevent the same
<interfacename>@Bean</interfacename> method from accidentally being invoked
multiple times and helps to reduce subtle bugs that can be hard to track down
when operating in 'lite' mode.</para>
</sidebar>
<para>The central artifacts in Spring's new Java-configuration support are
<interfacename>@Configuration</interfacename>-annotated classes and
<interfacename>@Bean</interfacename>-annotated methods.</para>
<para>The <interfacename>@Bean</interfacename> annotation is used to indicate that a
method instantiates, configures and initializes a new object to be managed by
the Spring IoC container. For those familiar with Spring's
<literal>&lt;beans/&gt;</literal> XML configuration the <literal>@Bean</literal>
annotation plays the same role as the <literal>&lt;bean/&gt;</literal>
element. You can use <interfacename>@Bean</interfacename> annotated methods with
any Spring <interfacename>@Component</interfacename>, however, they are most
often used with <interfacename>@Configuration</interfacename> beans.</para>
<para>Annotating a class with <interfacename>@Configuration</interfacename>
indicates that its primary purpose is as a source of bean definitions. Furthermore,
<interfacename>@Configuration</interfacename> classes allow inter-bean
dependencies to be defined by simply calling other <interfacename>@Bean</interfacename>
methods in the same class. 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>The <literal>AppConfig</literal> class above would be equivalent to the
following Spring <literal>&lt;beans/&gt;</literal> XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myService" class="com.acme.services.MyServiceImpl"/&gt;
&lt;/beans&gt;</programlisting>
The <interfacename>@Bean</interfacename> and <interfacename>@Configuration</interfacename>
annotations 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 xml: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 xml: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 xml: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 xml: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 xml: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 /app/* to the dispatcher servlet --&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
&lt;url-pattern&gt;/app/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/web-app&gt;</programlisting></para>
</section>
</section>
<section xml: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 xml: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 xml:id="beans-java-lifecycle-callbacks">
<title>Receiving lifecycle callbacks</title>
<para>Any classes defined with the
<literal>@Bean</literal> annotation support
the regular lifecycle callbacks and 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 xml:id="beans-java-specifying-bean-scope">
<title>Specifying bean scope</title>
<section xml: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 xml: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>
<section xml: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 xml: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 xml:id="beans-java-configuration-annotation">
<title>Using the <interfacename>@Configuration</interfacename> annotation</title>
<para><interfacename>@Configuration</interfacename> is a class-level annotation
indicating that an object is a source of bean definitions.
<interfacename>@Configuration</interfacename> classes declare beans via
public <interfacename>@Bean</interfacename> annotated methods. Calls to
<interfacename>@Bean</interfacename> methods on
<interfacename>@Configuration</interfacename> classes can also be used to
define inter-bean dependencies. See <xref linkend="beans-java-basic-concepts"/> for
a general introduction.</para>
<section xml:id="beans-java-injecting-dependencies">
<title>Injecting inter-bean 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>
<note>
<para>This method of declaring inter-bean dependencies only works when
the <interfacename>@Bean</interfacename> method is declared within a
<interfacename>@Configuration</interfacename> class. You cannot declare
inter-bean dependencies using plain <interfacename>@Component</interfacename>
classes.</para>
</note>
</section>
<section xml: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 xml: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. Note that as of Spring
3.2, it is no longer necessary to add CGLIB to your classpath because
CGLIB classes have been repackaged under org.springframework and included
directly within the spring-core JAR.</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> 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>
<section xml:id="beans-java-composing-configuration-classes">
<title>Composing Java-based configurations</title>
<section xml: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 xml: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 xml: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 <link xl:href="http://www.springsource.com/products/sts"
>SpringSource Tool Suite</link> 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 xml: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 xml: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 xml: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 xml: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 xml: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>

View File

@ -1,676 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-factory-scopes"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<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 xml: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 <link
xl:href="http://static.springsource.org/spring/docs/current/api/org/springframework/context/support/SimpleThreadScope.html"
>SimpleThreadScope</link>. For instructions on how to register this or
any other custom scope, see <xref
linkend="beans-factory-scopes-custom-using"/>.</para>
</note>
<section xml: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>
<imagedata align="center" fileref="images/singleton.png" format="PNG" width="400" />
</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 xml: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>
<imagedata align="center" fileref="images/prototype.png" format="PNG" width="400"/>
</imageobject>
</mediaobject></para>
<para>The following example defines a bean as a prototype in XML:</para>
<programlisting language="xml"><lineannotation>&lt;!-- using spring-beans-2.0.dtd --&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 xml: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 xml: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 xml: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 xml: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 xml: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 xml: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 xml: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>.</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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"&gt;
<lineannotation>&lt;!-- an HTTP Session-scoped bean exposed as a proxy --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.UserPreferences" scope="session"&gt;
<lineannotation>&lt;!-- instructs the container to proxy the surrounding bean --&gt;</lineannotation>
&lt;aop:scoped-proxy/&gt;
&lt;/bean&gt;
<lineannotation>&lt;!-- a singleton-scoped bean injected with a proxy to the above bean --&gt;</lineannotation>
&lt;bean id="userService" class="com.foo.SimpleUserService"&gt;
<lineannotation>&lt;!-- a reference to the proxied userPreferences 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. 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;
<literal>&lt;aop:scoped-proxy/&gt;</literal>
&lt;/bean&gt;
&lt;bean id="userManager" class="com.foo.UserManager"&gt;
&lt;property name="userPreferences" ref="userPreferences"/&gt;
&lt;/bean&gt;</programlisting>
<section xml: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>.</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;!-- DefaultUserPreferences implements the UserPreferences interface --&gt;</lineannotation>
&lt;bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session"&gt;
&lt;aop:scoped-proxy proxy-target-class="false"<literal/>/&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 xml: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 xml: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 <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/Scope.html"
>Scope Javadoc</link>, 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 xml: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("thread", 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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"&gt;
&lt;bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"&gt;
&lt;property name="scopes"&gt;
&lt;map&gt;
&lt;entry key="thread"&gt;
&lt;bean class="org.springframework.context.support.SimpleThreadScope"/&gt;
&lt;/entry&gt;
&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>

View File

@ -1,205 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<section xml:id="beans-standard-annotations"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Using JSR 330 Standard Annotations</title>
<para>Starting with Spring 3.0, Spring offers support for JSR-330 standard annotations (Dependency Injection).
Those annotations are scanned in the same way as the Spring annotations. You just need to have the relevant jars in your classpath.
</para>
<note>
<para>
If you are using Maven, the <interfacename>javax.inject</interfacename> artifact is available
in the standard Maven repository
(<link xl:href="http://repo1.maven.org/maven2/javax/inject/javax.inject/1/">http://repo1.maven.org/maven2/javax/inject/javax.inject/1/</link>).
You can add the following dependency to your file pom.xml:
</para>
<programlisting language="xml">
&lt;dependency&gt;
&lt;groupId&gt;javax.inject&lt;/groupId&gt;
&lt;artifactId&gt;javax.inject&lt;/artifactId&gt;
&lt;version&gt;1&lt;/version&gt;
&lt;/dependency&gt;</programlisting>
</note>
<section xml:id="beans-inject-named">
<title>Dependency Injection with <interfacename>@Inject</interfacename> and <interfacename>@Named</interfacename></title>
<para>Instead of <interfacename>@Autowired</interfacename>,
<interfacename>@javax.inject.Inject</interfacename> may be used as follows:
<programlisting language="java">import javax.inject.Inject;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>As with <interfacename>@Autowired</interfacename>, it is possible to use <interfacename>@Inject</interfacename>
at the class-level, field-level, method-level and constructor-argument level.
If you would like to use a qualified name for the dependency that should be injected,
you should use the <interfacename>@Named</interfacename> annotation as follows:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
</section>
<section xml:id="beans-named">
<title><interfacename>@Named</interfacename>: a standard equivalent to the <interfacename>@Component</interfacename> annotation</title>
<para>
Instead of <interfacename>@Component</interfacename>, <interfacename>@javax.inject.Named</interfacename> may be used as follows:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
@Named("movieListener")
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>
It is very common to use <interfacename>@Component</interfacename> without
specifying a name for the component. <interfacename>@Named</interfacename>
can be used in a similar fashion:
<programlisting language="java">import javax.inject.Inject;
import javax.inject.Named;
@Named
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
<lineannotation>// ...</lineannotation>
}</programlisting>
</para>
<para>
When using <interfacename>@Named</interfacename>, it is possible to use
component-scanning in the exact same way as when using Spring annotations:
<programlisting language="xml">&lt;beans&gt;
&lt;context:component-scan base-package="org.example"/&gt;
&lt;/beans&gt;</programlisting>
</para>
</section>
<section xml:id="beans-standard-annotations-limitations">
<title>Limitations of the standard approach</title>
<para>When working with standard annotations, it is important to know that
some significant features are not available as shown in the table below:</para>
<para><table xml:id="annotations-comparison">
<title>Spring annotations vs. standard annotations</title>
<tgroup cols="3">
<colspec colnum="1" colwidth="0.7*" />
<colspec colnum="2" colwidth="0.6*" />
<colspec colnum="3" colwidth="1.5*" />
<thead>
<row>
<entry>Spring</entry>
<entry>javax.inject.*</entry>
<entry>javax.inject restrictions / comments</entry>
</row>
</thead>
<tbody>
<row>
<entry>@Autowired</entry>
<entry>@Inject</entry>
<entry>@Inject has no 'required' attribute</entry>
</row>
<row>
<entry>@Component</entry>
<entry>@Named</entry>
<entry>&#151;</entry>
</row>
<row>
<entry>@Scope("singleton")</entry>
<entry>@Singleton</entry>
<entry>
<para>
The JSR-330 default scope is like Spring's <interfacename>prototype</interfacename>.
However, in order to keep it consistent with Spring's general defaults,
a JSR-330 bean declared in the Spring container is a
<interfacename>singleton</interfacename> by default. In order to use a
scope other than <interfacename>singleton</interfacename>, you should use Spring's
<interfacename>@Scope</interfacename> annotation.
</para>
<para>
<interfacename>javax.inject</interfacename> also provides a
<link xl:href="http://download.oracle.com/javaee/6/api/javax/inject/Scope.html">@Scope</link> annotation.
Nevertheless, this one is only intended to be used for creating your own annotations.
</para>
</entry>
</row>
<row>
<entry>@Qualifier</entry>
<entry>@Named</entry>
<entry>&#151;</entry>
</row>
<row>
<entry>@Value</entry>
<entry>&#151;</entry>
<entry>no equivalent</entry>
</row>
<row>
<entry>@Required</entry>
<entry>&#151;</entry>
<entry>no equivalent</entry>
</row>
<row>
<entry>@Lazy</entry>
<entry>&#151;</entry>
<entry>no equivalent</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@ -1,626 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="cache"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Cache Abstraction</title>
<section xml:id="cache-introduction">
<title>Introduction</title>
<para>Since version 3.1, Spring Framework provides support for transparently
adding caching into an existing Spring application. Similar to the <link linkend="transaction">transaction</link>
support, the caching abstraction allows consistent use of various caching
solutions with minimal impact on the code.</para>
</section>
<section xml:id="cache-strategies">
<title>Understanding the cache abstraction</title>
<sidebar>
<title>Cache vs Buffer</title>
<para>The terms "buffer" and "cache" tend to be used interchangeably; note however they represent different things.
A buffer is used traditionally as an intermediate temporary store for data between a fast and a slow entity. As one
party would have to <emphasis>wait</emphasis> for the other affecting performance, the buffer alleviates this by
allowing entire blocks of data to move at once rather then in small chunks. The data is written and read only once from
the buffer. Furthermore, the buffers are <emphasis>visible</emphasis> to at least one party which is aware of it.</para>
<para>A cache on the other hand by definition is hidden and neither party is aware that caching occurs.It as well improves
performance but does that by allowing the same data to be read multiple times in a fast fashion.</para>
<para>A further explanation of the differences between two can be found
<link xl:href="http://en.wikipedia.org/wiki/Cache#The_difference_between_buffer_and_cache">here</link>.</para>
</sidebar>
<para>At its core, the abstraction applies caching to Java methods, reducing thus the number of executions based on the
information available in the cache. That is, each time a <emphasis>targeted</emphasis> method is invoked, the abstraction
will apply a caching behavior checking whether the method has been already executed for the given arguments. If it has,
then the cached result is returned without having to execute the actual method; if it has not, then method is executed, the
result cached and returned to the user so that, the next time the method is invoked, the cached result is returned.
This way, expensive methods (whether CPU or IO bound) can be executed only once for a given set of parameters and the result
reused without having to actually execute the method again. The caching logic is applied transparently without any interference
to the invoker.</para>
<important><para>Obviously this approach works only for methods that are guaranteed to return the same output (result) for a given input
(or arguments) no matter how many times it is being executed.</para></important>
<para>To use the cache abstraction, the developer needs to take care of two aspects:
<itemizedlist>
<listitem><para>caching declaration - identify the methods that need to be cached and their policy</para></listitem>
<listitem><para>cache configuration - the backing cache where the data is stored and read from</para></listitem>
</itemizedlist>
</para>
<para>Note that just like other services in Spring Framework, the caching service is an abstraction (not a cache implementation) and requires
the use of an actual storage to store the cache data - that is, the abstraction frees the developer from having to write the caching
logic but does not provide the actual stores. There are two integrations available out of the box, for JDK <literal>java.util.concurrent.ConcurrentMap</literal>
and <link xl:href="http://ehcache.org/">EhCache</link> - see <xref linkend="cache-plug"/> for more information on plugging in other cache stores/providers.</para>
</section>
<section xml:id="cache-annotations">
<title>Declarative annotation-based caching</title>
<para>For caching declaration, the abstraction provides two Java annotations: <literal>@Cacheable</literal> and <literal>@CacheEvict</literal> which allow methods
to trigger cache population or cache eviction. Let us take a closer look at each annotation:</para>
<section xml:id="cache-annotations-cacheable">
<title><literal>@Cacheable</literal> annotation</title>
<para>As the name implies, <literal>@Cacheable</literal> is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache
so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form,
the annotation declaration requires the name of the cache associated with the annotated method:</para>
<programlisting language="java"><![CDATA[@Cacheable("books")
public Book findBook(ISBN isbn) {...}]]></programlisting>
<para>In the snippet above, the method <literal>findBook</literal> is associated with the cache named <literal>books</literal>. Each time the method is called, the cache
is checked to see whether the invocation has been already executed and does not have to be repeated. While in most cases, only one cache is declared, the annotation allows multiple
names to be specified so that more then one cache are being used. In this case, each of the caches will be checked before executing the method - if at least one cache is hit,
then the associated value will be returned:</para>
<note><para>All the other caches that do not contain the method will be updated as well even though the cached method was not actually
executed.</para></note>
<programlisting language="java"><![CDATA[@Cacheable({ "books", "isbns" })
public Book findBook(ISBN isbn) {...}]]></programlisting>
<section xml:id="cache-annotations-cacheable-default-key">
<title>Default Key Generation</title>
<para>Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for cache access.
Out of the box, the caching abstraction uses a simple <interfacename>KeyGenerator</interfacename> based on the following algorithm:</para>
<itemizedlist>
<listitem><para>If no params are given, return 0.</para></listitem>
<listitem><para>If only one param is given, return that instance.</para></listitem>
<listitem><para>If more the one param is given, return a key computed from the hashes of all parameters.</para></listitem>
</itemizedlist>
<para>
This approach works well for objects with <emphasis>natural keys</emphasis> as long as the <literal>hashCode()</literal> reflects that. If that is not the case then
for distributed or persistent environments, the strategy needs to be changed as the objects hashCode is not preserved.
In fact, depending on the JVM implementation or running conditions, the same hashCode can be reused for different objects, in the same VM instance.</para>
<para>To provide a different <emphasis>default</emphasis> key generator, one needs to implement the <interfacename>org.springframework.cache.KeyGenerator</interfacename> interface.
Once configured, the generator will be used for each declaration that does not specify its own key generation strategy (see below).
</para>
</section>
<section xml:id="cache-annotations-cacheable-key">
<title>Custom Key Generation Declaration</title>
<para>Since caching is generic, it is quite likely the target methods have various signatures that cannot be simply mapped on top of the cache structure. This tends to become
obvious when the target method has multiple arguments out of which only some are suitable for caching (while the rest are used only by the method logic). For example:</para>
<programlisting language="java"><![CDATA[@Cacheable("books")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]></programlisting>
<para>At first glance, while the two <literal>boolean</literal> arguments influence the way the book is found, they are no use for the cache. Further more what if only one of the two
is important while the other is not?</para>
<para>For such cases, the <literal>@Cacheable</literal> annotation allows the user to specify how the key is generated through its <literal>key</literal> attribute.
The developer can use <link linkend="expressions">SpEL</link> to pick the arguments of interest (or their nested properties), perform operations or even invoke arbitrary methods without
having to write any code or implement any interface. This is the recommended approach over the <link linkend="cache-annotations-cacheable-default-key">default</link> generator since
methods tend to be quite different in signatures as the code base grows; while the default strategy might work for some methods, it rarely does for all methods.</para>
<para>
Below are some examples of various SpEL declarations - if you are not familiar with it, do yourself a favour and read <xref linkend="expressions"/>:
</para>
<programlisting language="java"><!-- select 'isbn' argument -->
@Cacheable(value="books", <emphasis role="bold">key="#isbn")</emphasis>
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
<!-- select nested property of a certain argument -->
@Cacheable(value="books", <emphasis role="bold">key="#isbn.rawNumber"</emphasis>)
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
<!-- invoke arbitrary method using certain arguments -->
@Cacheable(value="books", <emphasis role="bold">key="T(someType).hash(#isbn)"</emphasis>)
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)</programlisting>
<para>The snippets above, show how easy it is to select a certain argument, one of its properties or even an arbitrary (static) method.</para>
</section>
<section xml:id="cache-annotations-cacheable-condition">
<title>Conditional caching</title>
<para>Sometimes, a method might not be suitable for caching all the time (for example, it might depend on the given arguments). The cache annotations support such functionality
through the <literal>conditional</literal> parameter which takes a <literal>SpEL</literal> expression that is evaluated to either <literal>true</literal> or <literal>false</literal>.
If <literal>true</literal>, the method is cached - if not, it behaves as if the method is not cached, that is executed every since time no matter what values are in the cache or what
arguments are used. A quick example - the following method will be cached, only if the argument <literal>name</literal> has a length shorter then 32:</para>
<programlisting language="java"><![CDATA[@Cacheable(value="book", condition="#name.length < 32")
public Book findBook(String name)]]></programlisting>
<para>In addition the <literal>conditional</literal> parameter, the <literal>unless</literal> parameter can be used to veto the adding of a value to the cache. Unlike
<literal>conditional</literal>, <literal>unless</literal> <literal>SpEL</literal> expressions are evalulated <emphasis>after</emphasis> the method has been called. Expanding
on the previous example - perhaps we only want to cache paperback books:</para>
<programlisting language="java"><![CDATA[@Cacheable(value="book", condition="#name.length < 32", unless="#result.hardback")
public Book findBook(String name)]]></programlisting>
</section>
<section xml:id="cache-spel-context">
<title>Available caching <literal>SpEL</literal> evaluation context</title>
<para>Each <literal>SpEL</literal> expression evaluates again a dedicated <literal><link linkend="expressions-language-ref">context</link></literal>. In addition
to the build in parameters, the framework provides dedicated caching related metadata such as the argument names. The next table lists the items made available to the context
so one can use them for key and conditional(see next section) computations:</para>
<table xml:id="cache-spel-context-tbl" pgwide="1">
<title>Cache SpEL available metadata</title>
<tgroup cols="4">
<colspec align="center" />
<thead>
<row>
<entry>Name</entry>
<entry>Location</entry>
<entry>Description</entry>
<entry>Example</entry>
</row>
</thead>
<tbody>
<row>
<entry>methodName</entry>
<entry>root object</entry>
<entry>The name of the method being invoked</entry>
<entry><screen>#root.methodName</screen></entry>
</row>
<row>
<entry>method</entry>
<entry>root object</entry>
<entry>The method being invoked</entry>
<entry><screen>#root.method.name</screen></entry>
</row>
<row>
<entry>target</entry>
<entry>root object</entry>
<entry>The target object being invoked</entry>
<entry><screen>#root.target</screen></entry>
</row>
<row>
<entry>targetClass</entry>
<entry>root object</entry>
<entry>The class of the target being invoked</entry>
<entry><screen>#root.targetClass</screen></entry>
</row>
<row>
<entry>args</entry>
<entry>root object</entry>
<entry>The arguments (as array) used for invoking the target</entry>
<entry><screen>#root.args[0]</screen></entry>
</row>
<row>
<entry>caches</entry>
<entry>root object</entry>
<entry>Collection of caches against which the current method is executed</entry>
<entry><screen>#root.caches[0].name</screen></entry>
</row>
<row>
<entry><emphasis>argument name</emphasis></entry>
<entry>evaluation context</entry>
<entry>Name of any of the method argument. If for some reason the names are not available (ex: no debug information),
the argument names are also available under the <literal><![CDATA[a<#arg>]]></literal> where
<emphasis><![CDATA[#arg]]></emphasis> stands for the argument index (starting from 0).</entry>
<entry><screen>iban</screen> or <screen>a0</screen> (one can also use <screen>p0</screen> or <literal><![CDATA[p<#arg>]]></literal> notation as an alias).</entry>
</row>
<row>
<entry>result</entry>
<entry>evaluation context</entry>
<entry>The result of the method call (the value to be cached). Only available in '<literal>unless</literal>' expressions and '<literal>cache evict</literal>'
expression (when <literal>beforeInvocation</literal> is <literal>false</literal>).</entry>
<entry><screen>#result</screen></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</section>
<section xml:id="cache-annotations-put">
<title><literal>@CachePut</literal> annotation</title>
<para>For cases where the cache needs to be updated without interfering with the method execution, one can use the <literal>@CachePut</literal> annotation. That is, the method will always
be executed and its result placed into the cache (according to the <literal>@CachePut</literal> options). It supports the same options as <literal>@Cacheable</literal> and should be used
for cache population rather then method flow optimization.</para>
<para>Note that using <literal>@CachePut</literal> and <literal>@Cacheable</literal> annotations on the same method is generally discouraged because they have different behaviors. While the latter
causes the method execution to be skipped by using the cache, the former forces the execution in order to execute a cache update. This leads to unexpected behavior and with the exception of specific
corner-cases (such as annotations having conditions that exclude them from each other), such declarations should be avoided.</para>
</section>
<section xml:id="cache-annotations-evict">
<title><literal>@CacheEvict</literal> annotation</title>
<para>The cache abstraction allows not just population of a cache store but also eviction. This process is useful for removing stale or unused data from the cache. Opposed to
<literal>@Cacheable</literal>, annotation <literal>@CacheEvict</literal> demarcates methods that perform cache <emphasis>eviction</emphasis>, that is methods that act as triggers
for removing data from the cache. Just like its sibling, <literal>@CacheEvict</literal> requires one to specify one (or multiple) caches that are affected by the action, allows a
key or a condition to be specified but in addition, features an extra parameter <literal>allEntries</literal> which indicates whether a cache-wide eviction needs to be performed
rather then just an entry one (based on the key):</para>
<programlisting language="java"><![CDATA[@CacheEvict(value = "books", allEntries=true)
public void loadBooks(InputStream batch)]]></programlisting>
<para>This option comes in handy when an entire cache region needs to be cleared out - rather then evicting each entry (which would take a long time since it is inefficient),
all the entires are removed in one operation as shown above. Note that the framework will ignore any key specified in this scenario as it does not apply (the entire cache is evicted not just
one entry).</para>
<para>One can also indicate whether the eviction should occur after (the default) or before the method executes through the <literal>beforeInvocation</literal> attribute.
The former provides the same semantics as the rest of the annotations - once the method completes successfully, an action (in this case eviction) on the cache is executed. If the method does not
execute (as it might be cached) or an exception is thrown, the eviction does not occur. The latter (<literal>beforeInvocation=true</literal>) causes the eviction to occur always, before the method
is invoked - this is useful in cases where the eviction does not need to be tied to the method outcome.</para>
<para>It is important to note that void methods can be used with <literal>@CacheEvict</literal> - as the methods act as triggers, the return values are ignored (as they don't interact with
the cache) - this is not the case with <literal>@Cacheable</literal> which adds/update data into the cache and thus requires a result.</para>
</section>
<section xml:id="cache-annotations-caching">
<title><literal>@Caching</literal> annotation</title>
<para>There are cases when multiple annotations of the same type, such as <literal>@CacheEvict</literal> or <literal>@CachePut</literal> need to be specified, for example because the condition or the key
expression is different between different caches. Unfortunately Java does not support such declarations however there is a workaround - using a <emphasis>enclosing</emphasis> annotation, in this case,
<literal>@Caching</literal>. <literal>@Caching</literal> allows multiple nested <literal>@Cacheable</literal>, <literal>@CachePut</literal> and <literal>@CacheEvict</literal> to be used on the same method:</para>
<programlisting language="java"><![CDATA[@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
public Book importBooks(String deposit, Date date)]]></programlisting>
</section>
<section xml:id="cache-annotation-enable">
<title>Enable caching annotations</title>
<para>It is important to note that even though declaring the cache annotations does not automatically triggers their actions - like many things in Spring, the feature has to be declaratively
enabled (which means if you ever suspect caching is to blame, you can disable it by removing only one configuration line rather then all the annotations in your code).</para>
<para>To enable caching annotations add the annotation <interfacename>@EnableCaching</interfacename> to one of your <interfacename>@Configuration</interfacename> classes:</para>
<programlisting language="java">@Configuration
@EnableCaching
public class AppConfig {
}</programlisting>
<para>Alternatively for XML configuration use the <literal>cache:annotation-driven</literal> element:</para>
<programlisting language="xml"><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"]]>
<emphasis role="bold">xmlns:cache="http://www.springframework.org/schema/cache"</emphasis><![CDATA[
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd]]>
<emphasis role="bold">http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd</emphasis><![CDATA[">]]>
<emphasis role="bold"><![CDATA[<cache:annotation-driven />]]></emphasis>
<![CDATA[</beans>]]></programlisting>
<para>Both the <literal>cache:annotation-driven</literal> element and <interfacename>@EnableCaching</interfacename> annotation allow various options to be specified that influence the way the
caching behavior is added to the application through AOP. The configuration is intentionally similar
with that of <link linkend="tx-annotation-driven-settings"><interfacename>@Transactional</interfacename></link>:
</para>
<para><table xml:id="cache-annotation-driven-settings">
<title>Cache annotation settings</title>
<tgroup cols="4">
<thead>
<row>
<entry>XML Attribute</entry>
<entry>Annotation Attribute</entry>
<entry>Default</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>cache-manager</literal></entry>
<entry>N/A (See <literal>CachingConfigurer</literal> Javadoc)</entry>
<entry>cacheManager</entry>
<entry><para>Name of cache manager to use. Only required
if the name of the cache manager is not
<literal>cacheManager</literal>, as in the example
above.</para></entry>
</row>
<row>
<entry><literal>mode</literal></entry>
<entry><literal>mode</literal></entry>
<entry>proxy</entry>
<entry><para>The default mode "proxy" processes annotated
beans to be proxied using Spring's AOP framework (following
proxy semantics, as discussed above, applying to method calls
coming in through the proxy only). The alternative mode
"aspectj" instead weaves the affected classes with Spring's
AspectJ caching aspect, modifying the target class byte
code to apply to any kind of method call. AspectJ weaving
requires spring-aspects.jar in the classpath as well as
load-time weaving (or compile-time weaving) enabled. (See
<xref linkend="aop-aj-ltw-spring" /> for details on how to set
up load-time weaving.)</para></entry>
</row>
<row>
<entry><literal>proxy-target-class</literal></entry>
<entry><literal>proxyTargetClass</literal></entry>
<entry>false</entry>
<entry><para>Applies to proxy mode only. Controls what type of
caching proxies are created for classes annotated with
the <interfacename>@Cacheable</interfacename> or <interfacename>@CacheEvict</interfacename> annotations.
If the <literal>proxy-target-class</literal> attribute is set
to <literal>true</literal>, then class-based proxies are
created. If <literal>proxy-target-class</literal> is
<literal>false</literal> or if the attribute is omitted, then
standard JDK interface-based proxies are created. (See <xref
linkend="aop-proxying" /> for a detailed examination of the
different proxy types.)</para></entry>
</row>
<row>
<entry><literal>order</literal></entry>
<entry><literal>order</literal></entry>
<entry>Ordered.LOWEST_PRECEDENCE</entry>
<entry><para>Defines the order of the cache advice that
is applied to beans annotated with
<interfacename>@Cacheable</interfacename> or <interfacename>@CacheEvict</interfacename>.
(For more
information about the rules related to ordering of AOP advice,
see <xref linkend="aop-ataspectj-advice-ordering" />.) No
specified ordering means that the AOP subsystem determines the
order of the advice.</para></entry>
</row>
</tbody>
</tgroup>
</table></para>
<note>
<para><literal>&lt;cache:annotation-driven/&gt;</literal> only looks for
<interfacename>@Cacheable/@CacheEvict</interfacename> on beans in the same
application context it is defined in. This means that, if you put
<literal>&lt;cache:annotation-driven/&gt;</literal> in a
<interfacename>WebApplicationContext</interfacename> for a
<classname>DispatcherServlet</classname>, it only checks for
<interfacename>@Cacheable/@CacheEvict</interfacename> beans in your
controllers, and not your services. See <xref
linkend="mvc-servlet" /> for more information.</para>
</note>
<sidebar>
<title>Method visibility and
<interfacename>@Cacheable/@CachePut/@CacheEvict</interfacename></title>
<para>When using proxies, you should apply the
<interfacename>@Cache*</interfacename> annotations only to
methods with <emphasis>public</emphasis> visibility. If you do
annotate protected, private or package-visible methods with these annotations,
no error is raised, but the annotated method does not exhibit the configured
caching settings. Consider the use of AspectJ (see below) if you
need to annotate non-public methods as it changes the bytecode itself.</para>
</sidebar>
<para><tip>
<para>Spring recommends that you only annotate concrete classes (and
methods of concrete classes) with the
<interfacename>@Cache*</interfacename> annotation, as opposed
to annotating interfaces. You certainly can place the
<interfacename>@Cache*</interfacename> annotation on an
interface (or an interface method), but this works only as you would
expect it to if you are using interface-based proxies. The fact that
Java annotations are <emphasis>not inherited from interfaces</emphasis>
means that if you are using class-based proxies
(<literal>proxy-target-class="true"</literal>) or the weaving-based
aspect (<literal>mode="aspectj"</literal>), then the caching
settings are not recognized by the proxying and weaving
infrastructure, and the object will not be wrapped in a
caching proxy, which would be decidedly
<emphasis>bad</emphasis>.</para>
</tip></para>
<note>
<para>In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
caching at runtime even if the invoked method is marked with
<interfacename>@Cacheable</interfacename> - considering using the aspectj mode in this case.</para>
</note>
</section>
<section xml:id="cache-annotation-stereotype">
<title>Using custom annotations</title>
<para>The caching abstraction allows one to use her own annotations to identify what method trigger cache population or eviction. This is quite handy as a template mechanism as it eliminates
the need to duplicate cache annotation declarations (especially useful if the key or condition are specified) or if the foreign imports (<literal>org.springframework</literal>) are not allowed
in your code base. Similar to the rest of the <link linkend="beans-stereotype-annotations">stereotype</link> annotations, both <literal>@Cacheable</literal> and <literal>@CacheEvict</literal>
can be used as meta-annotations, that is annotations that can annotate other annotations. To wit, let us replace a common <literal>@Cacheable</literal> declaration with our own, custom
annotation:
</para>
<programlisting language="java"><![CDATA[@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Cacheable(value=“books”, key="#isbn")
public @interface SlowService {
}]]></programlisting>
<para>Above, we have defined our own <literal>SlowService</literal> annotation which itself is annotated with <literal>@Cacheable</literal> - now we can replace the following code:</para>
<programlisting language="java"><![CDATA[@Cacheable(value="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]></programlisting>
<para>with:</para>
<programlisting language="java"><![CDATA[@SlowService
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]></programlisting>
<para>Even though <literal>@SlowService</literal> is not a Spring annotation, the container automatically picks up its declaration at runtime and understands its meaning. Note that as
mentioned <link linkend="cache-annotation-enable">above</link>, the annotation-driven behavior needs to be enabled.</para>
</section>
</section>
<section xml:id="cache-declarative-xml">
<title>Declarative XML-based caching</title>
<para>If annotations are not an option (no access to the sources or no external code), one can use XML for declarative caching. So instead of annotating the methods for caching, one specifies
the target method and the caching directives externally (similar to the declarative transaction management <link linkend="transaction-declarative-first-example">advice</link>). The previous example
can be translated into:</para>
<programlisting language="xml"><![CDATA[<!-- the service we want to make cacheable -->
<bean id="bookService" class="x.y.service.DefaultBookService"/>
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="books">
<cache:cacheable method="findBook" key="#isbn"/>
<cache:cache-evict method="loadBooks" all-entries="true"/>
</cache:caching>
</cache:advice>
<!-- apply the cacheable behavior to all BookService interfaces -->
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.BookService.*(..))"/>
</aop:config>
<!-- cache manager definition omitted -->
]]>
</programlisting>
<para>In the configuration above, the <literal>bookService</literal> is made cacheable. The caching semantics to apply are encapsulated in the <literal>cache:advice</literal> definition which
instructs method <literal>findBooks</literal> to be used for putting data into the cache while method <literal>loadBooks</literal> for evicting data. Both definitions are working against the
<literal>books</literal> cache.</para>
<para>The <literal>aop:config</literal> definition applies the cache advice to the appropriate points in the program by using the AspectJ pointcut expression (more information is available
in <xref linkend="aop" />). In the example above, all methods from the <interfacename>BookService</interfacename> are considered and the cache advice applied to them.</para>
<para>The declarative XML caching supports all of the annotation-based model so moving between the two should be fairly easy - further more both can be used inside the same application.
The XML based approach does not touch the target code however it is inherently more verbose; when dealing with classes with overloaded methods that are targeted for caching, identifying the
proper methods does take an extra effort since the <literal>method</literal> argument is not a good discriminator - in these cases, the AspectJ pointcut can be used to cherry pick the target
methods and apply the appropriate caching functionality. However through XML, it is easier to apply a package/group/interface-wide caching (again due to the AspectJ pointcut) and to create
template-like definitions (as we did in the example above by defining the target cache through the <literal>cache:definitions </literal><literal>cache</literal> attribute).
</para>
</section>
<section xml:id="cache-store-configuration">
<title>Configuring the cache storage</title>
<para>Out of the box, the cache abstraction provides integration with two storages - one on top of the JDK <interfacename>ConcurrentMap</interfacename> and one
for <link xl:href="http://ehcache.org/">EhCache</link> library. To use them, one needs to simply declare an appropriate <interfacename>CacheManager</interfacename> - an entity that controls and
manages <interfacename>Cache</interfacename>s and can be used to retrieve these for storage.</para>
<section xml:id="cache-store-configuration-jdk">
<title>JDK <interfacename>ConcurrentMap</interfacename>-based <interfacename>Cache</interfacename></title>
<para>The JDK-based <interfacename>Cache</interfacename> implementation resides under <literal>org.springframework.cache.concurrent</literal> package. It allows one to use <classname>
ConcurrentHashMap</classname> as a backing <interfacename>Cache</interfacename> store.</para>
<programlisting language="xml"><![CDATA[<!-- generic cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="books"/>
</set>
</property>
</bean>]]></programlisting>
<para>The snippet above uses the <classname>SimpleCacheManager</classname> to create a <interfacename>CacheManager</interfacename> for the two nested <classname>ConcurrentMapCache</classname>
instances named <emphasis>default</emphasis> and <emphasis>books</emphasis>.
Note that the names are configured directly for each cache.</para>
<para>As the cache is created by the application, it is bound to its lifecycle, making it suitable for basic use cases, tests or simple applications. The cache scales well and is very fast
but it does not provide any management or persistence capabilities nor eviction contracts.</para>
</section>
<section xml:id="cache-store-configuration-ehcache">
<title>EhCache-based <interfacename>Cache</interfacename></title>
<para>The EhCache implementation is located under <literal>org.springframework.cache.ehcache</literal> package. Again, to use it, one simply needs to declare the appropriate
<interfacename>CacheManager</interfacename>:</para>
<programlisting language="xml"><![CDATA[<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/>
<!-- EhCache library setup -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:config-location="ehcache.xml"/>]]></programlisting>
<para>This setup bootstraps ehcache library inside Spring IoC (through bean <literal>ehcache</literal>) which is then wired into the dedicated <interfacename>CacheManager</interfacename>
implementation. Note the entire ehcache-specific configuration is read from the resource <literal>ehcache.xml</literal>.</para>
</section>
<section xml:id="cache-store-configuration-gemfire">
<title>GemFire-based <interfacename>Cache</interfacename></title>
<para>GemFire is a memory-oriented/disk-backed, elastically scalable, continuously available, active (with built-in pattern-based subscription notifications),
globally replicated database and provides fully-featured edge caching. For further information on how to use GemFire as a CacheManager (and more), please refer
to the <link xl:href="http://static.springsource.org/spring-gemfire/docs/1.0.0.RELEASE/reference/html/">Spring GemFire reference documentation</link>.</para>
</section>
<section xml:id="cache-store-configuration-noop">
<title>Dealing with caches without a backing store</title>
<para>Sometimes when switching environments or doing testing, one might have cache declarations without an actual backing cache configured. As this is an invalid configuration, at runtime an
exception will be through since the caching infrastructure is unable to find a suitable store. In situations like this, rather then removing the cache declarations (which can prove tedious),
one can wire in a simple, dummy cache that performs no caching - that is, forces the cached methods to be executed every time:</para>
<programlisting language="xml"><![CDATA[<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<list>
<ref bean="jdkCache"/>
<ref bean="gemfireCache"/>
</list>
</property>
<property name="fallbackToNoOpCache" value="true"/>
</bean>]]></programlisting>
<para>The <literal>CompositeCacheManager</literal> above chains multiple <literal>CacheManager</literal>s and additionally, through the <literal>fallbackToNoOpCache</literal> flag, adds a
<emphasis>no op</emphasis> cache that for all the definitions not handled by the configured cache managers. That is, every cache definition not found in either <literal>jdkCache</literal>
or <literal>gemfireCache</literal> (configured above) will be handled by the no op cache, which will not store any information causing the target method to be executed every time.
</para>
</section>
</section>
<section xml:id="cache-plug">
<title>Plugging-in different back-end caches</title>
<para>Clearly there are plenty of caching products out there that can be used as a backing store. To plug them in, one needs to provide a <interfacename>CacheManager</interfacename> and
<interfacename>Cache</interfacename> implementation since unfortunately there is no available standard that we can use instead. This may sound harder then it is since in practice,
the classes tend to be simple <link xl:href="http://en.wikipedia.org/wiki/Adapter_pattern">adapter</link>s that map the caching abstraction framework on top of the storage API as the <literal>ehcache</literal> classes can show.
Most <interfacename>CacheManager</interfacename> classes can use the classes in <literal>org.springframework.cache.support</literal> package, such as <classname>AbstractCacheManager</classname>
which takes care of the boiler-plate code leaving only the actual <emphasis>mapping</emphasis> to be completed. We hope that in time, the libraries that provide integration with Spring
can fill in this small configuration gap.</para>
</section>
<section xml:id="cache-specific-config">
<title>How can I set the TTL/TTI/Eviction policy/XXX feature?</title>
<para>Directly through your cache provider. The cache abstraction is... well, an abstraction not a cache implementation. The solution you are using might support various data policies and different
topologies which other solutions do not (take for example the JDK <literal>ConcurrentHashMap</literal>) - exposing that in the cache abstraction would be useless simply because there would
no backing support. Such functionality should be controlled directly through the backing cache, when configuring it or through its native API.
</para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,458 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xml:id="classic-spring"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Classic Spring Usage</title>
<para>This appendix discusses some classic Spring usage patterns as a
reference for developers maintaining legacy Spring applications. These usage
patterns no longer reflect the recommended way of using these features and
the current recommended usage is covered in the respective sections of the
reference manual.</para>
<section xml:id="classic-spring-orm">
<title>Classic ORM usage</title>
<para>This section documents the classic usage patterns that you might
encounter in a legacy Spring application. For the currently recommended
usage patterns, please refer to the <xref linkend="orm" /> chapter.</para>
<section xml:id="classic-spring-hibernate">
<title>Hibernate</title>
<para>For the currently recommended usage patterns for Hibernate see
<xref linkend="orm-hibernate" /></para>
<section xml:id="orm-hibernate-template">
<title>The <classname>HibernateTemplate</classname></title>
<para>The basic programming model for templating looks as follows, for
methods that can be part of any custom data access object or business
service. There are no restrictions on the implementation of the
surrounding object at all, it just needs to provide a Hibernate
<interfacename>SessionFactory</interfacename>. It can get the latter
from anywhere, but preferably as bean reference from a Spring IoC
container - via a simple
<methodname>setSessionFactory(..)</methodname> bean property setter.
The following snippets show a DAO definition in a Spring container,
referencing the above defined
<interfacename>SessionFactory</interfacename>, and an example for a
DAO method implementation.</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="sessionFactory" ref="mySessionFactory"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(String category) throws DataAccessException {
return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
}
}</programlisting>
<para>The <classname>HibernateTemplate</classname> class provides many
methods that mirror the methods exposed on the Hibernate
<interfacename>Session</interfacename> interface, in addition to a
number of convenience methods such as the one shown above. If you need
access to the <interfacename>Session</interfacename> to invoke methods
that are not exposed on the <classname>HibernateTemplate</classname>,
you can always drop down to a callback-based approach like so.</para>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Criteria criteria = session.createCriteria(Product.class);
criteria.add(Expression.eq("category", category));
criteria.setMaxResults(6);
return criteria.list();
}
};
}
}</programlisting>
<para>A callback implementation effectively can be used for any
Hibernate data access. <classname>HibernateTemplate</classname> will
ensure that <interfacename>Session</interfacename> instances are
properly opened and closed, and automatically participate in
transactions. The template instances are thread-safe and reusable,
they can thus be kept as instance variables of the surrounding class.
For simple single step actions like a single find, load, saveOrUpdate,
or delete call, <classname>HibernateTemplate</classname> offers
alternative convenience methods that can replace such one line
callback implementations. Furthermore, Spring provides a convenient
<classname>HibernateDaoSupport</classname> base class that provides a
<methodname>setSessionFactory(..)</methodname> method for receiving a
<interfacename>SessionFactory</interfacename>, and
<methodname>getSessionFactory()</methodname> and
<methodname>getHibernateTemplate()</methodname>for use by subclasses.
In combination, this allows for very simple DAO implementations for
typical requirements:</para>
<programlisting language="java">public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
return this.getHibernateTemplate().find(
"from test.Product product where product.category=?", category);
}
}</programlisting>
</section>
<section xml:id="orm-hibernate-daos">
<title>Implementing Spring-based DAOs without callbacks</title>
<para>As alternative to using Spring's
<classname>HibernateTemplate</classname> to implement DAOs, data
access code can also be written in a more traditional fashion, without
wrapping the Hibernate access code in a callback, while still
respecting and participating in Spring's generic
<classname>DataAccessException</classname> hierarchy. The
<classname>HibernateDaoSupport</classname> base class offers methods
to access the current transactional
<interfacename>Session</interfacename> and to convert exceptions in
such a scenario; similar methods are also available as static helpers
on the <classname>SessionFactoryUtils</classname> class. Note that
such code will usually pass '<literal>false</literal>' as the value of
the <methodname>getSession(..)</methodname> methods
'<literal>allowCreate</literal>' argument, to enforce running within a
transaction (which avoids the need to close the returned
<interfacename>Session</interfacename>, as its lifecycle is managed by
the transaction).</para>
<programlisting language="java">public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
Session session = getSession(false);
try {
Query query = session.createQuery("from test.Product product where product.category=?");
query.setString(0, category);
List result = query.list();
if (result == null) {
throw new MyException("No search results.");
}
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
}
}</programlisting>
<para>The advantage of such direct Hibernate access code is that it
allows <emphasis>any</emphasis> checked application exception to be
thrown within the data access code; contrast this to the
<classname>HibernateTemplate</classname> class which is restricted to
throwing only unchecked exceptions within the callback. Note that you
can often defer the corresponding checks and the throwing of
application exceptions to after the callback, which still allows
working with <classname>HibernateTemplate</classname>. In general, the
<classname>HibernateTemplate</classname> class' convenience methods
are simpler and more convenient for many scenarios.</para>
</section>
</section>
<section xml:id="classic-spring-jdo">
<title>JDO</title>
<para>For the currently recommended usage patterns for JDO see <xref
linkend="orm-jdo" /></para>
<section xml:id="orm-jdo-template">
<title><classname>JdoTemplate</classname> and
<classname>JdoDaoSupport</classname></title>
<para>Each JDO-based DAO will then receive the
<interfacename>PersistenceManagerFactory</interfacename> through
dependency injection. Such a DAO could be coded against plain JDO API,
working with the given
<interfacename>PersistenceManagerFactory</interfacename>, but will
usually rather be used with the Spring Framework's
<classname>JdoTemplate</classname>:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="persistenceManagerFactory" ref="myPmf"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class ProductDaoImpl implements ProductDao {
private JdoTemplate jdoTemplate;
public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
this.jdoTemplate = new JdoTemplate(pmf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jdoTemplate.execute(new JdoCallback() {
public Object doInJdo(PersistenceManager pm) throws JDOException {
Query query = pm.newQuery(Product.class, "category = pCategory");
query.declareParameters("String pCategory");
List result = query.execute(category);
<lineannotation>// do some further stuff with the result list</lineannotation>
return result;
}
});
}
}</programlisting>
<para>A callback implementation can effectively be used for any JDO
data access. <classname>JdoTemplate</classname> will ensure that
<classname>PersistenceManager</classname>s are properly opened and
closed, and automatically participate in transactions. The template
instances are thread-safe and reusable, they can thus be kept as
instance variables of the surrounding class. For simple single-step
actions such as a single <literal>find</literal>,
<literal>load</literal>, <literal>makePersistent</literal>, or
<literal>delete</literal> call, <classname>JdoTemplate</classname>
offers alternative convenience methods that can replace such one line
callback implementations. Furthermore, Spring provides a convenient
<classname>JdoDaoSupport</classname> base class that provides a
<literal>setPersistenceManagerFactory(..)</literal> method for
receiving a <classname>PersistenceManagerFactory</classname>, and
<methodname>getPersistenceManagerFactory()</methodname> and
<methodname>getJdoTemplate()</methodname> for use by subclasses. In
combination, this allows for very simple DAO implementations for
typical requirements:</para>
<programlisting language="java">public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
return getJdoTemplate().find(
Product.class, "category = pCategory", "String category", new Object[] {category});
}
}</programlisting>
<para>As alternative to working with Spring's
<classname>JdoTemplate</classname>, you can also code Spring-based
DAOs at the JDO API level, explicitly opening and closing a
<interfacename>PersistenceManager</interfacename>. As elaborated in
the corresponding Hibernate section, the main advantage of this
approach is that your data access code is able to throw checked
exceptions. <classname>JdoDaoSupport</classname> offers a variety of
support methods for this scenario, for fetching and releasing a
transactional <interfacename>PersistenceManager</interfacename> as
well as for converting exceptions.</para>
</section>
</section>
<section xml:id="classic-spring-jpa">
<title>JPA</title>
<para>For the currently recommended usage patterns for JPA see <xref
linkend="orm-jpa" /></para>
<section xml:id="orm-jpa-template">
<title><classname>JpaTemplate</classname> and
<classname>JpaDaoSupport</classname></title>
<para>Each JPA-based DAO will then receive a
<interfacename>EntityManagerFactory</interfacename> via dependency
injection. Such a DAO can be coded against plain JPA and work with the
given <interfacename>EntityManagerFactory</interfacename> or through
Spring's <classname>JpaTemplate</classname>:</para>
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
&lt;property name="entityManagerFactory" ref="myEmf"/&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<programlisting language="java">public class JpaProductDao implements ProductDao {
private JpaTemplate jpaTemplate;
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.jpaTemplate = new JpaTemplate(emf);
}
public Collection loadProductsByCategory(final String category) throws DataAccessException {
return (Collection) this.jpaTemplate.execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query query = em.createQuery("from Product as p where p.category = :category");
query.setParameter("category", category);
List result = query.getResultList();
<lineannotation>// do some further processing with the result list</lineannotation>
return result;
}
});
}
}</programlisting>
<para>The <interfacename>JpaCallback</interfacename> implementation
allows any type of JPA data access. The
<classname>JpaTemplate</classname> will ensure that
<interfacename>EntityManager</interfacename>s are properly opened and
closed and automatically participate in transactions. Moreover, the
<classname>JpaTemplate</classname> properly handles exceptions, making
sure resources are cleaned up and the appropriate transactions rolled
back. The template instances are thread-safe and reusable and they can
be kept as instance variable of the enclosing class. Note that
<classname>JpaTemplate</classname> offers single-step actions such as
find, load, merge, etc along with alternative convenience methods that
can replace one line callback implementations.</para>
<para>Furthermore, Spring provides a convenient
<classname>JpaDaoSupport</classname> base class that provides the
<literal>get/setEntityManagerFactory</literal> and
<methodname>getJpaTemplate()</methodname> to be used by
subclasses:</para>
<programlisting language="java">public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException {
Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
params.put("category", category);
return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
}
}</programlisting>
<para>Besides working with Spring's
<classname>JpaTemplate</classname>, one can also code Spring-based
DAOs against the JPA, doing one's own explicit
<interfacename>EntityManager</interfacename> handling. As also
elaborated in the corresponding Hibernate section, the main advantage
of this approach is that your data access code is able to throw
checked exceptions. <classname>JpaDaoSupport</classname> offers a
variety of support methods for this scenario, for retrieving and
releasing a transaction <interfacename>EntityManager</interfacename>,
as well as for converting exceptions.</para>
<para><emphasis>JpaTemplate mainly exists as a sibling of JdoTemplate
and HibernateTemplate, offering the same style for people used to
it.</emphasis></para>
</section>
</section>
</section>
<section xml:id="clasic-spring-mvc">
<title>Classic Spring MVC</title>
<para>...</para>
</section>
<section xml:id="classic-spring-jms">
<title>JMS Usage</title>
<para>One of the benefits of Spring's JMS support is to shield the user
from differences between the JMS 1.0.2 and 1.1 APIs. (For a description of
the differences between the two APIs see sidebar on Domain Unification).
Since it is now common to encounter only the JMS 1.1 API the use of
classes that are based on the JMS 1.0.2 API has been deprecated in Spring
3.0. This section describes Spring JMS support for the JMS 1.0.2
deprecated classes. </para>
<sidebar>
<title>Domain Unification</title>
<para>There are two major releases of the JMS specification, 1.0.2 and
1.1.</para>
<para>JMS 1.0.2 defined two types of messaging domains, point-to-point
(Queues) and publish/subscribe (Topics). The 1.0.2 API reflected these
two messaging domains by providing a parallel class hierarchy for each
domain. As a result, a client application became domain specific in its
use of the JMS API. JMS 1.1 introduced the concept of domain unification
that minimized both the functional differences and client API
differences between the two domains. As an example of a functional
difference that was removed, if you use a JMS 1.1 provider you can
transactionally consume a message from one domain and produce a message
on the other using the same
<interfacename>Session</interfacename>.</para>
<note>
<para>The JMS 1.1 specification was released in April 2002 and
incorporated as part of J2EE 1.4 in November 2003. As a result, common
J2EE 1.3 application servers which are still in widespread use (such
as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS
1.0.2.</para>
</note>
</sidebar>
<section xml:id="classic-spring-jms-template">
<title>JmsTemplate</title>
<para>Located in the package
<literal>org.springframework.jms.core</literal> the class
<classname>JmsTemplate102</classname> provides all of the features of
the <classname>JmsTemplate</classname> described the JMS chapter, but is
based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence,
if you are using JmsTemplate102 you need to set the boolean property
<property>pubSubDomain</property> to configure the
<classname>JmsTemplate</classname> with knowledge of what JMS domain is
being used. By default the value of this property is false, indicating
that the point-to-point domain, Queues, will be used.</para>
</section>
<section xml:id="classic-spring-aysnc-messages">
<title>Asynchronous Message Reception </title>
<para><link
linkend="jms-receiving-async-message-listener-adapter">MessageListenerAdapter's</link>
are used in conjunction with Spring's <link linkend="jms-mdp">message
listener containers</link> to support asynchronous message reception by
exposing almost any class as a Message-driven POJO. If you are using the
JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as
<classname>MessageListenerAdapter102</classname>,
<classname>SimpleMessageListenerContainer102</classname>, and
<classname>DefaultMessageListenerContainer102</classname>. These classes
provide the same functionality as the JMS 1.1 based counterparts but
rely only on the JMS 1.0.2 API. </para>
</section>
<section xml:id="classic-spring-jms-connections">
<title>Connections</title>
<para>The <classname>ConnectionFactory</classname> interface is part of
the JMS specification and serves as the entry point for working with
JMS. Spring provides an implementation of the
<classname>ConnectionFactory</classname> interface,
<classname>SingleConnectionFactory102</classname>, based on the JMS
1.0.2 API that will return the same <classname>Connection</classname> on
all <methodname>createConnection()</methodname> calls and ignore calls to
<methodname>close()</methodname>. You will need to set the boolean
property <property>pubSubDomain</property> to indicate which messaging
domain is used as <classname>SingleConnectionFactory102</classname> will
always explicitly differentiate between a
<classname>javax.jms.QueueConnection</classname> and a
<classname>javax.jmsTopicConnection</classname>.</para>
</section>
<section xml:id="classic-spring-jms-tx-management">
<title>Transaction Management</title>
<para>In a JMS 1.0.2 environment the class
<classname>JmsTransactionManager102</classname> provides support for
managing JMS transactions for a single Connection Factory. Please refer
to the reference documentation on <link linkend="jms-tx">JMS Transaction
Management</link> for more information on this functionality.</para>
</section>
</section>
</appendix>

View File

@ -1,156 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="dao"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>DAO support</title>
<section xml:id="dao-introduction">
<title>Introduction</title>
<para>The Data Access Object (DAO) support in Spring is aimed at making it
easy to work with data access technologies like JDBC, Hibernate, JPA or
JDO in a consistent way. This allows one to switch between the
aforementioned persistence technologies fairly easily and it also allows
one to code without worrying about catching exceptions that are specific
to each technology.</para>
</section>
<section xml:id="dao-exceptions">
<title>Consistent exception hierarchy</title>
<para>Spring provides a convenient translation from technology-specific
exceptions like <classname>SQLException</classname> to its own exception
class hierarchy with the <classname>DataAccessException</classname> as the
root exception. These exceptions wrap the original exception so there is
never any risk that one might lose any information as to what might have
gone wrong.</para>
<para>In addition to JDBC exceptions, Spring can also wrap
Hibernate-specific exceptions, converting them from proprietary, checked
exceptions (in the case of versions of Hibernate prior to Hibernate 3.0),
to a set of focused runtime exceptions (the same is true for JDO and JPA
exceptions). This allows one to handle most persistence exceptions, which
are non-recoverable, only in the appropriate layers, without having
annoying boilerplate catch-and-throw blocks and exception declarations in
one's DAOs. (One can still trap and handle exceptions anywhere one needs
to though.) As mentioned above, JDBC exceptions (including
database-specific dialects) are also converted to the same hierarchy,
meaning that one can perform some operations with JDBC within a consistent
programming model.</para>
<para>The above holds true for the various template classes in Springs
support for various ORM frameworks. If one uses the interceptor-based
classes then the application must care about handling
<classname>HibernateExceptions</classname> and
<classname>JDOExceptions</classname> itself, preferably via delegating to
<classname>SessionFactoryUtils</classname>'
<methodname>convertHibernateAccessException(..)</methodname> or
<methodname>convertJdoAccessException()</methodname> methods respectively.
These methods convert the exceptions to ones that are compatible with the
exceptions in the <literal>org.springframework.dao</literal> exception
hierarchy. As <classname>JDOExceptions</classname> are unchecked, they can
simply get thrown too, sacrificing generic DAO abstraction in terms of
exceptions though.</para>
<para>The exception hierarchy that Spring provides can be seen below.
(Please note that the class hierarchy detailed in the image shows only a
subset of the entire <classname>DataAccessException</classname>
hierarchy.)</para>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/DataAccessException.gif" format="PNG" width="400" />
</imageobject>
</mediaobject>
</section>
<section xml:id="dao-annotations">
<title>Annotations used for configuring DAO or Repository classes</title>
<para>The best way to guarantee that your Data Access Objects (DAOs) or
repositories provide exception translation is to use the
<interfacename>@Repository</interfacename> annotation. This annotation
also allows the component scanning support to find and configure your DAOs
and repositories without having to provide XML configuration entries for
them.</para>
<programlisting language="java"><emphasis role="bold">@Repository</emphasis>
public class SomeMovieFinder implements MovieFinder {
// ...
}</programlisting>
<para>Any DAO or repository implementation will need to access to a
persistence resource, depending on the persistence technology used; for
example, a JDBC-based repository will need access to a JDBC
<interfacename>DataSource</interfacename>; a JPA-based repository will need
access to an <interfacename>EntityManager</interfacename>. The easiest way
to accomplish this is to have this resource dependency injected using one of
the <interfacename>@Autowired,</interfacename>, <interfacename>@Inject</interfacename>,
<interfacename>@Resource</interfacename> or
<interfacename>@PersistenceContext</interfacename> annotations. Here is an
example for a JPA repository:</para>
<programlisting language="java">@Repository
public class JpaMovieFinder implements MovieFinder {
@PersistenceContext
private EntityManager entityManager;
// ...
}</programlisting>
<para>If you are using the classic Hibernate APIs than you can inject the
SessionFactory:</para>
<programlisting language="java">@Repository
public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// ...
}</programlisting>
<para>Last example we will show here is for typical JDBC support. You
would have the <classname>DataSource</classname> injected into an
initialization method where you would create a
<classname>JdbcTemplate</classname> and other data access support classes
like <classname>SimpleJdbcCall</classname> etc using this
<classname>DataSource</classname>.</para>
<programlisting language="java">@Repository
public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate;
@Autowired
public void init(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// ...
}</programlisting>
<note>
<para>Please see the specific coverage of each persistence technology
for details on how to configure the application context to take
advantage of these annotations.</para>
</note>
<para></para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,313 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="ejb"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Enterprise JavaBeans (EJB) integration</title>
<section xml:id="ejb-introduction">
<title>Introduction</title>
<para>
As a lightweight container, Spring is often considered an EJB
replacement. We do believe that for many if not most applications and use
cases, Spring as a container, combined with its rich supporting
functionality in the area of transactions, ORM and JDBC access, is a better
choice than implementing equivalent functionality via an EJB container and
EJBs.
</para>
<para>
However, it is important to note that using Spring does not prevent
you from using EJBs. In fact, Spring makes it much easier to access EJBs and
implement EJBs and functionality within them. Additionally, using Spring to
access services provided by EJBs allows the implementation of those services
to later transparently be switched between local EJB, remote EJB, or POJO
(plain old Java object) variants, without the client code having to
be changed.
</para>
<para>
In this chapter, we look at how Spring can help you access and
implement EJBs. Spring provides particular value when accessing stateless
session beans (SLSBs), so we'll begin by discussing this.
</para>
</section>
<section xml:id="ejb-access">
<title>Accessing EJBs</title>
<section xml:id="ejb-access-concepts">
<title>Concepts</title>
<para>
To invoke a method on a local or remote stateless session bean,
client code must normally perform a JNDI lookup to obtain the (local or
remote) EJB Home object, then use a 'create' method call on that object
to obtain the actual (local or remote) EJB object. One or more methods
are then invoked on the EJB.
</para>
<para>
To avoid repeated low-level code, many EJB applications use the
Service Locator and Business Delegate patterns. These are better than
spraying JNDI lookups throughout client code, but their usual
implementations have significant disadvantages. For example:
</para>
<itemizedlist>
<listitem>
<para>
Typically code using EJBs depends on Service Locator or
Business Delegate singletons, making it hard to test.
</para>
</listitem>
<listitem>
<para>
In the case of the Service Locator pattern used without a
Business Delegate, application code still ends up having to invoke
the create() method on an EJB home, and deal with the resulting
exceptions. Thus it remains tied to the EJB API and the complexity
of the EJB programming model.
</para>
</listitem>
<listitem>
<para>
Implementing the Business Delegate pattern typically results
in significant code duplication, where we have to write numerous
methods that simply call the same method on the EJB.
</para>
</listitem>
</itemizedlist>
<para>
The Spring approach is to allow the creation and use of proxy objects,
normally configured inside a Spring container, which act as codeless
business delegates. You do not need to write another Service Locator, another
JNDI lookup, or duplicate methods in a hand-coded Business Delegate unless
you are actually adding real value in such code.
</para>
</section>
<section xml:id="ejb-access-local">
<title>Accessing local SLSBs</title>
<para>
Assume that we have a web controller that needs to use a local
EJB. Well follow best practice and use the EJB Business Methods
Interface pattern, so that the EJBs local interface extends a non
EJB-specific business methods interface. Lets call this business
methods interface <classname>MyComponent</classname>.
</para>
<programlisting language="java"><![CDATA[public interface MyComponent {
...
}]]></programlisting>
<para>
One of the main reasons to use the Business Methods Interface pattern
is to ensure that synchronization between method signatures in local
interface and bean implementation class is automatic. Another reason is
that it later makes it much easier for us to switch to a POJO (plain old
Java object) implementation of the service if it makes sense to do so.
Of course well also need to implement the local home interface and
provide an implementation class that implements <classname>SessionBean</classname>
and the <classname>MyComponent</classname> business methods interface. Now the
only Java coding well need to do to hook up our web tier controller to the
EJB implementation is to expose a setter method of type <classname>MyComponent</classname>
on the controller. This will save the reference as an instance variable in the
controller:
</para>
<programlisting language="java"><![CDATA[private MyComponent myComponent;
public void setMyComponent(MyComponent myComponent) {
this.myComponent = myComponent;
}]]></programlisting>
<para>
We can subsequently use this instance variable in any business
method in the controller. Now assuming we are obtaining our controller
object out of a Spring container, we can (in the same context) configure a
<classname>LocalStatelessSessionProxyFactoryBean</classname> instance, which
will be the EJB proxy object. The configuration of the proxy, and setting of
the <literal>myComponent</literal> property of the controller is done
with a configuration entry such as:
</para>
<programlisting language="xml"><![CDATA[<bean id="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myBean"/>
<property name="businessInterface" value="com.mycom.MyComponent"/>
</bean>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>]]></programlisting>
<para>
Theres a lot of work happening behind the scenes, courtesy of
the Spring AOP framework, although you arent forced to work with AOP
concepts to enjoy the results. The <literal>myComponent</literal> bean
definition creates a proxy for the EJB, which implements the business
method interface. The EJB local home is cached on startup, so theres
only a single JNDI lookup. Each time the EJB is invoked, the proxy
invokes the <literal>classname</literal> method on the local EJB and
invokes the corresponding business method on the EJB.
</para>
<para>
The <literal>myController</literal> bean definition sets the
<literal>myComponent</literal> property of the controller class to the
EJB proxy.
</para>
<para>
Alternatively (and preferably in case of many such proxy definitions),
consider using the <literal>&lt;jee:local-slsb&gt;</literal>
configuration element in Spring's "jee" namespace:
</para>
<programlisting language="xml"><![CDATA[<jee:local-slsb id="myComponent" jndi-name="ejb/myBean"
business-interface="com.mycom.MyComponent"/>
<bean id="myController" class="com.mycom.myController">
<property name="myComponent" ref="myComponent"/>
</bean>]]></programlisting>
<para>
This EJB access mechanism delivers huge simplification of
application code: the web tier code (or other EJB client code) has no
dependence on the use of EJB. If we want to replace this EJB reference
with a POJO or a mock object or other test stub, we could simply change
the <literal>myComponent</literal> bean definition without changing a
line of Java code. Additionally, we havent had to write a single line of
JNDI lookup or other EJB plumbing code as part of our application.
</para>
<para>
Benchmarks and experience in real applications indicate that the
performance overhead of this approach (which involves reflective
invocation of the target EJB) is minimal, and is typically undetectable
in typical use. Remember that we dont want to make fine-grained calls
to EJBs anyway, as theres a cost associated with the EJB infrastructure
in the application server.
</para>
<para>
There is one caveat with regards to the JNDI lookup. In a bean
container, this class is normally best used as a singleton (there simply
is no reason to make it a prototype). However, if that bean container
pre-instantiates singletons (as do the various XML
<classname>ApplicationContext</classname> variants)
you may have a problem if the bean container is loaded before the EJB
container loads the target EJB. That is because the JNDI lookup will be
performed in the <literal>init()</literal> method of this class and then
cached, but the EJB will not have been bound at the target location yet.
The solution is to not pre-instantiate this factory object, but allow it
to be created on first use. In the XML containers, this is controlled via
the <literal>lazy-init</literal> attribute.
</para>
<para>
Although this will not be of interest to the majority of Spring
users, those doing programmatic AOP work with EJBs may want to look at
<classname>LocalSlsbInvokerInterceptor</classname>.
</para>
</section>
<section xml:id="ejb-access-remote">
<title>Accessing remote SLSBs</title>
<para>
Accessing remote EJBs is essentially identical to accessing local
EJBs, except that the
<classname>SimpleRemoteStatelessSessionProxyFactoryBean</classname> or
<literal>&lt;jee:remote-slsb&gt;</literal> configuration element is used.
Of course, with or without Spring, remote invocation semantics apply; a
call to a method on an object in another VM in another computer does
sometimes have to be treated differently in terms of usage scenarios and
failure handling.
</para>
<para>
Spring's EJB client support adds one more advantage over the
non-Spring approach. Normally it is problematic for EJB client code to
be easily switched back and forth between calling EJBs locally or
remotely. This is because the remote interface methods must declare that
they throw <classname>RemoteException</classname>, and client code must deal
with this, while the local interface methods don't. Client code
written for local EJBs which needs to be moved to remote EJBs
typically has to be modified to add handling for the remote exceptions,
and client code written for remote EJBs which needs to be moved to local
EJBs, can either stay the same but do a lot of unnecessary handling of
remote exceptions, or needs to be modified to remove that code. With the
Spring remote EJB proxy, you can instead not declare any thrown
<classname>RemoteException</classname> in your Business Method Interface and
implementing EJB code, have a remote interface which is identical except
that it does throw <classname>RemoteException</classname>, and rely on the
proxy to dynamically treat the two interfaces as if they were the same.
That is, client code does not have to deal with the checked
<classname>RemoteException</classname> class. Any actual
<classname>RemoteException</classname> that is thrown during the EJB
invocation will be re-thrown as the non-checked
<classname>RemoteAccessException</classname> class, which is a subclass of
<classname>RuntimeException</classname>. The target service can then be
switched at will between a local EJB or remote EJB (or even plain Java
object) implementation, without the client code knowing or caring. Of
course, this is optional; there is nothing stopping you from declaring
<classname>RemoteExceptions</classname> in your business interface.
</para>
</section>
<section xml:id="ejb-access-ejb2-ejb3">
<title>Accessing EJB 2.x SLSBs versus EJB 3 SLSBs</title>
<para>
Accessing EJB 2.x Session Beans and EJB 3 Session Beans via Spring
is largely transparent. Spring's EJB accessors, including the
<literal>&lt;jee:local-slsb&gt;</literal> and <literal>&lt;jee:remote-slsb&gt;</literal>
facilities, transparently adapt to the actual component at runtime.
They handle a home interface if found (EJB 2.x style), or perform straight
component invocations if no home interface is available (EJB 3 style).
</para>
<para>
Note: For EJB 3 Session Beans, you could effectively use a
<classname>JndiObjectFactoryBean</classname> / <literal>&lt;jee:jndi-lookup&gt;</literal>
as well, since fully usable component references are exposed for plain
JNDI lookups there. Defining explicit <literal>&lt;jee:local-slsb&gt;</literal>
/ <literal>&lt;jee:remote-slsb&gt;</literal> lookups simply provides
consistent and more explicit EJB access configuration.
</para>
</section>
</section>
<section xml:id="ejb-implementation">
<title>Using Spring's EJB implementation support classes</title>
<section xml:id="ejb-implementation-ejb3">
<title>EJB 3 injection interceptor</title>
<para>
For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient
interceptor that resolves Spring 2.5's <literal>@Autowired</literal> annotation
in the EJB component class:
<classname>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</classname>.
This interceptor can be applied through an <code>@Interceptors</code> annotation
in the EJB component class, or through an <literal>interceptor-binding</literal>
XML element in the EJB deployment descriptor.
</para>
<programlisting language="java"><![CDATA[@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
@Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}]]></programlisting>
<para>
<classname>SpringBeanAutowiringInterceptor</classname> by default obtains target
beans from a <classname>ContextSingletonBeanFactoryLocator</classname>, with the
context defined in a bean definition file named <literal>beanRefContext.xml</literal>.
By default, a single context definition is expected, which is obtained by type rather
than by name. However, if you need to choose between multiple context definitions,
a specific locator key is required. The locator key (i.e. the name of the context
definition in <literal>beanRefContext.xml</literal>) can be explicitly specified
either through overriding the <literal>getBeanFactoryLocatorKey</literal> method
in a custom <classname>SpringBeanAutowiringInterceptor</classname> subclass.
</para>
<para>
Alternatively, consider overriding <classname>SpringBeanAutowiringInterceptor</classname>'s
<literal>getBeanFactory</literal> method, e.g. obtaining a shared
<interfacename>ApplicationContext</interfacename> from a custom holder class.
</para>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,492 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<book xml:id="spring-framework-reference"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<info>
<title>Spring Framework Reference Documentation</title>
<productname>Spring Framework</productname>
<releaseinfo>${version}</releaseinfo>
<authorgroup>
<author>
<personname>
<firstname>Rod</firstname>
<surname>Johnson</surname>
</personname>
</author><author>
<personname>
<firstname>Juergen</firstname>
<surname>Hoeller</surname>
</personname>
</author><author>
<personname>
<firstname>Keith</firstname>
<surname>Donald</surname>
</personname>
</author><author>
<personname>
<firstname>Colin</firstname>
<surname>Sampaleanu</surname>
</personname>
</author><author>
<personname>
<firstname>Rob</firstname>
<surname>Harrop</surname>
</personname>
</author><author>
<personname>
<firstname>Thomas</firstname>
<surname>Risberg</surname>
</personname>
</author><author>
<personname>
<firstname>Alef</firstname>
<surname>Arendsen</surname>
</personname>
</author><author>
<personname>
<firstname>Darren</firstname>
<surname>Davison</surname>
</personname>
</author><author>
<personname>
<firstname>Dmitriy</firstname>
<surname>Kopylenko</surname>
</personname>
</author><author>
<personname>
<firstname>Mark</firstname>
<surname>Pollack</surname>
</personname>
</author><author>
<personname>
<firstname>Thierry</firstname>
<surname>Templier</surname>
</personname>
</author><author>
<personname>
<firstname>Erwin</firstname>
<surname>Vervaet</surname>
</personname>
</author><author>
<personname>
<firstname>Portia</firstname>
<surname>Tung</surname>
</personname>
</author><author>
<personname>
<firstname>Ben</firstname>
<surname>Hale</surname>
</personname>
</author><author>
<personname>
<firstname>Adrian</firstname>
<surname>Colyer</surname>
</personname>
</author><author>
<personname>
<firstname>John</firstname>
<surname>Lewis</surname>
</personname>
</author><author>
<personname>
<firstname>Costin</firstname>
<surname>Leau</surname>
</personname>
</author><author>
<personname>
<firstname>Mark</firstname>
<surname>Fisher</surname>
</personname>
</author><author>
<personname>
<firstname>Sam</firstname>
<surname>Brannen</surname>
</personname>
</author><author>
<personname>
<firstname>Ramnivas</firstname>
<surname>Laddad</surname>
</personname>
</author><author>
<personname>
<firstname>Arjen</firstname>
<surname>Poutsma</surname>
</personname>
</author><author>
<personname>
<firstname>Chris</firstname>
<surname>Beams</surname>
</personname>
</author><author>
<personname>
<firstname>Tareq</firstname>
<surname>Abedrabbo</surname>
</personname>
</author><author>
<personname>
<firstname>Andy</firstname>
<surname>Clement</surname>
</personname>
</author><author>
<personname>
<firstname>Dave</firstname>
<surname>Syer</surname>
</personname>
</author><author>
<personname>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</personname>
</author><author>
<personname>
<firstname>Rossen</firstname>
<surname>Stoyanchev</surname>
</personname>
</author><author>
<personname>
<firstname>Phillip</firstname>
<surname>Webb</surname>
</personname>
</author>
</authorgroup>
<copyright>
<year>2004-2013</year>
</copyright>
<legalnotice>
<para>Copies of this document may be made for your own use and for
distribution to others, provided that you do not charge any fee for such
copies and further provided that each copy contains this Copyright
Notice, whether distributed in print or electronically.</para>
</legalnotice>
</info>
<!-- front matter -->
<toc></toc>
<part xml:id="spring-introduction">
<title>Overview of Spring Framework</title>
<partintro>
<para>The Spring Framework is a lightweight solution and a potential
one-stop-shop for building your enterprise-ready applications. However,
Spring is modular, allowing you to use only those parts that you need,
without having to bring in the rest. You can use the IoC container, with
Struts on top, but you can also use only the <link
linkend="orm-hibernate">Hibernate integration code</link> or the <link
linkend="jdbc-introduction">JDBC abstraction layer</link>. The Spring
Framework supports declarative transaction management, remote access to
your logic through RMI or web services, and various options for
persisting your data. It offers a full-featured <link
linkend="mvc-introduction">MVC framework</link>, and enables you to
integrate <link linkend="aop-introduction">AOP</link> transparently into
your software.</para>
<para>Spring is designed to be non-intrusive, meaning that your domain
logic code generally has no dependencies on the framework itself. In
your integration layer (such as the data access layer), some
dependencies on the data access technology and the Spring libraries will
exist. However, it should be easy to isolate these dependencies from the
rest of your code base.</para>
<para>This document is a reference guide to Spring Framework features.
If you have any requests, comments, or questions on this document,
please post them on the user mailing list or on the support forums at
<link xl:href="http://forum.springsource.org/"></link>.<!-- Missing link above. PDF shows it as http://forum.springsource.org/ --></para>
</partintro>
<xi:include href="overview.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-whats-new">
<title>What's New in Spring 3</title>
<xi:include href="new-in-3.0.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="new-in-3.1.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="new-in-3.2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-core">
<title>Core Technologies</title>
<partintro>
<para>This part of the reference documentation covers all of those
technologies that are absolutely integral to the Spring
Framework.</para>
<para>Foremost amongst these is the Spring Framework's Inversion of
Control (IoC) container. A thorough treatment of the Spring Framework's
IoC container is closely followed by comprehensive coverage of Spring's
Aspect-Oriented Programming (AOP) technologies. The Spring Framework has
its own AOP framework, which is conceptually easy to understand, and
which successfully addresses the 80% sweet spot of AOP requirements in
Java enterprise programming.</para>
<para>Coverage of Spring's integration with AspectJ (currently the
richest - in terms of features - and certainly most mature AOP
implementation in the Java enterprise space) is also provided.</para>
<para>Finally, the adoption of the test-driven-development (TDD)
approach to software development is certainly advocated by the Spring
team, and so coverage of Spring's support for integration testing is
covered (alongside best practices for unit testing). The Spring team has
found that the correct use of IoC certainly does make both unit and
integration testing easier (in that the presence of setter methods and
appropriate constructors on classes makes them easier to wire together
in a test without having to set up service locator registries and
suchlike)... the chapter dedicated solely to testing will hopefully
convince you of this as well.</para>
<itemizedlist>
<listitem>
<para><xref linkend="beans" /></para>
</listitem>
<listitem>
<para><xref linkend="resources" /></para>
</listitem>
<listitem>
<para><xref linkend="validation" /></para>
</listitem>
<listitem>
<para><xref linkend="expressions" /></para>
</listitem>
<listitem>
<para><xref linkend="aop" /></para>
</listitem>
<listitem>
<para><xref linkend="aop-api" /></para>
</listitem>
<listitem>
<para><xref linkend="testing" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="beans.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="resources.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="validation.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="expressions.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="aop.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="aop-api.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="testing.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-data-tier">
<title>Data Access</title>
<partintro xml:id="spring-data-tier-intro">
<para>This part of the reference documentation is concerned with data
access and the interaction between the data access layer and the
business or service layer.</para>
<para>Spring's comprehensive transaction management support is covered
in some detail, followed by thorough coverage of the various data access
frameworks and technologies that the Spring Framework integrates
with.</para>
<itemizedlist>
<listitem>
<para><xref linkend="transaction" /></para>
</listitem>
<listitem>
<para><xref linkend="dao" /></para>
</listitem>
<listitem>
<para><xref linkend="jdbc" /></para>
</listitem>
<listitem>
<para><xref linkend="orm" /></para>
</listitem>
<listitem>
<para><xref linkend="oxm" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="transaction.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="dao.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jdbc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="orm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="oxm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-web">
<title>The Web</title>
<partintro>
<para>This part of the reference documentation covers the Spring
Framework's support for the presentation tier (and specifically
web-based presentation tiers).</para>
<para>The Spring Framework's own web framework, <link
linkend="mvc">Spring Web MVC</link>, is covered in the first couple of
chapters. A number of the remaining chapters in this part of the
reference documentation are concerned with the Spring Framework's
integration with other web technologies, such as <link
linkend="struts">Struts</link> and <link linkend="jsf">JSF</link> (to
name but two).</para>
<para>This section concludes with coverage of Spring's MVC <link
linkend="portlet">portlet framework</link>.</para>
<itemizedlist>
<listitem>
<para><xref linkend="mvc" /></para>
</listitem>
<listitem>
<para><xref linkend="view" /></para>
</listitem>
<listitem>
<para><xref linkend="web-integration" /></para>
</listitem>
<listitem>
<para><xref linkend="portlet" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="mvc.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="view.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="web-integration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="portlet.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-integration">
<title>Integration</title>
<partintro>
<para>This part of the reference documentation covers the Spring
Framework's integration with a number of Java EE (and related)
technologies.</para>
<itemizedlist>
<listitem>
<para><xref linkend="remoting" /></para>
</listitem>
<listitem>
<para><xref linkend="ejb" /></para>
</listitem>
<listitem>
<para><xref linkend="jms" /></para>
</listitem>
<listitem>
<para><xref linkend="jmx" /></para>
</listitem>
<listitem>
<para><xref linkend="cci" /></para>
</listitem>
<listitem>
<para><xref linkend="mail" /></para>
</listitem>
<listitem>
<para><xref linkend="scheduling" /></para>
</listitem>
<listitem>
<para><xref linkend="dynamic-language" /></para>
</listitem>
<listitem>
<para><xref linkend="cache" /></para>
</listitem>
</itemizedlist>
</partintro>
<xi:include href="remoting.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ejb.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jms.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="jmx.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="cci.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="mail.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scheduling.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="dynamic-languages.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="cache.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part xml:id="spring-appendices">
<title>Appendices</title>
<xi:include href="classic-spring.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="classic-aop-spring.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="migration-3.1.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="migration-3.2.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xsd-configuration.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xml-custom.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="spring.tld.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="spring-form.tld.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
</book>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,404 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="mail"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Email</title>
<section xml:id="mail-introduction">
<title>Introduction</title>
<sidebar>
<title>Library dependencies</title>
<para>The following additional jars to be on the classpath of your
application in order to be able to use the Spring Framework's email library.</para>
<itemizedlist>
<listitem>
<para>The <link xl:href="http://java.sun.com/products/javamail/">JavaMail</link> <filename class="libraryfile">mail.jar</filename> library</para>
</listitem>
<listitem>
<para>The <link xl:href="http://java.sun.com/products/javabeans/jaf/downloads/index.html">JAF</link> <filename class="libraryfile">activation.jar</filename> library</para>
</listitem>
</itemizedlist>
<para>All of these libraries are freely available on the web.</para>
</sidebar>
<para>The Spring Framework provides a helpful utility library for sending
email that shields the user from the specifics of the underlying mailing
system and is responsible for low level resource handling on behalf of
the client.</para>
<para>The <literal>org.springframework.mail</literal> package is the root level package
for the Spring Framework's email support. The central interface for sending
emails is the <interfacename>MailSender</interfacename> interface; a simple value object
encapsulating the properties of a simple mail such as <emphasis>from</emphasis> and
<emphasis>to</emphasis> (plus many others) is the <classname>SimpleMailMessage</classname> class.
This package also contains a hierarchy of checked exceptions which provide
a higher level of abstraction over the lower level mail system exceptions
with the root exception being <exceptionname>MailException</exceptionname>. Please
refer to the JavaDocs for more information on the rich mail exception hierarchy.</para>
<para>The <interfacename>org.springframework.mail.javamail.JavaMailSender</interfacename>
interface adds specialized <emphasis>JavaMail</emphasis> features such as MIME
message support to the <interfacename>MailSender</interfacename> interface
(from which it inherits). <interfacename>JavaMailSender</interfacename> also provides a
callback interface for preparation of JavaMail MIME messages, called
<interfacename>org.springframework.mail.javamail.MimeMessagePreparator</interfacename></para>
</section>
<section xml:id="mail-usage">
<title>Usage</title>
<para>Let's assume there is a business interface called <interfacename>OrderManager</interfacename>:</para>
<programlisting language="java"><![CDATA[public interface OrderManager {
void placeOrder(Order order);
}]]></programlisting>
<para>Let us also assume that there is a requirement stating that an email message
with an order number needs to be generated and sent to a customer placing the
relevant order.</para>
<section xml:id="mail-usage-simple">
<title>Basic <interfacename>MailSender</interfacename> and <classname>SimpleMailMessage</classname> usage</title>
<programlisting language="java"><![CDATA[import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
public class SimpleOrderManager implements OrderManager {
private MailSender mailSender;
private SimpleMailMessage templateMessage;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public void setTemplateMessage(SimpleMailMessage templateMessage) {
this.templateMessage = templateMessage;
}
public void placeOrder(Order order) {
]]><lineannotation>// Do the business calculations...</lineannotation><![CDATA[
]]><lineannotation>// Call the collaborators to persist the order...</lineannotation><![CDATA[
]]><lineannotation>// Create a thread safe "copy" of the template message and customize it</lineannotation><![CDATA[
SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear " + order.getCustomer().getFirstName()
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
try{
this.mailSender.send(msg);
}
catch(MailException ex) {
]]><lineannotation>// simply log it and go on...</lineannotation><![CDATA[
System.err.println(ex.getMessage());
}
}
}]]></programlisting>
<para>Find below the bean definitions for the above code:</para>
<programlisting language="xml"><![CDATA[<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.mycompany.com"/>
</bean>
]]><lineannotation>&lt;!-- this is a template message that we can pre-load with default state --&gt;</lineannotation><![CDATA[
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from" value="customerservice@mycompany.com"/>
<property name="subject" value="Your order"/>
</bean>
<bean id="orderManager" class="com.mycompany.businessapp.support.SimpleOrderManager">
<property name="mailSender" ref="mailSender"/>
<property name="templateMessage" ref="templateMessage"/>
</bean>]]></programlisting>
</section>
<section xml:id="mail-usage-mime">
<title>Using the <interfacename>JavaMailSender</interfacename> and the <classname>MimeMessagePreparator</classname></title>
<para>Here is another implementation of <interfacename>OrderManager</interfacename> using
the <interfacename>MimeMessagePreparator</interfacename> callback interface. Please note
in this case that the <literal>mailSender</literal> property is of type
<interfacename>JavaMailSender</interfacename> so that we are able to use the JavaMail
<classname>MimeMessage</classname> class:</para>
<programlisting language="java"><![CDATA[import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessagePreparator;
public class SimpleOrderManager implements OrderManager {
private JavaMailSender mailSender;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void placeOrder(final Order order) {
]]><lineannotation>// Do the business calculations...</lineannotation><![CDATA[
]]><lineannotation>// Call the collaborators to persist the order...</lineannotation><![CDATA[
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
mimeMessage.setRecipient(Message.RecipientType.TO,
new InternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(new InternetAddress("mail@mycompany.com"));
mimeMessage.setText(
"Dear " + order.getCustomer().getFirstName() + " "
+ order.getCustomer().getLastName()
+ ", thank you for placing order. Your order number is "
+ order.getOrderNumber());
}
};
try {
this.mailSender.send(preparator);
}
catch (MailException ex) {
]]><lineannotation>// simply log it and go on...</lineannotation><![CDATA[
System.err.println(ex.getMessage());
}
}
}]]></programlisting>
<note>
<para>The mail code is a crosscutting concern and could well be a candidate
for refactoring into a <link linkend="aop">custom Spring AOP aspect</link>,
which then could be executed at appropriate joinpoints on the
<interfacename>OrderManager</interfacename> target.</para>
</note>
<para>The Spring Framework's mail support ships with the standard JavaMail
implementation. Please refer to the relevant JavaDocs for more information.</para>
</section>
</section>
<section xml:id="mail-javamail-mime">
<title>Using the JavaMail <classname>MimeMessageHelper</classname></title>
<para>A class that comes in pretty handy when dealing with JavaMail messages is
the <classname>org.springframework.mail.javamail.MimeMessageHelper</classname> class,
which shields you from having to use the verbose JavaMail API. Using
the <classname>MimeMessageHelper</classname> it is pretty easy to
create a <classname>MimeMessage</classname>:</para>
<programlisting language="java"><lineannotation>// of course you would use DI in any real-world cases</lineannotation><![CDATA[
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setTo("test@host.com");
helper.setText("Thank you for ordering!");
sender.send(message);]]></programlisting>
<section xml:id="mail-javamail-mime-attachments">
<title>Sending attachments and inline resources</title>
<para>Multipart email messages allow for both attachments and inline resources.
Examples of inline resources would be images or a stylesheet you want to use
in your message, but that you don't want displayed as an attachment.</para>
<section xml:id="mail-javamail-mime-attachments-attachment">
<title>Attachments</title>
<para>The following example shows you how to use the
<classname>MimeMessageHelper</classname> to send an email along with a
single JPEG image attachment.</para>
<programlisting language="java"><![CDATA[JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
]]><lineannotation>// use the true flag to indicate you need a multipart message</lineannotation><![CDATA[
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
helper.setText("Check out this image!");
]]><lineannotation>// let's attach the infamous windows Sample file (this time copied to c:/)</lineannotation><![CDATA[
FileSystemResource file = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg", file);
sender.send(message);]]></programlisting>
</section>
<section xml:id="mail-javamail-mime-attachments-inline">
<title>Inline resources</title>
<para>The following example shows you how to use the
<classname>MimeMessageHelper</classname> to send an email along with an
inline image.</para>
<programlisting language="java"><![CDATA[JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
]]><lineannotation>// use the true flag to indicate you need a multipart message</lineannotation><![CDATA[
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
]]><lineannotation>// use the true flag to indicate the text included is HTML</lineannotation><![CDATA[
helper.setText("<html><body><img src='cid:identifier1234'></body></html>", true);
]]><lineannotation>// let's include the infamous windows Sample file (this time copied to c:/)</lineannotation><![CDATA[
FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addInline("identifier1234", res);
sender.send(message);]]></programlisting>
<warning>
<para>Inline resources are added to the mime message using the
specified <literal>Content-ID</literal> (<literal>identifier1234</literal>
in the above example). The order in which you are adding the text and the
resource are <emphasis role="bold">very</emphasis> important. Be sure to
<emphasis>first add the text</emphasis> and after that the resources. If
you are doing it the other way around, it won't work!</para>
</warning>
</section>
</section>
<section xml:id="mail-templates">
<title>Creating email content using a templating library</title>
<para>The code in the previous examples explicitly created the
content of the email message, using methods calls such as
<methodname>message.setText(..)</methodname>. This is fine for
simple cases, and it is okay in the context of the aforementioned
examples, where the intent was to show you the very basics of the API.</para>
<para>In your typical enterprise application though, you are not going
to create the content of your emails using the above approach for a number
of reasons.</para>
<para>
<itemizedlist>
<listitem>
<para>Creating HTML-based email content in Java code is tedious and error prone</para>
</listitem>
<listitem>
<para>There is no clear separation between display logic and business logic</para>
</listitem>
<listitem>
<para>Changing the display structure of the email content requires writing Java code, recompiling, redeploying...</para>
</listitem>
</itemizedlist>
</para>
<para>Typically the approach taken to address these issues is to use a template library
such as FreeMarker or Velocity to define the display structure of email content. This leaves
your code tasked only with creating the data that is to be rendered in the email
template and sending the email. It is definitely a best practice for when
the content of your emails becomes even moderately complex, and with
the Spring Framework's support classes for FreeMarker and Velocity becomes
quite easy to do. Find below an example of using the Velocity template library
to create email content.</para>
<section xml:id="mail-templates-example">
<title>A Velocity-based example</title>
<para>To use <link xl:href="http://velocity.apache.org">Velocity</link> to
create your email template(s), you will need to have the Velocity libraries
available on your classpath. You will also need to create one or more Velocity templates
for the email content that your application needs. Find below the Velocity
template that this example will be using. As you can see it is HTML-based,
and since it is plain text it can be created using your favorite HTML
or text editor.</para>
<programlisting language="xml"><lineannotation># in the com/foo/package</lineannotation><![CDATA[
<html>
<body>
<h3>Hi ${user.userName}, welcome to the Chipping Sodbury On-the-Hill message boards!</h3>
<div>
Your email address is <a href="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>
</body>
</html>]]></programlisting>
<para>Find below some simple code and Spring XML configuration that
makes use of the above Velocity template to create email content and
send email(s).</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.ui.velocity.VelocityEngineUtils;
import javax.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.Map;
public class SimpleRegistrationService implements RegistrationService {
private JavaMailSender mailSender;
private VelocityEngine velocityEngine;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
}
public void register(User user) {
]]><lineannotation>// Do the registration logic...</lineannotation><![CDATA[
sendConfirmationEmail(user);
}
private void sendConfirmationEmail(final User user) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(user.getEmailAddress());
message.setFrom("webmaster@csonth.gov.uk"); ]]><lineannotation>// could be parameterized...</lineannotation><![CDATA[
Map model = new HashMap();
model.put("user", user);
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "com/dns/registration-confirmation.vm", model);
message.setText(text, true);
}
};
this.mailSender.send(preparator);
}
}]]></programlisting>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.csonth.gov.uk"/>
</bean>
<bean id="registrationService" class="com.foo.SimpleRegistrationService">
<property name="mailSender" ref="mailSender"/>
<property name="velocityEngine" ref="velocityEngine"/>
</bean>
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
</beans>]]></programlisting>
</section>
</section>
</section>
</chapter>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xml:id="migration-3.1"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Migrating to Spring Framework 3.1</title>
<para>In this appendix we discuss what users will want to know when upgrading to
Spring Framework 3.1. For a general overview of features, please see
<xref linkend="new-in-3.1"/></para>
<section xml:id="migration-3.1-component-scan">
<title>Component scanning against the "org" base package</title>
<para>Spring Framework 3.1 introduces a number of <literal>@Configuration</literal>
classes such as <literal>org.springframework.cache.annotation.ProxyCachingConfiguration
</literal> and
<literal>org.springframework.scheduling.annotation.ProxyAsyncConfiguration</literal>.
Because <literal>@Configuration</literal> is ultimately meta-annotated with Spring's
<literal>@Component</literal> annotation, these classes will inadvertently be scanned
and processed by the container for any component-scanning directive against the
unqualified "org" package, e.g.:
<programlisting language="xml">
&lt;context:component-scan base-package="org"/&gt;</programlisting>
Therefore, in order to avoid errors like the one reported in <link
xl:href="https://jira.springsource.org/browse/SPR-9843">SPR-9843</link>,
any such directives should be updated to at least one more level of qualification e.g.:
<programlisting language="xml">
&lt;context:component-scan base-package="org.xyz"/&gt;</programlisting>
Alternatively, an <literal>exclude-filter</literal> may be used. See
<link linkend="beans-scanning-filters"><literal>context:component-scan</literal></link>
documentation for details.</para>
</section>
</appendix>

View File

@ -1,357 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xml:id="migration-3.2"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Migrating to Spring Framework 3.2</title>
<para>In this appendix we discuss what users will want to know when upgrading to
Spring Framework 3.2. For a general overview of features, please see
<xref linkend="new-in-3.2"/></para>
<section xml:id="migration-3.2-new-optional-deps">
<title>Newly optional dependencies</title>
<para>Certain inter-module dependencies are now <literal>optional</literal> at the
Maven POM level where they were once required. For example, <literal>spring-tx</literal>
and its dependence on <literal>spring-context</literal>. This may result in <literal>
ClassNotFoundErrors</literal> or other similar problems for users that have been relying
on transitive dependency management to pull in affected downstream <literal>spring-*
</literal>. To resolve this problem, simply add the appropriate missing jars to your
build configuration.</para>
</section>
<section xml:id="migration-3.2-ehcache-support">
<title>EHCache support moved to spring-context-support</title>
<para>Along with Spring's new JCache support, the EHCache support classes in the
<literal>org.springframework.cache.ehcache</literal> package moved from the
<literal>spring-context</literal> module to <literal>spring-context-support</literal>.</para>
</section>
<section xml:id="migration-3.2-inline-asm">
<title>Inlining of spring-asm jar</title>
<para>In versions 3.0 and 3.1, we published a discrete <literal>spring-asm</literal>
containing repackaged <literal>org.objectweb.asm</literal> 3.x sources. As of Spring
Framework 3.2, we have upgraded to <literal>org.objectweb.asm</literal> 4.0 and done
away with the separate module jar, favoring inlining these classes directly within
<literal>spring-core</literal>. This should cause no migration issue for most users;
but on the off chance that you have <literal>spring-asm</literal> declared directly
within your project's build script, you'll want to remove it when upgrading to
Spring Framework 3.2.</para>
</section>
<section xml:id="migration-3.2-inline-cglib">
<title>Explicit CGLIB dependency no longer required</title>
<para>In prior versions, users of Spring's subclass-based AOP proxies (e.g. via
<literal>proxy-target-class="true"</literal>) and <literal>@Configuration</literal>
class support were required to declare an explicit dependency on CGLIB 2.2. As of
Spring Framework 3.2, we now repackage and inline the newly-released CGLIB 3.0.</para>
<para>This means greater convenience for users, as well as correct functionality for
Java 7 users who are creating subclass proxies of types that contain <literal>
invokedynamic</literal> bytecode instructions. Repackaging CGLIB internally ensures
no classpath conflicts with other third party frameworks that may depend on other
versions of CGLIB.</para>
</section>
<section xml:id="migration-3.2-osgi-users">
<title>For OSGi users</title>
<para>OSGi metadata is no longer published within individual Spring Framework
jar MANIFEST.MF files. Please see this
<link xl:href="http://www.springsource.org/springframework-ebr">announcement</link>
for more information about how users can get OSGi-ready versions of Spring
Framework 3.2 jars.</para>
</section>
<section xml:id="migration-3.2-compatibility-mvc-config">
<title>MVC Java Config and MVC Namespace</title>
<para>As explained in <xref linkend="mvc-config-content-negotiation"/>, both
the MVC Java config and the MVC namespace register extensions such as
<filename>.json</filename> and <filename>.xml</filename> if the
corresponding classpath dependencies are present. That means controller
methods may now return JSON or XML formatted content if those
extensions are present in the request URI,
even if the 'Accept' header doesn't request those media types.</para>
<para>The newly added support for matrix variables is explained in
<xref linkend="mvc-ann-matrix-variables"/>. To preserve backward
compatibility, by default, semicolon content is removed from incoming
request URIs and therefore <interfacename>@MatrixVariable</interfacename>
cannot be used without additional configuration. However, when using
the MVC Java config and the MVC namespace, semicolon content is left
in the URI so that matrix variables are automatically supported.
The removal of semicolon content is controlled through the
<classname>UrlPathHelper</classname> property of
<classname>RequestMappingHandlerMapping</classname>.</para>
</section>
<section xml:id="migration-3.2-compatibility-uri-variable-values">
<title>Decoding of URI Variable Values</title>
<para>URI variable values now get decoded when
<code>UrlPathHelper.setUrlDecode</code> is set to <code>false</code>.
See <link xl:href="https://jira.springsource.org/browse/SPR-9098">SPR-9098</link>.</para>
</section>
<section xml:id="migration-3.2-compatibility-http-patch">
<title>HTTP PATCH method</title>
<para>The <classname>DispatcherServlet</classname> now allows the
HTTP PATCH method where previously it didn't.</para>
</section>
<section xml:id="migration-3.2-compatibility-tiles3">
<title>Tiles 3</title>
<para>Besides the version number change, the set of Tiles
dependencies has also changed. You will need to have a subset or all of
<filename>tiles-request-api</filename>, <filename>tiles-api</filename>,
<filename>tiles-core</filename>, <filename>tiles-servlet</filename>,
<filename>tiles-jsp</filename>, <filename>tiles-el</filename>.
</para>
</section>
<section xml:id="migration-3.2-compatibility-spring-mvc-test">
<title>Spring MVC Test standalone project</title>
<para>If migrating from the
<link xl:href="https://github.com/SpringSource/spring-test-mvc">spring-test-mvc</link>
standalone project to the <filename>spring-test</filename> module in
Spring Framework 3.2, you will need to adjust the root package
to be <classname>org.springframework.test.web.servlet</classname>.</para>
<para>You will no longer be able to use the
<classname>MockMvcBuilders</classname> <code>annotationConfigSetup</code>
and <code>xmlConfigSetup</code> options. Instead you'll need to switch
to using the <interfacename>@WebAppConfiguration</interfacename> support
of <filename>spring-test</filename> for loading Spring configuration,
then inject a <interfacename>WebApplicationContext</interfacename> into
the test and use it to create a <classname>MockMvc</classname>. See
<xref linkend="spring-mvc-test-framework" /> for details.</para>
</section>
<section xml:id="migration-3.2-compatibility-spring-test">
<title>Spring Test Dependencies</title>
<para>The <literal>spring-test</literal> module has been upgraded to
depend on JUnit 4.11 (<literal>junit:junit</literal>), TestNG 6.5.2
(<literal>org.testng:testng</literal>), and Hamcrest Core 1.3
(<literal>org.hamcrest:hamcrest-core</literal>). Each of these
dependencies is declared as an <emphasis>optional</emphasis> dependency in
the Maven POM. Furthermore, it is important to note that the JUnit team
has stopped inlining Hamcrest Core within the
<literal>junit:junit</literal> Maven artifact as of JUnit 4.11. Hamcrest
Core is now a <emphasis>required</emphasis> transitive dependency of
<literal>junit</literal>, and users may therefore need to remove any
exclusions on <literal>hamcrest-core</literal> that they had previously
configured for their build.</para>
</section>
<section xml:id="migration-3.2-changes">
<title>Public API changes</title>
<section xml:id="migration-3.2-api-changes">
<title>JDiff reports</title>
<para>
Select JDiff reports are now being published to provide users with a convenient
means of understanding what's changed between versions. Going forward these will be
published between each minor version, e.g. from 3.1.3.RELEASE to 3.1.4.RELEASE; from
the latest maintenance version to the latest GA release, e.g.
<link xl:href="http://static.springsource.org/spring-framework/docs/3.1.3.RELEASE_to_3.2.0.RELEASE">
3.1.3.RELEASE to 3.2.0.RELEASE</link>; and in between each milestone
and/or RC for users who are tracking next-generation development, e.g.
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RC2_to_3.2.0.RELEASE">
3.2.0.RC2 to 3.2.0.RELEASE</link>.
</para>
</section>
<section xml:id="migration-3.2-removals-and-deprecations">
<title>Deprecations</title>
<para>The following packages and types have been wholly or partially deprecated
in Spring Framework 3.2 and may be removed in a future version. Click through
to the linked Javadoc for each item for exact details. See also the
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/deprecated-list.html">
complete list of deprecations</link> in the framework.</para>
<itemizedlist>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/ibatis/package-summary.html">
org.springframework.orm.ibatis</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/scheduling/backportconcurrent/package-summary.html">
org.springframework.scheduling.backportconcurrent</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ejb/support/package-summary.html">
org.springframework.ejb.support</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/http/converter/xml/XmlAwareFormHttpMessageConverter.html">
org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/jsf/DelegatingVariableResolver.html">
org.springframework.web.jsf.DelegatingVariableResolver</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/jsf/SpringBeanVariableResolver.html">
org.springframework.web.jsf.SpringBeanVariableResolver</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ui/velocity/CommonsLoggingLogSystem.html">
org.springframework.ui.velocity.CommonsLoggingLogSystem</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/ui/velocity/VelocityEngineUtils.html">
org.springframework.ui.velocity.VelocityEngineUtils</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/beans/factory/config/BeanReferenceFactoryBean.html">
org.springframework.beans.factory.config.BeanReferenceFactoryBean</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/beans/factory/config/CommonsLogFactoryBean.html">
org.springframework.beans.factory.config.CommonsLogFactoryBean</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/instrument/classloading/oc4j/OC4JLoadTimeWeaver.html">
org.springframework.beans.instrument.classloading.oc4j.OC4JLoadTimeWeaver</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/transaction/jta/OC4JJtaTransactionManager.html">
org.springframework.transaction.jta.OC4JJtaTransactionManager</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/util/ExpressionEvaluationUtils.html">
org.springframework.web.util.ExpressionEvaluationUtils</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.html">
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.html">
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.html">
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/annotation/ServletAnnotationMappingUtils.html">
org.springframework.web.servlet.mvc.annotation.ServletAnnotationMappingUtils</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/jmx/support/MBeanRegistrationSupport.html">
org.springframework.jmx.support.MBeanRegistrationSupport</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/ContextConfigurationAttributes.html">
org.springframework.test.context.ContextConfigurationAttributes</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/junit4/AbstractTransactionalJUnit4SpringContextTests.html">
org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests</link>:
use of the <varname>simpleJdbcTemplate</varname> instance variable has been deprecated
in favor of the new <varname>jdbcTemplate</varname> instance variable.</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/context/testng/AbstractTransactionalTestNGSpringContextTests.html">
org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests</link>:
use of the <varname>simpleJdbcTemplate</varname> instance variable has been deprecated
in favor of the new <varname>jdbcTemplate</varname> instance variable.</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/test/jdbc/SimpleJdbcTestUtils.html">
org.springframework.test.jdbc.SimpleJdbcTestUtils</link> has been deprecated in
favor of <classname>JdbcTestUtils</classname> which now contains all of the
functionality previously available in <classname>SimpleJdbcTestUtils</classname>.</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html">
org.springframework.web.servlet.view.ContentNegotiatingViewResolver</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/transaction/interceptor/TransactionAspectUtils.html">
org.springframework.transaction.interceptor.TransactionAspectUtils</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/http/HttpStatus.html">
org.springframework.http.HttpStatus</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/web/util/UriUtils.html">
org.springframework.web.util.UriUtils</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/jpa/vendor/TopLinkJpaDialect.html">
org.springframework.orm.jpa.vendor.TopLinkJpaDialect</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/orm/jpa/vendor/TopLinkJpaVendorAdapter.html">
org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter</link>
</para>
</listitem>
<listitem>
<para>
<link xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.RELEASE/javadoc-api/org/springframework/util/CachingMapDecorator.html">
org.springframework.orm.util.CachingMapDecorator</link>
</para>
</listitem>
</itemizedlist>
</section>
</section>
</appendix>

File diff suppressed because it is too large Load Diff

View File

@ -1,522 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="new-in-3.0"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>New Features and Enhancements in Spring Framework 3.0</title>
<para>If you have been using the Spring Framework for some time, you will be
aware that Spring has undergone two major revisions: Spring 2.0, released in
October 2006, and Spring 2.5, released in November 2007. It is now time for
a third overhaul resulting in Spring Framework 3.0.</para>
<sidebar xml:id="new-in-3.0-intro-java">
<title>Java SE and Java EE Support</title>
<para>The Spring Framework is now based on Java 5, and Java 6 is fully
supported.</para>
<para>Furthermore, Spring is compatible with J2EE 1.4 and Java EE 5, while
at the same time introducing some early support for Java EE 6.</para>
</sidebar>
<section xml:id="new-in-3.0-intro">
<title>Java 5</title>
<para>The entire framework code has been revised to take advantage of Java
5 features like generics, varargs and other language improvements. We have
done our best to still keep the code backwards compatible. We now have
consistent use of generic Collections and Maps, consistent use of generic
FactoryBeans, and also consistent resolution of bridge methods in the
Spring AOP API. Generic ApplicationListeners automatically receive
specific event types only. All callback interfaces such as
TransactionCallback and HibernateCallback declare a generic result value
now. Overall, the Spring core codebase is now freshly revised and
optimized for Java 5.</para>
<para>Spring's TaskExecutor abstraction has been updated for close
integration with Java 5's java.util.concurrent facilities. We provide
first-class support for Callables and Futures now, as well as
ExecutorService adapters, ThreadFactory integration, etc. This has been
aligned with JSR-236 (Concurrency Utilities for Java EE 6) as far as
possible. Furthermore, we provide support for asynchronous method
invocations through the use of the new @Async annotation (or EJB 3.1's
@Asynchronous annotation).</para>
</section>
<section xml:id="new-in-3.0-improved-docs">
<title>Improved documentation</title>
<para>The Spring reference documentation has also substantially been
updated to reflect all of the changes and new features for Spring Framework
3.0. While every effort has been made to ensure that there are no errors in
this documentation, some errors may nevertheless have crept in. If you do
spot any typos or even more serious errors, and you can spare a few cycles
during lunch, please do bring the error to the attention of the Spring
team by <link xl:href="http://jira.springframework.org/">raising an
issue</link>.</para>
</section>
<section xml:id="new-in-3.0-new-tutorial">
<title>New articles and tutorials</title>
<para>
There are many excellent articles and tutorials that show how to get
started with Spring Framework 3 features. Read them at the
<link xl:href="http://www.springsource.org/documentation">Spring Documentation</link> page.
</para>
<para xml:id="new-in-3.0-samples">
The samples have been improved and updated to take advantage of the new features in Spring
Framework 3. Additionally, the samples have been moved out of the source tree into a dedicated SVN
<link xl:href="https://anonsvn.springframework.org/svn/spring-samples/">repository</link> available at:</para>
<para>
<literal>https://anonsvn.springframework.org/svn/spring-samples/</literal>
</para>
<para>As such, the samples are no longer distributed alongside Spring
Framework 3 and need to be downloaded separately from the repository
mentioned above. However, this documentation will continue to refer to
some samples (in particular Petclinic) to illustrate various features.</para>
<note><para>For more information on Subversion (or in short SVN), see the project homepage at:
<literal>http://subversion.apache.org/</literal></para>
</note>
</section>
<section xml:id="new-in-3.0-modules-build">
<title>New module organization and build system</title>
<para>The framework modules have been revised and are now managed
separately with one source-tree per module jar:</para>
<itemizedlist>
<listitem>
<para>org.springframework.aop</para>
</listitem>
<listitem>
<para>org.springframework.beans</para>
</listitem>
<listitem>
<para>org.springframework.context</para>
</listitem>
<listitem>
<para>org.springframework.context.support</para>
</listitem>
<listitem>
<para>org.springframework.expression</para>
</listitem>
<listitem>
<para>org.springframework.instrument</para>
</listitem>
<listitem>
<para>org.springframework.jdbc</para>
</listitem>
<listitem>
<para>org.springframework.jms</para>
</listitem>
<listitem>
<para>org.springframework.orm</para>
</listitem>
<listitem>
<para>org.springframework.oxm</para>
</listitem>
<listitem>
<para>org.springframework.test</para>
</listitem>
<listitem>
<para>org.springframework.transaction</para>
</listitem>
<listitem>
<para>org.springframework.web</para>
</listitem>
<listitem>
<para>org.springframework.web.portlet</para>
</listitem>
<listitem>
<para>org.springframework.web.servlet</para>
</listitem>
<listitem>
<para>org.springframework.web.struts</para>
</listitem>
</itemizedlist>
<sidebar xml:id="new-in-3.0-intro-spring-jar">
<title>Note:</title>
<para>The spring.jar artifact that contained almost the entire framework
is no longer provided.</para>
</sidebar>
<para>We are now using a new Spring build system as known from Spring Web
Flow 2.0. This gives us:</para>
<itemizedlist>
<listitem>
<para>Ivy-based "Spring Build" system</para>
</listitem>
<listitem>
<para>consistent deployment procedure</para>
</listitem>
<listitem>
<para>consistent dependency management</para>
</listitem>
<listitem>
<para>consistent generation of OSGi manifests</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.0-features-overview">
<title>Overview of new features</title>
<para>This is a list of new features for Spring Framework 3.0. We will cover these
features in more detail later in this section.</para>
<itemizedlist>
<listitem>
<para>Spring Expression Language</para>
</listitem>
<listitem>
<para>IoC enhancements/Java based bean metadata</para>
</listitem>
<listitem>
<para>General-purpose type conversion system and field formatting
system</para>
</listitem>
<listitem>
<para>Object to XML mapping functionality (OXM) moved from Spring Web
Services project</para>
</listitem>
<listitem>
<para>Comprehensive REST support</para>
</listitem>
<listitem>
<para>@MVC additions</para>
</listitem>
<listitem>
<para>Declarative model validation</para>
</listitem>
<listitem>
<para>Early support for Java EE 6</para>
</listitem>
<listitem>
<para>Embedded database support</para>
</listitem>
</itemizedlist>
<section xml:id="new-feature-java5">
<title>Core APIs updated for Java 5</title>
<para>BeanFactory interface returns typed bean instances as far as
possible: <itemizedlist>
<listitem>
<para>T getBean(Class&lt;T&gt; requiredType)</para>
</listitem>
<listitem>
<para>T getBean(String name, Class&lt;T&gt; requiredType)</para>
</listitem>
<listitem>
<para>Map&lt;String, T&gt; getBeansOfType(Class&lt;T&gt;
type)</para>
</listitem>
</itemizedlist></para>
<para>Spring's TaskExecutor interface now extends
<classname>java.util.concurrent.Executor</classname>: <itemizedlist>
<listitem>
<para>extended AsyncTaskExecutor supports standard Callables with
Futures</para>
</listitem>
</itemizedlist></para>
<para>New Java 5 based converter API and SPI: <itemizedlist>
<listitem>
<para>stateless ConversionService and Converters</para>
</listitem>
<listitem>
<para>superseding standard JDK PropertyEditors</para>
</listitem>
</itemizedlist></para>
<para>Typed ApplicationListener&lt;E&gt;</para>
</section>
<section xml:id="new-feature-el">
<title>Spring Expression Language</title>
<para>Spring introduces an expression language which is similar to
Unified EL in its syntax but offers significantly more features. The
expression language can be used when defining XML and Annotation based
bean definitions and also serves as the foundation for expression
language support across the Spring portfolio. Details of this new
functionality can be found in the chapter <link
linkend="expressions">Spring Expression Language (SpEL).</link></para>
<para>The Spring Expression Language was created to provide the Spring
community a single, well supported expression language that can be used
across all the products in the Spring portfolio. Its language features
are driven by the requirements of the projects in the Spring portfolio,
including tooling requirements for code completion support within the
Eclipse based <link xl:href="http://www.springsource.com/products/sts">SpringSource
Tool Suite</link>.</para>
<para>The following is an example of how the Expression Language can be
used to configure some properties of a database setup <programlisting
language="xml">&lt;bean class="mycompany.RewardsTestDatabase"&gt;
&lt;property name="databaseName"
value="#{systemProperties.databaseName}"/&gt;
&lt;property name="keyGenerator"
value="#{strategyBean.databaseKeyGenerator}"/&gt;
&lt;/bean&gt;
</programlisting></para>
<para>This functionality is also available if you prefer to configure
your components using annotations: <programlisting language="java">@Repository
public class RewardsTestDatabase {
@Value("#{systemProperties.databaseName}")
public void setDatabaseName(String dbName) { … }
@Value("#{strategyBean.databaseKeyGenerator}")
public void setKeyGenerator(KeyGenerator kg) { … }
}
</programlisting></para>
</section>
<section xml:id="new-feature-java-config">
<title>The Inversion of Control (IoC) container</title>
<section xml:id="new-java-configuration">
<title>Java based bean metadata</title>
<para>Some core features from the <link
xl:href="http://www.springsource.org/javaconfig">JavaConfig</link>
project have been added to the Spring Framework now. This means that
the following annotations are now directly supported: <itemizedlist>
<listitem>
<para>@Configuration</para>
</listitem>
<listitem>
<para>@Bean</para>
</listitem>
<listitem>
<para>@DependsOn</para>
</listitem>
<listitem>
<para>@Primary</para>
</listitem>
<listitem>
<para>@Lazy</para>
</listitem>
<listitem>
<para>@Import</para>
</listitem>
<listitem>
<para>@ImportResource</para>
</listitem>
<listitem>
<para>@Value</para>
</listitem>
</itemizedlist></para>
<para>Here is an example of a Java class providing basic configuration
using the new JavaConfig features: <programlisting language="java">package org.example.config;
@Configuration
public class AppConfig {
private @Value("#{jdbcProperties.url}") String jdbcUrl;
private @Value("#{jdbcProperties.username}") String username;
private @Value("#{jdbcProperties.password}") String password;
@Bean
public FooService fooService() {
return new FooServiceImpl(fooRepository());
}
@Bean
public FooRepository fooRepository() {
return new HibernateFooRepository(sessionFactory());
}
@Bean
public SessionFactory sessionFactory() {
// wire up a session factory
AnnotationSessionFactoryBean asFactoryBean =
new AnnotationSessionFactoryBean();
asFactoryBean.setDataSource(dataSource());
// additional config
return asFactoryBean.getObject();
}
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(jdbcUrl, username, password);
}
}
</programlisting> To get this to work you need to add the following component
scanning entry in your minimal application context XML file.
<programlisting language="xml">&lt;context:component-scan base-package="org.example.config"/&gt;
&lt;util:properties id="jdbcProperties" location="classpath:org/example/config/jdbc.properties"/&gt;
</programlisting>
Or you can bootstrap a <literal>@Configuration</literal> class directly using
<literal>AnnotationConfigApplicationContext</literal>:
<programlisting language="java">public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
FooService fooService = ctx.getBean(FooService.class);
fooService.doStuff();
}</programlisting>
See <xref linkend="beans-java-instantiating-container"/> for full information on
<literal>AnnotationConfigApplicationContext</literal>.</para>
</section>
<section xml:id="new-bean-metadata-in-components">
<title>Defining bean metadata within components</title>
<para><literal>@Bean</literal> annotated methods are also supported
inside Spring components. They contribute a factory bean definition to
the container. See <link
linkend="beans-factorybeans-annotations">Defining bean metadata within
components</link> for more information</para>
</section>
</section>
<section xml:id="new-feature-convert-and-format">
<title>General purpose type conversion system and field formatting
system</title>
<para>A general purpose <link linkend="core-convert">type conversion
system</link> has been introduced. The system is currently used by SpEL
for type conversion, and may also be used by a Spring Container and DataBinder when
binding bean property values.</para>
<para>In addition, a <link linkend="format">formatter</link> SPI
has been introduced for formatting field values. This SPI provides
a simpler and more robust alternative to JavaBean PropertyEditors for use in client
environments such as Spring MVC.</para>
</section>
<section xml:id="new-feature-oxm">
<title>The Data Tier</title>
<para>Object to XML mapping functionality (OXM) from the Spring Web
Services project has been moved to the core Spring Framework now. The
functionality is found in the <literal>org.springframework.oxm</literal>
package. More information on the use of the <literal>OXM</literal>
module can be found in the <link linkend="oxm">Marshalling XML using O/X
Mappers</link> chapter.</para>
</section>
<section xml:id="new-feature-rest">
<title>The Web Tier</title>
<para>The most exciting new feature for the Web Tier is the support for
building RESTful web services and web applications. There are also some
new annotations that can be used in any web application.</para>
<section xml:id="new-feature-rest-support">
<title>Comprehensive REST support</title>
<para>Server-side support for building RESTful applications has been
provided as an extension of the existing annotation driven MVC web
framework. Client-side support is provided by the
<classname>RestTemplate</classname> class in the spirit of other
template classes such as <classname>JdbcTemplate</classname> and
<classname>JmsTemplate</classname>. Both server and client side REST
functionality make use of
<interfacename>HttpConverter</interfacename>s to facilitate the
conversion between objects and their representation in HTTP requests
and responses.</para>
<para>The <classname>MarshallingHttpMessageConverter</classname> uses
the <emphasis>Object to XML mapping</emphasis> functionality mentioned
earlier.</para>
<para>Refer to the sections on <link linkend="mvc">MVC</link> and <link
linkend="rest-resttemplate">the RestTemplate</link> for more
information.</para>
</section>
<section xml:id="new-feature-at-mvc">
<title>@MVC additions</title>
<para>A <literal>mvc</literal> namespace has been introduced that greatly simplifies Spring MVC configuration.</para>
<para>Additional annotations such as
<classname>@CookieValue</classname> and
<classname>@RequestHeaders</classname> have been added. See <link
linkend="mvc-ann-cookievalue">Mapping cookie values with the
@CookieValue annotation</link> and <link
linkend="mvc-ann-requestheader">Mapping request header attributes with
the @RequestHeader annotation</link> for more information.</para>
</section>
</section>
<section xml:id="new-feature-validation">
<title>Declarative model validation</title>
<para>Several <link linkend="validation-beanvalidation">validation enhancements</link>,
including JSR 303 support that uses Hibernate Validator as the default provider.</para>
</section>
<section xml:id="new-feature-jee-6">
<title>Early support for Java EE 6</title>
<para>We provide support for asynchronous method invocations through the
use of the new @Async annotation (or EJB 3.1's @Asynchronous
annotation).</para>
<para>JSR 303, JSF 2.0, JPA 2.0, etc</para>
</section>
<section xml:id="new-feature-embedded-databases">
<title>Support for embedded databases</title>
<para>Convenient support for <link
linkend="jdbc-embedded-database-support">embedded Java database
engines</link>, including HSQL, H2, and Derby, is now provided.</para>
</section>
</section>
</chapter>

View File

@ -1,509 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="new-in-3.1"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>New Features and Enhancements in Spring Framework 3.1</title>
<para>This is a list of new features for Spring Framework 3.1. A number of features
do not have dedicated reference documentation but do have complete Javadoc. In such
cases, fully-qualified class names are given. See also <xref linkend="migration-3.1"/>
</para>
<section xml:id="new-in-3.1-cache-abstraction">
<title>Cache Abstraction</title>
<itemizedlist>
<listitem>
<para><xref linkend="cache" /></para>
</listitem>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/02/23/spring-3-1-m1-caching/">
Cache Abstraction</link> (SpringSource team blog)</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-bean-definition-profiles">
<title>Bean Definition Profiles</title>
<itemizedlist>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/">
XML profiles</link> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/">
Introducing @Profile</link> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.Configuration
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.Profile
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-environment-abstraction">
<title>Environment Abstraction</title>
<itemizedlist>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/">
Environment Abstraction</link> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.Environment Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-property-source-abstraction">
<title>PropertySource Abstraction</title>
<itemizedlist>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/02/15/spring-3-1-m1-unified-property-management/">
Unified Property Management</link> (SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.Environment Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.core.env.PropertySource Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.PropertySource
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-code-equivalent-xml-namespaces">
<title>Code equivalents for Spring's XML namespaces</title>
<para>Code-based equivalents to popular Spring XML namespace elements
&lt;context:component-scan/&gt;, &lt;tx:annotation-driven/&gt;
and &lt;mvc:annotation-driven&gt; have been developed, most in the
form of <interfacename>@Enable</interfacename> annotations. These are
designed for use in conjunction with Spring's
<interfacename>@Configuration</interfacename> classes, which were
introduced in Spring Framework 3.0.</para>
<itemizedlist>
<listitem>
<para>See org.springframework.context.annotation.Configuration
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.context.annotation.ComponentScan
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.transaction.annotation.EnableTransactionManagement
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.cache.annotation.EnableCaching Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.web.servlet.config.annotation.EnableWebMvc
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.scheduling.annotation.EnableScheduling
Javadoc</para>
</listitem>
<listitem>
<para>See org.springframework.scheduling.annotation.EnableAsync
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.context.annotation.EnableAspectJAutoProxy
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.context.annotation.EnableLoadTimeWeaving
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.beans.factory.aspectj.EnableSpringConfigured
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-hibernate-4-support">
<title>Support for Hibernate 4.x</title>
<itemizedlist>
<listitem>
<para>See Javadoc for classes within the new
org.springframework.orm.hibernate4 package</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-test-context-profiles">
<title>TestContext framework support for @Configuration classes and bean
definition profiles</title>
<para>The <interfacename>@ContextConfiguration</interfacename>
annotation now supports supplying
<interfacename>@Configuration</interfacename> classes for configuring
the Spring <classname>TestContext</classname>. In addition, a new
<interfacename>@ActiveProfiles</interfacename> annotation has been
introduced to support declarative configuration of active bean
definition profiles in <interfacename>ApplicationContext</interfacename>
integration tests.</para>
<itemizedlist>
<listitem>
<para><link
xl:href="http://blog.springsource.com/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles/">Spring
3.1 M2: Testing with @Configuration Classes and Profiles</link>
(SpringSource Team Blog)</para>
</listitem>
<listitem>
<para>See <xref linkend="testcontext-framework" /></para>
</listitem>
<listitem>
<para>See <xref linkend="testcontext-ctx-management-javaconfig" />
and
<interfacename>org.springframework.test.context.ContextConfiguration</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.ActiveProfiles</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.SmartContextLoader</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.support.DelegatingSmartContextLoader</interfacename>
Javadoc</para>
</listitem>
<listitem>
<para>See
<interfacename>org.springframework.test.context.support.AnnotationConfigContextLoader</interfacename>
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-c-namespace">
<title>c: namespace for more concise constructor injection</title>
<itemizedlist>
<listitem>
<para><xref linkend="beans-c-namespace" /></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-injection-non-javabeans-setters">
<title>Support for injection against non-standard JavaBeans
setters</title>
<para>Prior to Spring Framework 3.1, in order to inject against a property
method it had to conform strictly to JavaBeans property signature rules,
namely that any 'setter' method must be void-returning. It is now possible
in Spring XML to specify setter methods that return any object type. This
is useful when considering designing APIs for method-chaining, where
setter methods return a reference to 'this'.</para>
</section>
<section xml:id="new-in-3.1-servlet-3-code-config">
<title>Support for Servlet 3 code-based configuration of Servlet
Container</title>
<para>The new <interfacename>WebApplicationInitializer</interfacename>
builds atop Servlet 3.0's
<interfacename>ServletContainerInitializer</interfacename> support to
provide a programmatic alternative to the traditional web.xml.</para>
<itemizedlist>
<listitem>
<para>See org.springframework.web.WebApplicationInitializer
Javadoc</para>
</listitem>
<listitem>
<para><link xl:href="http://bit.ly/lrDHja">Diff from Spring's
Greenhouse reference application</link> demonstrating migration
from web.xml to
<interfacename>WebApplicationInitializer</interfacename></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-servlet-3-multipart-resolver">
<title>Support for Servlet 3 MultipartResolver</title>
<itemizedlist>
<listitem>
<para>See
org.springframework.web.multipart.support.StandardServletMultipartResolver
Javadoc</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.1-jpa-without-xml">
<title>JPA EntityManagerFactory bootstrapping without
persistence.xml</title>
<para>In standard JPA, persistence units get defined through
<literal>META-INF/persistence.xml</literal> files in specific jar files
which will in turn get searched for <literal>@Entity</literal> classes.
In many cases, persistence.xml does not contain more than a unit name
and relies on defaults and/or external setup for all other concerns
(such as the DataSource to use, etc). For that reason, Spring Framework
3.1 provides an alternative:
<classname>LocalContainerEntityManagerFactoryBean</classname> accepts a
'packagesToScan' property, specifying base packages to scan for
<literal>@Entity</literal> classes. This is analogous to
<classname>AnnotationSessionFactoryBean</classname>'s property of the
same name for native Hibernate setup, and also to Spring's
component-scan feature for regular Spring beans. Effectively, this
allows for XML-free JPA setup at the mere expense of specifying a base
package for entity scanning: a particularly fine match for Spring
applications which rely on component scanning for Spring beans as well,
possibly even bootstrapped using a code-based Servlet 3.0
initializer.</para>
</section>
<section xml:id="new-in-3.1-handler-method-controller-processing">
<title>New HandlerMethod-based Support Classes For Annotated Controller
Processing</title>
<para>Spring Framework 3.1 introduces a new set of support classes for
processing requests with annotated controllers:</para>
<itemizedlist>
<listitem>
<para><classname>RequestMappingHandlerMapping</classname></para>
</listitem>
<listitem>
<para><classname>RequestMappingHandlerAdapter</classname></para>
</listitem>
<listitem>
<para><classname>ExceptionHandlerExceptionResolver</classname></para>
</listitem>
</itemizedlist>
<para>These classes are a replacement for the existing:</para>
<itemizedlist>
<listitem>
<para><classname>DefaultAnnotationHandlerMapping</classname></para>
</listitem>
<listitem>
<para><classname>AnnotationMethodHandlerAdapter</classname></para>
</listitem>
<listitem>
<para><classname>AnnotationMethodHandlerExceptionResolver</classname></para>
</listitem>
</itemizedlist>
<para>The new classes were developed in response to many requests to
make annotation controller support classes more customizable and open
for extension. Whereas previously you could configure a custom annotated
controller method argument resolver, with the new support classes you
can customize the processing for any supported method argument or return
value type.</para>
<itemizedlist>
<listitem>
<para>See
org.springframework.web.method.support.HandlerMethodArgumentResolver
Javadoc</para>
</listitem>
<listitem>
<para>See
org.springframework.web.method.support.HandlerMethodReturnValueHandler
Javadoc</para>
</listitem>
</itemizedlist>
<para>A second notable difference is the introduction of a
<classname>HandlerMethod</classname> abstraction to represent an
<interfacename>@RequestMapping</interfacename> method. This abstraction is used
throughout by the new support classes as the <literal>handler</literal>
instance. For example a <classname>HandlerInterceptor</classname> can
cast the <literal>handler</literal> from <classname>Object</classname>
to <classname>HandlerMethod</classname> and get access to the target
controller method, its annotations, etc.</para>
<para>The new classes are enabled by default by the MVC namespace and by
Java-based configuration via <interfacename>@EnableWebMvc</interfacename>. The
existing classes will continue to be available but use of the new
classes is recommended going forward.</para>
<para>See <xref linkend="mvc-ann-requestmapping-31-vs-30"/> for additional
details and a list of features not available with the new support classes.</para>
</section>
<section xml:id="new-in-3.1-request-mapping-consumes-produces">
<title>"consumes" and "produces" conditions in
<interfacename>@RequestMapping</interfacename></title>
<para>Improved support for specifying media types consumed by a method
through the <literal>'Content-Type'</literal> header as well as for
producible types specified through the <literal>'Accept'</literal>
header. See <xref linkend="mvc-ann-requestmapping-consumes" /> and <xref
linkend="mvc-ann-requestmapping-produces" /></para>
</section>
<section xml:id="new-in-3.1-flash-redirect-attributes">
<title>Flash Attributes and
<interfacename>RedirectAttributes</interfacename></title>
<para>Flash attributes can now be stored in a
<classname>FlashMap</classname> and saved in the HTTP session to survive
a redirect. For an overview of the general support for flash attributes
in Spring MVC see <xref linkend="mvc-flash-attributes" />.</para>
<para>In annotated controllers, an
<interfacename>@RequestMapping</interfacename> method can add flash
attributes by declaring a method argument of type
<interfacename>RedirectAttributes</interfacename>. This method argument
can now also be used to get precise control over the attributes used in
a redirect scenario. See <xref linkend="mvc-ann-redirect-attributes" />
for more details.</para>
</section>
<section xml:id="new-in-3.1-uri-template-var-enhancements">
<title>URI Template Variable Enhancements</title>
<para>URI template variables from the current request are used in more
places: <itemizedlist>
<listitem>
<para>URI template variables are used in addition to request
parameters when binding a request to
<interfacename>@ModelAttribute</interfacename> method
arguments.</para>
</listitem>
<listitem>
<para>@PathVariable method argument values are merged into the
model before rendering, except in views that generate content in
an automated fashion such as JSON serialization or XML
marshalling.</para>
</listitem>
<listitem>
<para>A redirect string can contain placeholders for URI variables
(e.g. <literal>"redirect:/blog/{year}/{month}"</literal>). When
expanding the placeholders, URI template variables from the
current request are automatically considered.</para>
</listitem>
<listitem>
<para>An <interfacename>@ModelAttribute</interfacename> method
argument can be instantiated from a URI template variable provided
there is a registered Converter or PropertyEditor to convert from
a String to the target object type.</para>
</listitem>
</itemizedlist></para>
</section>
<section xml:id="new-in-3.1-mvc-valid-requestbody">
<title><interfacename>@Valid</interfacename> On
<interfacename>@RequestBody</interfacename> Controller Method Arguments</title>
<para>An <interfacename>@RequestBody</interfacename> method argument can be
annotated with <interfacename>@Valid</interfacename> to invoke automatic
validation similar to the support for
<interfacename>@ModelAttribute</interfacename> method arguments. A resulting
<classname>MethodArgumentNotValidException</classname> is handled in the
<classname>DefaultHandlerExceptionResolver</classname> and results in a
<literal>400</literal> response code.</para>
</section>
<section xml:id="new-in-3.1-mvc-requestpart">
<title><interfacename>@RequestPart</interfacename> Annotation On
Controller Method Arguments</title>
<para>This new annotation provides access to the content of a
"multipart/form-data" request part. See <xref
linkend="mvc-multipart-forms-non-browsers" /> and <xref
linkend="mvc-multipart" />.</para>
</section>
<section xml:id="new-in-3.1-mvc-uricomponentsbuilder">
<title><classname>UriComponentsBuilder</classname> and <classname>UriComponents</classname></title>
<para>A new <classname>UriComponents</classname> class has been added,
which is an immutable container of URI components providing
access to all contained URI components.
A new <classname>UriComponentsBuilder</classname> class is also
provided to help create <classname>UriComponents</classname> instances.
Together the two classes give fine-grained control over all
aspects of preparing a URI including construction, expansion
from URI template variables, and encoding.</para>
<para>In most cases the new classes can be used as a more flexible
alternative to the existing <classname>UriTemplate</classname>
especially since <classname>UriTemplate</classname> relies on those
same classes internally.
</para>
<para>A <classname>ServletUriComponentsBuilder</classname> sub-class
provides static factory methods to copy information from
a Servlet request. See <xref linkend="mvc-construct-encode-uri"/>.
</para>
</section>
</chapter>

View File

@ -1,328 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.0"
xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
xml:id="new-in-3.2" xmlns="http://docbook.org/ns/docbook"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:ns="http://docbook.org/ns/docbook">
<title>New Features and Enhancements in Spring Framework 3.2</title>
<para>This section covers what's new in Spring Framework 3.2. See also
<xref linkend="migration-3.2"/></para>
<section xml:id="new-in-3.2-webmvc-async">
<title>Support for Servlet 3 based asynchronous request processing</title>
<para>The Spring MVC programming model now provides explicit Servlet 3
async support. <interfacename>@RequestMapping</interfacename> methods can
return one of:</para>
<itemizedlist>
<listitem>
<para><interfacename>java.util.concurrent.Callable</interfacename> to
complete processing in a separate thread managed by a task executor
within Spring MVC.</para>
</listitem>
<listitem>
<para><classname>org.springframework.web.context.request.async.DeferredResult</classname>
to complete processing at a later time from a thread not known to
Spring MVC — for example, in response to some external event (JMS,
AMQP, etc.)</para>
</listitem>
<listitem>
<para><classname>org.springframework.web.context.request.async.AsyncTask</classname>
to wrap a <interfacename>Callable</interfacename> and customize the
timeout value or the task executor to use.</para>
</listitem>
</itemizedlist>
<para>See <xref linkend="mvc-ann-async"/>.</para>
</section>
<section xml:id="new-in-3.2-spring-mvc-test">
<title>Spring MVC Test framework</title>
<para>First-class support for testing Spring MVC applications with a
fluent API and without a Servlet container. Server-side tests involve use
of the <classname>DispatcherServlet</classname> while client-side REST
tests rely on the <classname>RestTemplate</classname>. See <xref
linkend="spring-mvc-test-framework" />.</para>
</section>
<section xml:id="new-in-3.2-webmvc-content-negotiation">
<title>Content negotiation improvements</title>
<para>A <interfacename>ContentNegotiationStrategy</interfacename> is now
available for resolving the requested media types from an incoming
request. The available implementations are based on the file extension,
query parameter, the 'Accept' header, or a fixed content type.
Equivalent options were previously available only in the
ContentNegotiatingViewResolver but are now available throughout.</para>
<para><classname>ContentNegotiationManager</classname> is the central
class to use when configuring content negotiation options.
For more details see <xref linkend="mvc-config-content-negotiation" />.</para>
<para>The introduction of <classname>ContentNegotiationManger</classname>
also enables selective suffix pattern matching for incoming requests.
For more details, see the Javadoc of
<link
xl:href="http://static.springsource.org/spring-framework/docs/3.2.0.BUILD-SNAPSHOT/api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html#setUseRegisteredSuffixPatternMatch(boolean)">RequestMappingHandlerMapping.setUseRegisteredSuffixPatternMatch</link>.</para>
</section>
<section xml:id="new-in-3.2-webmvc-controller-advice">
<title><interfacename>@ControllerAdvice</interfacename> annotation</title>
<para>Classes annotated with
<interfacename>@ControllerAdvice</interfacename> can contain
<interfacename>@ExceptionHandler</interfacename>,
<interfacename>@InitBinder</interfacename>, and
<interfacename>@ModelAttribute</interfacename> methods and those will
apply to <interfacename>@RequestMapping</interfacename> methods across
controller hierarchies as opposed to the controller hierarchy within which
they are declared. <interfacename>@ControllerAdvice</interfacename> is a
component annotation allowing implementation classes to be auto-detected
through classpath scanning.</para>
</section>
<section xml:id="new-in-3.2-matrix-variables">
<title>Matrix variables</title>
<para>A new <interfacename>@MatrixVariable</interfacename> annotation adds
support for extracting matrix variables from the request URI. For more
details see <xref linkend="mvc-ann-matrix-variables" />.</para>
</section>
<section xml:id="new-in-3.2-dispatcher-servlet-initializer">
<title>Abstract base class for code-based Servlet 3+ container
initialization</title>
<para>An abstract base class implementation of the
<interfacename>WebApplicationInitializer</interfacename> interface is
provided to simplify code-based registration of a DispatcherServlet and
filters mapped to it. The new class is named
<classname>AbstractDispatcherServletInitializer</classname> and its
sub-class
<classname>AbstractAnnotationConfigDispatcherServletInitializer</classname>
can be used with Java-based Spring configuration. For more details see
<xref linkend="mvc-container-config" />.</para>
</section>
<section xml:id="new-in-3.2-webmvc-exception-handler-support">
<title><classname>ResponseEntityExceptionHandler</classname> class</title>
<para>A convenient base class with an
<interfacename>@ExceptionHandler</interfacename> method that handles
standard Spring MVC exceptions and returns a
<classname>ResponseEntity</classname> that allowing customizing and
writing the response with HTTP message converters. This serves as an
alternative to the <classname>DefaultHandlerExceptionResolver</classname>,
which does the same but returns a <classname>ModelAndView</classname>
instead.</para>
<para>See the revised <xref linkend="mvc-exceptionhandlers" /> including
information on customizing the default Servlet container error
page.</para>
</section>
<section xml:id="new-in-3.2-webmvc-generic-types-rest-template">
<title>Support for generic types in the
<classname>RestTemplate</classname> and in
<interfacename>@RequestBody</interfacename> arguments</title>
<para>The <classname>RestTemplate</classname> can now read an HTTP
response to a generic type (e.g. <code>List&lt;Account&gt;</code>). There
are three new <code>exchange()</code> methods that accept
<classname>ParameterizedTypeReference</classname>, a new class that
enables capturing and passing generic type info.</para>
<para>In support of this feature, the
<interfacename>HttpMessageConverter</interfacename> is extended by
<interfacename>GenericHttpMessageConverter</interfacename> adding a method
for reading content given a specified parameterized type. The new
interface is implemented by the
<classname>MappingJacksonHttpMessageConverter</classname> and also by a
new <classname>Jaxb2CollectionHttpMessageConverter</classname> that can
read read a generic <interfacename>Collection</interfacename> where the
generic type is a JAXB type annotated with
<interfacename>@XmlRootElement</interfacename> or
<interfacename>@XmlType</interfacename>.</para>
</section>
<section xml:id="new-in-3.2-webmvc-jackson-json">
<title>Jackson JSON 2 and related improvements</title>
<para>The Jackson JSON 2 library is now supported. Due to packaging
changes in the Jackson library, there are separate classes in Spring MVC
as well. Those are
<classname>MappingJackson2HttpMessageConverter</classname> and
<classname>MappingJackson2JsonView</classname>. Other related
configuration improvements include support for pretty printing as well as
a <classname>JacksonObjectMapperFactoryBean</classname> for convenient
customization of an <classname>ObjectMapper</classname> in XML
configuration.</para>
</section>
<section xml:id="new-in-3.2-webmvc-tiles3">
<title>Tiles 3</title>
<para>Tiles 3 is now supported in addition to Tiles 2.x. Configuring
it should be very similar to the Tiles 2 configuration, i.e. the
combination of <classname>TilesConfigurer</classname>,
<classname>TilesViewResolver</classname> and <classname>TilesView</classname>
except using the <code>tiles3</code> instead of the <code>tiles2</code>
package.</para>
<para>Also note that besides the version number change, the tiles
dependencies have also changed. You will need to have a subset or all of
<filename>tiles-request-api</filename>, <filename>tiles-api</filename>,
<filename>tiles-core</filename>, <filename>tiles-servlet</filename>,
<filename>tiles-jsp</filename>, <filename>tiles-el</filename>.
</para>
</section>
<section xml:id="new-in-3.2-webmvc-request-body-arg-with-binding-result">
<title><interfacename>@RequestBody</interfacename> improvements</title>
<para>An <interfacename>@RequestBody</interfacename> or an
<interfacename>@RequestPart</interfacename> argument can now be followed
by an <interfacename>Errors</interfacename> argument making it possible to
handle validation errors (as a result of an
<interfacename>@Valid</interfacename> annotation) locally within the
<interfacename>@RequestMapping</interfacename> method.
<interfacename>@RequestBody</interfacename> now also supports a required
flag.</para>
</section>
<section xml:id="new-in-3.2-webmvc-http-patch">
<title>HTTP PATCH method</title>
<para>The HTTP request method <code>PATCH</code> may now be used in
<interfacename>@RequestMapping</interfacename> methods as well as in the
<classname>RestTemplate</classname> in conjunction with Apache
HttpComponents HttpClient version 4.2 or later. The JDK
<classname>HttpURLConnection</classname> does not support the
<code>PATCH</code> method.</para>
</section>
<section xml:id="new-in-3.2-webmvc-mapped-interceptor-exclude-patterns">
<title>Excluded patterns in mapped interceptors</title>
<para>Mapped interceptors now support URL patterns to be excluded. The MVC
namespace and the MVC JavaConfig both expose these options.</para>
</section>
<section xml:id="new-in-3.2-meta-annotations">
<title>Using meta-annotations for injection points and for bean definition methods</title>
<para>As of 3.2, Spring allows for <interfacename>@Autowired</interfacename> and
<interfacename>@Value</interfacename> to be used as meta-annotations,
e.g. to build custom injection annotations in combination with specific qualifiers.
Analogously, you may build custom <interfacename>@Bean</interfacename> definition
annotations for <interfacename>@Configuration</interfacename> classes,
e.g. in combination with specific qualifiers, @Lazy, @Primary, etc.</para>
</section>
<section xml:id="new-in-3.2-jcache">
<title>Initial support for JCache 0.5</title>
<para>Spring provides a CacheManager adapter for JCache, building against the JCache 0.5
preview release. Full JCache support is coming next year, along with Java EE 7 final.</para>
</section>
<section xml:id="new-in-3.2-date-time-format-without-joda">
<title>Support for <interfacename>@DateTimeFormat</interfacename> without
Joda Time</title>
<para>The <interfacename>@DateTimeFormat</interfacename> annotation can
now be used without needing a dependency on the Joda Time library. If Joda
Time is not present the JDK <classname>SimpleDateFormat</classname> will
be used to parse and print date patterns. When Joda Time is present it
will continue to be used in preference to
<classname>SimpleDateFormat</classname>.</para>
</section>
<section xml:id="new-in-3.2-global-date-time-format">
<title>Global date &amp; time formatting</title>
<para>It is now possible to define global formats that will be used when
parsing and printing date and time types. See <xref
linkend="format-configuring-formatting-globaldatetimeformat" /> for
details.</para>
</section>
<section xml:id="new-in-3.2-testing">
<title>New Testing Features</title>
<para>In addition to the aforementioned inclusion of the <link
linkend="spring-mvc-test-framework">Spring MVC Test Framework</link> in
the <literal>spring-test</literal> module, the <emphasis>Spring
TestContext Framework</emphasis> has been revised with support for
integration testing web applications as well as configuring application
contexts with context initializers. For further details, consult the
following.</para>
<itemizedlist>
<listitem>
<para>Configuring and <link
linkend="testcontext-ctx-management-web">loading a
WebApplicationContext</link> in integration tests</para>
</listitem>
<listitem>
<para>Configuring <link
linkend="testcontext-ctx-management-ctx-hierarchies">context hierarchies</link>
in integration tests</para>
</listitem>
<listitem>
<para>Testing <link linkend="testcontext-web-scoped-beans">request and
session scoped beans</link></para>
</listitem>
<listitem>
<para>Improvements to <link linkend="mock-objects-servlet">Servlet API
mocks</link></para>
</listitem>
<listitem>
<para>Configuring test application contexts with <link
linkend="testcontext-ctx-management-initializers">ApplicationContextInitializers</link></para>
</listitem>
</itemizedlist>
</section>
<section xml:id="new-in-3.2-concurrency">
<title>Concurrency refinements across the framework</title>
<para>Spring Framework 3.2 includes fine-tuning of concurrent data structures
in many parts of the framework, minimizing locks and generally improving the
arrangements for highly concurrent creation of scoped/prototype beans.</para>
</section>
<section xml:id="new-in-3.2-build">
<title>New Gradle-based build and move to GitHub</title>
<para>Building and contributing to the framework has never been simpler with
our move to a Gradle-based build system and source control at GitHub.
See the <link xl:href="https://github.com/SpringSource/spring-framework#building-from-source">
building from source</link> section of the README and the
<link xl:href="https://github.com/SpringSource/spring-framework/blob/master/CONTRIBUTING.md">
contributor guidelines</link> for complete details.</para>
</section>
<section xml:id="new-in-3.2-java7">
<title>Refined Java SE 7 / OpenJDK 7 support</title>
<para>Last but not least, Spring Framework 3.2 comes with refined Java 7 support
within the framework as well as through upgraded third-party dependencies:
specifically, CGLIB 3.0, ASM 4.0 (both of which come as inlined dependencies with
Spring now) and AspectJ 1.7 support (next to the existing AspectJ 1.6 support).</para>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,939 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="overview"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Introduction to Spring Framework</title>
<para>Spring Framework is a Java platform that provides comprehensive
infrastructure support for developing Java applications. Spring handles the
infrastructure so you can focus on your application.<!--First text mention should be *Spring Framework* not just *Spring*. I revised next sentence because *plumbing* is idiomatic and --><!--*the domain problem* is an unclear reference. Isn't the point that Spring takes care of *under the covers* so you can focus on app? TR: OK.--></para>
<para>Spring enables you to build applications from “plain old Java objects”
(POJOs) and to apply enterprise services non-invasively to POJOs. This
capability applies to the Java SE programming model and to full and partial
Java EE.</para>
<para>Examples of how you, as an application developer, can use the Spring
platform advantage:<!--In each of the examples, clarify what you mean by *the implementer* (identify it, or is it a person?). ALSO in each sentence replace--><!--*dealing with* APIs with what you mean: what does not have to be done in regard to APIs? IMPORTANT, because this discusses advantage--><!--of product. TR: REVISED, PLS REVIEW. I changed *implementer* to *application developer* and put it upfront rather than repeat it.--></para>
<itemizedlist>
<listitem>
<para>Make a Java method execute in a database transaction without
having to deal with transaction APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a remote procedure without having to deal
with remote APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a management operation without having to
deal with JMX APIs.</para>
</listitem>
<listitem>
<para>Make a local Java method a message handler without having to deal
with JMS APIs.</para>
</listitem>
</itemizedlist>
<section xml:id="overview-dependency-injection">
<title>Dependency Injection and Inversion of Control</title>
<sidebar xml:id="background-ioc">
<title>Background</title>
<para><quote><emphasis>The question is, what aspect of control are
[they] inverting?</emphasis></quote> Martin Fowler posed this question
about Inversion of Control (IoC) on his site in 2004. Fowler suggested
renaming the principle to make it more self-explanatory and came up with
<firstterm>Dependency Injection</firstterm>.</para>
<para>For insight into IoC and DI, refer to Fowler's article at <link
xl:href="http://martinfowler.com/articles/injection.html">http://martinfowler.com/articles/injection.html</link>.</para>
</sidebar>
<para>Java applications -- a loose term that runs the gamut from
constrained applets to n-tier server-side enterprise applications --
typically consist of objects that collaborate to form the application
proper. Thus the objects in an application have
<emphasis>dependencies</emphasis> on each other.</para>
<para>Although the Java platform provides a wealth of application
development functionality, it lacks the means to organize the basic
building blocks into a coherent whole, leaving that task to architects and
developers. True, you can use design patterns such as
<firstterm>Factory</firstterm>, <firstterm>Abstract Factory</firstterm>,
<firstterm>Builder</firstterm>, <firstterm>Decorator</firstterm>, and
<firstterm>Service Locator</firstterm> to compose the various classes and
object instances that make up an application. However, these patterns are
simply that: best practices given a name, with a description of what the
pattern does, where to apply it, the problems it addresses, and so forth.
Patterns are formalized best practices that <emphasis>you must implement
yourself</emphasis> in your application.</para>
<para>The Spring Framework <emphasis>Inversion of Control</emphasis> (IoC)
component addresses this concern by providing a formalized means of
composing disparate components into a fully working application ready for
use. <!--Preceding sentence sounds like a description of what patterns do (and Spring uses patterns). Distinguish from patterns.-->The
Spring Framework codifies formalized design patterns as first-class
objects that you can integrate into your own application(s). <!--Preceding sentence suggests that you already have the application and *then* you integrate design patterns into it. Again, I--><!--don't see a major distinction here from use of patterns (as described in earlier paragraph) and use of IoC component to build apps.
TR: This section doesn't read well and I think we should try to rewrite it.-->Numerous
organizations and institutions use the Spring Framework in this manner to
engineer robust, <emphasis>maintainable</emphasis> applications.</para>
</section>
<section xml:id="overview-modules">
<title>Modules</title>
<para>The Spring Framework consists of features organized into about 20
modules. These modules are grouped into Core Container, Data
Access/Integration, Web, AOP (Aspect Oriented Programming),
Instrumentation, and Test, as shown in the following diagram.</para>
<para><mediaobject>
<imageobject>
<imagedata align="center" fileref="images/spring-overview.png" format="PNG" width="400" />
</imageobject>
<caption><para>Overview of the Spring Framework</para></caption>
</mediaobject></para>
<section xml:id="overview-core-container">
<title>Core Container</title>
<para>The <link linkend="beans-introduction"><emphasis>Core
Container</emphasis></link> consists of the Core, Beans, Context, and
Expression Language modules.</para>
<para>The <link linkend="beans-introduction"><emphasis>Core and
Beans</emphasis></link> modules provide the fundamental parts of the
framework, including the IoC and Dependency Injection features. The
<classname>BeanFactory</classname> is a sophisticated implementation of
the factory pattern. It removes the need for programmatic singletons and
allows you to decouple the configuration and specification of
dependencies from your actual program logic.</para>
<para>The <link
linkend="context-introduction"><emphasis>Context</emphasis></link>
module builds on the solid base provided by the <link
linkend="beans-introduction"><emphasis>Core and Beans</emphasis></link>
modules: it is a means to access objects in a framework-style manner
that is similar to a JNDI registry. The Context module inherits its
features from the Beans module and adds support for internationalization
(using, for example, resource bundles), event-propagation,
resource-loading, and the transparent creation of contexts by, for
example, a servlet container. The Context module also supports Java EE
features such as EJB, JMX ,and basic remoting. The
<classname>ApplicationContext</classname> interface is the focal point
of the Context module.</para>
<para>The <link linkend="expressions"><emphasis>Expression
Language</emphasis></link> module <!--Provide link as you do with others TR: FIXED.-->provides
a powerful expression language for querying and manipulating an object
graph at runtime. It is an extension of the unified expression language
(unified EL) as specified in the JSP 2.1 specification. The language
supports setting and getting property values, property assignment,
method invocation, accessing the context of arrays, collections and
indexers, logical and arithmetic operators, named variables, and
retrieval of objects by name from Spring's IoC container. It also
supports list projection and selection as well as common list
aggregations.</para>
</section>
<section xml:id="overview-data-access">
<title>Data Access/Integration</title>
<para>The <emphasis>Data Access/Integration</emphasis> layer consists of
the JDBC, ORM, OXM, JMS and Transaction modules.</para>
<para>The <link linkend="jdbc-introduction">JDBC</link> module provides
a JDBC-abstraction layer that removes the need to do tedious JDBC coding
and parsing of database-vendor specific error codes.</para>
<para>The <link
linkend="orm-introduction"><emphasis>ORM</emphasis></link> module
provides integration layers for popular object-relational mapping APIs,
including <link linkend="orm-jpa">JPA</link>, <link
linkend="orm-jdo">JDO</link>, <link
linkend="orm-hibernate">Hibernate</link>, and <link
linkend="orm-ibatis">iBatis</link>. Using the ORM package you can use
all of these O/R-mapping frameworks in combination with all of the other
features Spring offers, such as the simple declarative transaction
management feature mentioned previously.</para>
<para>The <link linkend="oxm">OXM</link> module provides an abstraction
layer that supports Object/XML mapping implementations for JAXB, Castor,
XMLBeans, JiBX and XStream.</para>
<para>The Java Messaging Service (<link linkend="jms">JMS</link>) module
contains features for producing and consuming messages.</para>
<para>The <link linkend="transaction">Transaction</link> module supports
programmatic and declarative transaction management for classes that
implement special interfaces and for <emphasis>all your POJOs (plain old
Java objects)</emphasis>.</para>
</section>
<section xml:id="overview-web">
<title>Web</title>
<para>The <emphasis>Web</emphasis> layer consists of the Web,
Web-Servlet, Web-Struts, and Web-Portlet modules.</para>
<para>Spring's <emphasis>Web</emphasis> module provides basic
web-oriented integration features such as multipart file-upload
functionality and the initialization of the IoC container using servlet
listeners and a web-oriented application context. It also contains the
web-related parts of Spring's remoting support.</para>
<para>The <emphasis>Web-Servlet</emphasis> module contains Spring's
model-view-controller (<link
linkend="mvc-introduction"><emphasis>MVC</emphasis></link>)
implementation for web applications. Spring's MVC framework provides a
clean separation between domain model code and web forms, and integrates
with all the other features of the Spring Framework.<!--MVC allows you to use *all other features*? (Or just all other features in Web layer?) How do you mean? Does this need elaboration?
It sounds important.--><!--TR: REVISED, PLS REVIEW.--></para>
<para>The <emphasis>Web-Struts</emphasis> module contains the support
classes for integrating a classic Struts web tier within a Spring
application. Note that this support is now deprecated as of Spring 3.0.
Consider migrating your application to Struts 2.0 and its Spring
integration or to a Spring MVC solution.</para>
<para>The <emphasis>Web-Portlet</emphasis> module provides the MVC
implementation to be used in a portlet environment and mirrors the
functionality of Web-Servlet module.<!--mirrors it in what way?--><!--TR: REVISED, PLS REVIEW. The functionality is mirrored - one for Servlets and the other for Portlets--></para>
</section>
<section xml:id="overview-aop-instrumentation">
<title>AOP and Instrumentation</title>
<para>Spring's <link
linkend="aop-introduction"><emphasis>AOP</emphasis></link> module
provides an <emphasis>AOP Alliance</emphasis>-compliant aspect-oriented
programming implementation allowing you to define, for example,
method-interceptors and pointcuts to cleanly decouple code that
implements functionality that should be separated. Using source-level
metadata functionality, you can also incorporate behavioral information
into your code, in a manner similar to that of .NET attributes.</para>
<para>The separate <emphasis>Aspects</emphasis> module provides
integration with AspectJ.<!--Aspects module not shown in diagram, add it to that. Also, why is this line under AOP and Instrumentation if it's separate?
TR: OK. Added to diagram.--></para>
<para>The <emphasis>Instrumentation</emphasis> module provides class
instrumentation support and classloader implementations to be used in
certain application servers.</para>
</section>
<section xml:id="overview-testing">
<title>Test</title>
<para>The <emphasis>Test</emphasis> module supports the testing of
Spring components with JUnit or TestNG. It provides consistent loading
of Spring ApplicationContexts and caching of those contexts. It also
provides mock objects that you can use to test your code in
isolation.</para>
</section>
</section>
<section xml:id="overview-usagescenarios">
<title>Usage scenarios</title>
<para>The building blocks described previously make Spring a logical
choice in many scenarios, from applets to full-fledged enterprise
applications that use Spring's transaction management functionality and
web framework integration.</para>
<para><mediaobject>
<imageobject>
<imagedata align="center" fileref="images/overview-full.png" format="PNG" width="400" />
</imageobject>
<caption><para>Typical full-fledged Spring web
application</para></caption>
</mediaobject></para>
<para>Spring's <link linkend="transaction-declarative">declarative
transaction management features</link> make the web application fully
transactional, just as it would be if you used EJB container-managed
transactions. All your custom business logic can be implemented with
simple POJOs and managed by Spring's IoC container. Additional services
include support for sending email and validation that is independent of
the web layer, which lets you choose where to execute validation rules.
Spring's ORM support is integrated with JPA, Hibernate, JDO and iBatis;
for example, when using Hibernate, you can continue to use your existing
mapping files and standard Hibernate
<interfacename>SessionFactory</interfacename> configuration. Form
controllers seamlessly integrate the web-layer with the domain model,
removing the need for <classname>ActionForms</classname> or other classes
that transform HTTP parameters to values for your domain model.</para>
<para><mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/overview-thirdparty-web.png" format="PNG"
width="400"/>
</imageobject>
<caption><para>Spring middle-tier using a third-party web
framework</para></caption>
</mediaobject></para>
<para>Sometimes circumstances do not allow you to completely switch to a
different framework. The Spring Framework does <emphasis>not</emphasis>
force you to use everything within it; it is not an
<emphasis>all-or-nothing</emphasis> solution. Existing front-ends built
with WebWork, Struts, Tapestry, or other UI frameworks can be integrated
with a Spring-based middle-tier, which allows you to use Spring
transaction features. You simply need to wire up your business logic using
an <classname>ApplicationContext</classname> and use a
<classname>WebApplicationContext </classname>to integrate your web
layer.</para>
<para><mediaobject>
<imageobject>
<imagedata align="center" fileref="images/overview-remoting.png"
format="PNG" width="400" />
</imageobject>
<caption><para>Remoting usage scenario</para></caption>
</mediaobject></para>
<para>When you need to access existing code through web services, you can
use Spring's <literal>Hessian-</literal>, <literal>Burlap-</literal>,
<literal>Rmi-</literal> or <classname>JaxRpcProxyFactory</classname>
classes. Enabling remote access to existing applications is not
difficult.</para>
<para><mediaobject>
<imageobject>
<imagedata align="center" fileref="images/overview-ejb.png"
format="PNG" width="400" />
</imageobject>
<caption><para>EJBs - Wrapping existing POJOs</para></caption>
</mediaobject></para>
<para>The Spring Framework also provides an <link linkend="ejb">access and
abstraction layer</link> for Enterprise JavaBeans, enabling you to reuse
your existing POJOs and wrap them in stateless session beans for use in
scalable, fail-safe web applications that might need declarative
security.</para>
<section xml:id="dependency-management">
<title>Dependency Management and Naming Conventions</title>
<para>Dependency management and dependency injection are different
things. To get those nice features of Spring into your application (like
dependency injection) you need to assemble all the libraries needed (jar
files) and get them onto your classpath at runtime, and possibly at
compile time. These dependencies are not virtual components that are
injected, but physical resources in a file system (typically). The
process of dependency management involves locating those resources,
storing them and adding them to classpaths. Dependencies can be direct
(e.g. my application depends on Spring at runtime), or indirect (e.g. my
application depends on <code>commons-dbcp</code> which depends on
<code>commons-pool</code>). The indirect dependencies are also known as
"transitive" and it is those dependencies that are hardest to identify
and manage.</para>
<para>If you are going to use Spring you need to get a copy of the jar
libraries that comprise the pieces of Spring that you need. To make this
easier Spring is packaged as a set of modules that separate the
dependencies as much as possible, so for example if you don't want to
write a web application you don't need the spring-web modules. To refer
to Spring library modules in this guide we use a shorthand naming
convention <code>spring-*</code> or <code>spring-*.jar,</code> where "*"
represents the short name for the module (e.g. <code>spring-core</code>,
<code>spring-webmvc</code>, <code>spring-jms</code>, etc.). The actual
jar file name that you use may be in this form (see below) or it may
not, and normally it also has a version number in the file name (e.g.
<code>spring-core-3.0.0.RELEASE.jar</code>).</para>
<para>In general, Spring publishes its artifacts to four different
places:<itemizedlist>
<listitem>
<para>On the community download site <link
xl:href="http://www.springsource.org/download/community">http://www.springsource.org/download/community</link>.
Here you find all the Spring jars bundled together into a zip file
for easy download. The names of the jars here since version 3.0
are in the form
<code>org.springframework.*-&lt;version&gt;.jar</code>.</para>
</listitem>
<listitem>
<para>Maven Central, which is the default repository that Maven
queries, and does not require any special configuration to use.
Many of the common libraries that Spring depends on also are
available from Maven Central and a large section of the Spring
community uses Maven for dependency management, so this is
convenient for them. The names of the jars here are in the form
<code>spring-*-&lt;version&gt;.jar</code> and the Maven groupId is
<code>org.springframework</code>.</para>
</listitem>
<listitem>
<para>The Enterprise Bundle Repository (EBR), which is run by
SpringSource and also hosts all the libraries that integrate with
Spring. Both Maven and Ivy repositories are available here for all
Spring jars and their dependencies, plus a large number of other
common libraries that people use in applications with Spring. Both
full releases and also milestones and development snapshots are
deployed here. The names of the jar files are in the same form as
the community download
(<code>org.springframework.*-&lt;version&gt;.jar</code>), and the
dependencies are also in this "long" form, with external libraries
(not from SpringSource) having the prefix
<code>com.springsource</code>. See the <link
xl:href="http://www.springsource.com/repository/app/faq">FAQ</link>
for more information.</para>
</listitem>
<listitem>
<para>In a public Maven repository hosted on Amazon S3 for
development snapshots and milestone releases (a copy of the final
releases is also held here). The jar file names are in the same
form as Maven Central, so this is a useful place to get
development versions of Spring to use with other libraries deployed
in Maven Central.</para>
</listitem>
</itemizedlist></para>
<para>So the first thing you need to decide is how to manage your
dependencies: most people use an automated system like Maven or Ivy, but
you can also do it manually by downloading all the jars yourself. When
obtaining Spring with Maven or Ivy you have then to decide which place
you'll get it from. In general, if you care about OSGi, use the EBR,
since it houses OSGi compatible artifacts for all of Spring's
dependencies, such as Hibernate and Freemarker. If OSGi does not matter
to you, either place works, though there are some pros and cons between
them. In general, pick one place or the other for your project; do not
mix them. This is particularly important since EBR artifacts necessarily
use a different naming convention than Maven Central artifacts.</para>
<para><table>
<title>Comparison of Maven Central and SpringSource EBR
Repositories</title>
<tgroup cols="3">
<thead>
<row>
<entry>Feature</entry>
<entry>Maven Central</entry>
<entry>EBR</entry>
</row>
</thead>
<tbody>
<row>
<entry>OSGi Compatible</entry>
<entry>Not explicit</entry>
<entry>Yes</entry>
</row>
<row>
<entry>Number of Artifacts</entry>
<entry>Tens of thousands; all kinds</entry>
<entry>Hundreds; those that Spring integrates with</entry>
</row>
<row>
<entry>Consistent Naming Conventions</entry>
<entry>No</entry>
<entry>Yes</entry>
</row>
<row>
<entry>Naming Convention: GroupId</entry>
<entry>Varies. Newer artifacts often use domain name, e.g.
org.slf4j. Older ones often just use the artifact name, e.g.
log4j.</entry>
<entry>Domain name of origin or main package root, e.g.
org.springframework</entry>
</row>
<row>
<entry>Naming Convention: ArtifactId</entry>
<entry>Varies. Generally the project or module name, using a
hyphen "-" separator, e.g. spring-core, logj4.</entry>
<entry>Bundle Symbolic Name, derived from the main package
root, e.g. org.springframework.beans. If the jar had to be
patched to ensure OSGi compliance then com.springsource is
appended, e.g. com.springsource.org.apache.log4j</entry>
</row>
<row>
<entry>Naming Convention: Version</entry>
<entry>Varies. Many new artifacts use m.m.m or m.m.m.X (with
m=digit, X=text). Older ones use m.m. Some neither. Ordering
is defined but not often relied on, so not strictly
reliable.</entry>
<entry>OSGi version number m.m.m.X, e.g. 3.0.0.RC3. The text
qualifier imposes alphabetic ordering on versions with the
same numeric values.</entry>
</row>
<row>
<entry>Publishing</entry>
<entry>Usually automatic via rsync or source control updates.
Project authors can upload individual jars to JIRA.</entry>
<entry>Manual (JIRA processed by SpringSource)</entry>
</row>
<row>
<entry>Quality Assurance</entry>
<entry>By policy. Accuracy is responsibility of
authors.</entry>
<entry>Extensive for OSGi manifest, Maven POM and Ivy
metadata. QA performed by Spring team.</entry>
</row>
<row>
<entry>Hosting</entry>
<entry>Contegix. Funded by Sonatype with several
mirrors.</entry>
<entry>S3 funded by SpringSource.</entry>
</row>
<row>
<entry>Search Utilities</entry>
<entry>Various</entry>
<entry><link
xl:href="http://www.springsource.com/repository">http://www.springsource.com/repository</link></entry>
</row>
<row>
<entry>Integration with SpringSource Tools</entry>
<entry>Integration through STS with Maven dependency
management</entry>
<entry>Extensive integration through STS with Maven, Roo,
CloudFoundry</entry>
</row>
</tbody>
</tgroup>
</table></para>
<section xml:id="overview-spring-dependencies">
<title>Spring Dependencies and Depending on Spring</title>
<para>Although Spring provides integration and support for a huge
range of enterprise and other external tools, it intentionally keeps
its mandatory dependencies to an absolute minimum: you shouldn't have
to locate and download (even automatically) a large number of jar
libraries in order to use Spring for simple use cases. For basic
dependency injection there is only one mandatory external dependency,
and that is for logging (see below for a more detailed description of
logging options).</para>
<para>Next we outline the basic steps needed to configure an
application that depends on Spring, first with Maven and then with
Ivy. In all cases, if anything is unclear, refer to the documentation
of your dependency management system, or look at some sample code -
Spring itself uses Ivy to manage dependencies when it is building, and
our samples mostly use Maven.</para>
</section>
<section xml:id="overview-maven-dependency-management">
<title>Maven Dependency Management</title>
<para>If you are using Maven for dependency management you don't even
need to supply the logging dependency explicitly. For example, to
create an application context and use dependency injection to
configure an application, your Maven dependencies will look like
this:</para>
<para><programlisting language="xml">&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting></para>
<para>That's it. Note the scope can be declared as runtime if you
don't need to compile against Spring APIs, which is typically the case
for basic dependency injection use cases.</para>
<para>We used the Maven Central naming conventions in the example
above, so that works with Maven Central or the SpringSource S3 Maven
repository. To use the S3 Maven repository (e.g. for milestones or
developer snapshots), you need to specify the repository location in
your Maven configuration. For full releases:</para>
<programlisting language="xml">&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.release&lt;/id&gt;
&lt;url&gt;http://repo.springsource.org/release/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>For milestones:</para>
<programlisting language="xml">&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.milestone&lt;/id&gt;
&lt;url&gt;http://repo.springsource.org/milestone/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>And for snapshots:</para>
<programlisting language="xml">&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.maven.snapshot&lt;/id&gt;
&lt;url&gt;http://repo.springsource.org/snapshot/&lt;/url&gt;
&lt;snapshots&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;/snapshots&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>To use the SpringSource EBR you would need to use a different
naming convention for the dependencies. The names are usually easy to
guess, e.g. in this case it is:</para>
<programlisting language="xml">&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;org.springframework.context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;</programlisting>
<para>You also need to declare the location of the repository
explicitly (only the URL is important):</para>
<programlisting language="xml">&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;com.springsource.repository.bundles.release&lt;/id&gt;
&lt;url&gt;http://repository.springsource.com/maven/bundles/release/&lt;/url&gt;
&lt;/repository&gt;
&lt;/repositories&gt;</programlisting>
<para>If you are managing your dependencies by hand, the URL in the
repository declaration above is not browsable, but there is a user
interface at <link
xl:href="http://www.springsource.com/repository">http://www.springsource.com/repository</link>
that can be used to search for and download dependencies. It also has
handy snippets of Maven and Ivy configuration that you can copy and
paste if you are using those tools.</para>
</section>
<section xml:id="overview-ivy-dependency-management">
<title>Ivy Dependency Management</title>
<para>If you prefer to use <link
xl:href="http://ant.apache.org/ivy">Ivy</link> to manage dependencies
then there are similar names and configuration options. </para>
<para>To configure Ivy to point to the SpringSource EBR add the
following resolvers to your
<filename>ivysettings.xml</filename>:</para>
<programlisting language="xml">&lt;resolvers&gt;
&lt;url name="com.springsource.repository.bundles.release"&gt;
&lt;ivy pattern="http://repository.springsource.com/ivy/bundles/release/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;artifact pattern="http://repository.springsource.com/ivy/bundles/release/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;/url&gt;
&lt;url name="com.springsource.repository.bundles.external"&gt;
&lt;ivy pattern="http://repository.springsource.com/ivy/bundles/external/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;artifact pattern="http://repository.springsource.com/ivy/bundles/external/
[organisation]/[module]/[revision]/[artifact]-[revision].[ext]" /&gt;
&lt;/url&gt;
&lt;/resolvers&gt;</programlisting>
<para>The XML above is not valid because the lines are too long - if
you copy-paste then remove the extra line endings in the middle of the
url patterns.</para>
<para>Once Ivy is configured to look in the EBR adding a dependency is
easy. Simply pull up the details page for the bundle in question in
the repository browser and you'll find an Ivy snippet ready for you to
include in your dependencies section. For example (in
<filename>ivy.xml</filename>): </para>
<programlisting language="xml">&lt;dependency org="org.springframework"
name="org.springframework.core" rev="3.0.0.RELEASE" conf="compile-&gt;runtime"/&gt;</programlisting>
</section>
</section>
<section xml:id="overview-logging">
<title>Logging</title>
<para>Logging is a very important dependency for Spring because a) it is
the only mandatory external dependency, b) everyone likes to see some
output from the tools they are using, and c) Spring integrates with lots
of other tools all of which have also made a choice of logging
dependency. One of the goals of an application developer is often to
have unified logging configured in a central place for the whole
application, including all external components. This is more difficult
than it might have been since there are so many choices of logging
framework.</para>
<para>The mandatory logging dependency in Spring is the Jakarta Commons
Logging API (JCL). We compile against JCL and we also make JCL
<classname>Log</classname> objects visible for classes that extend the
Spring Framework. It's important to users that all versions of Spring
use the same logging library: migration is easy because backwards
compatibility is preserved even with applications that extend Spring.
The way we do this is to make one of the modules in Spring depend
explicitly on <code>commons-logging</code> (the canonical implementation
of JCL), and then make all the other modules depend on that at compile
time. If you are using Maven for example, and wondering where you picked
up the dependency on <code>commons-logging</code>, then it is from
Spring and specifically from the central module called
<code>spring-core</code>.</para>
<para>The nice thing about <code>commons-logging</code> is that you
don't need anything else to make your application work. It has a runtime
discovery algorithm that looks for other logging frameworks in well
known places on the classpath and uses one that it thinks is appropriate
(or you can tell it which one if you need to). If nothing else is
available you get pretty nice looking logs just from the JDK
(java.util.logging or JUL for short). You should find that your Spring
application works and logs happily to the console out of the box in most
situations, and that's important.</para>
<section xml:id="overview-not-using-commons-logging">
<title>Not Using Commons Logging</title>
<para>Unfortunately, the runtime discovery algorithm in
<code>commons-logging</code>, while convenient for the end-user, is
problematic. If we could turn back the clock and start Spring now
as a new project it would use a different logging dependency. The
first choice would probably be the Simple Logging Facade for Java (<link
xl:href="http://www.slf4j.org">SLF4J</link>), which is also used by a lot
of other tools that people use with Spring inside their
applications.</para>
<para>Switching off <code>commons-logging</code> is easy: just make
sure it isn't on the classpath at runtime. In Maven terms you exclude
the dependency, and because of the way that the Spring dependencies
are declared, you only have to do that once.</para>
<programlisting language="xml">&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;commons-logging&lt;/groupId&gt;
&lt;artifactId&gt;commons-logging&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>Now this application is probably broken because there is no
implementation of the JCL API on the classpath, so to fix it a new one
has to be provided. In the next section we show you how to provide an
alternative implementation of JCL using SLF4J as an example.</para>
</section>
<section xml:id="overview-logging-slf4j">
<title>Using SLF4J</title>
<para>SLF4J is a cleaner dependency and more efficient at runtime than
<code>commons-logging</code> because it uses compile-time bindings
instead of runtime discovery of the other logging frameworks it
integrates. This also means that you have to be more explicit about what
you want to happen at runtime, and declare it or configure it
accordingly. SLF4J provides bindings to many common logging frameworks,
so you can usually choose one that you already use, and bind to that for
configuration and management.</para>
<para>SLF4J provides bindings to many common logging frameworks,
including JCL, and it also does the reverse: bridges between other
logging frameworks and itself. So to use SLF4J with Spring you need to
replace the <code>commons-logging</code> dependency with the SLF4J-JCL
bridge. Once you have done that then logging calls from within Spring
will be translated into logging calls to the SLF4J API, so if other
libraries in your application use that API, then you have a single place
to configure and manage logging.</para>
<para>A common choice might be to bridge Spring to SLF4J, and then
provide explicit binding from SLF4J to Log4J. You need to supply 4
dependencies (and exclude the existing <code>commons-logging</code>):
the bridge, the SLF4J API, the binding to Log4J, and the Log4J
implementation itself. In Maven you would do that like this</para>
<programlisting language="xml">&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;commons-logging&lt;/groupId&gt;
&lt;artifactId&gt;commons-logging&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;jcl-over-slf4j&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.slf4j&lt;/groupId&gt;
&lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
&lt;version&gt;1.5.8&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j&lt;/artifactId&gt;
&lt;version&gt;1.2.14&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>That might seem like a lot of dependencies just to get some
logging. Well it is, but it <emphasis>is</emphasis> optional, and it
should behave better than the vanilla <code>commons-logging</code> with
respect to classloader issues, notably if you are in a strict container
like an OSGi platform. Allegedly there is also a performance benefit
because the bindings are at compile-time not runtime.</para>
<para>A more common choice amongst SLF4J users, which uses fewer steps
and generates fewer dependencies, is to bind directly to <link
xl:href="http://logback.qos.ch">Logback</link>. This removes the extra
binding step because Logback implements SLF4J directly, so you only need
to depend on two libraries not four (<code>jcl-over-slf4j</code> and
<code>logback</code>). If you do that you might also need to exclude the
slf4j-api dependency from other external dependencies (not Spring),
because you only want one version of that API on the classpath.</para>
</section>
<section xml:id="overview-logging-log4j">
<title>Using Log4J</title>
<para>Many people use <link
xl:href="http://logging.apache.org/log4j">Log4j</link> as a logging
framework for configuration and management purposes. It's efficient
and well-established, and in fact it's what we use at runtime when we
build and test Spring. Spring also provides some utilities for
configuring and initializing Log4j, so it has an optional compile-time
dependency on Log4j in some modules.</para>
<para>To make Log4j work with the default JCL dependency
(<code>commons-logging</code>) all you need to do is put Log4j on the
classpath, and provide it with a configuration file
(<code>log4j.properties</code> or <code>log4j.xml</code> in the root
of the classpath). So for Maven users this is your dependency
declaration:</para>
<programlisting language="xml">&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework&lt;/groupId&gt;
&lt;artifactId&gt;spring-context&lt;/artifactId&gt;
&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j&lt;/artifactId&gt;
&lt;version&gt;1.2.14&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt; </programlisting>
<para>And here's a sample log4j.properties for logging to the
console:</para>
<programlisting>log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
log4j.category.org.springframework.beans.factory=DEBUG</programlisting>
<section xml:id="overview-native-jcl">
<title>Runtime Containers with Native JCL</title>
<para>Many people run their Spring applications in a container that
itself provides an implementation of JCL. IBM Websphere Application
Server (WAS) is the archetype. This often causes problems, and
unfortunately there is no silver bullet solution; simply excluding
<code>commons-logging</code> from your application is not enough in
most situations.</para>
<para>To be clear about this: the problems reported are usually not
with JCL per se, or even with <code>commons-logging</code>: rather
they are to do with binding <code>commons-logging</code> to another
framework (often Log4J). This can fail because
<code>commons-logging</code> changed the way they do the runtime
discovery in between the older versions (1.0) found in some
containers and the modern versions that most people use now (1.1).
Spring does not use any unusual parts of the JCL API, so nothing
breaks there, but as soon as Spring or your application tries to do
any logging you can find that the bindings to Log4J are not
working.</para>
<para>In such cases with WAS the easiest thing to do is to invert
the class loader hierarchy (IBM calls it "parent last") so that the
application controls the JCL dependency, not the container. That
option isn't always open, but there are plenty of other suggestions
in the public domain for alternative approaches, and your mileage
may vary depending on the exact version and feature set of the
container.</para>
</section>
</section>
</section>
</section>
</chapter>

View File

@ -1,786 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="oxm"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Marshalling XML using O/X Mappers</title>
<section xml:id="oxm-introduction">
<title>Introduction</title>
<para>
In this chapter, we will describe Spring's Object/XML Mapping support. Object/XML Mapping, or O/X mapping
for short, is the act of converting an XML document to and from an object. This conversion process is also
known as XML Marshalling, or XML Serialization. This chapter uses these terms interchangeably.
</para>
<para>
Within the field of O/X mapping, a <emphasis>marshaller</emphasis> is responsible for serializing an
object (graph) to XML. In similar fashion, an <emphasis>unmarshaller</emphasis> deserializes the XML to an
object graph. This XML can take the form of a DOM document, an input or output stream, or a SAX handler.
</para>
<para>Some of the benefits of using Spring for your O/X mapping needs are:</para>
<formalpara>
<title>Ease of configuration</title>
<para>
Spring's bean factory makes it easy to configure marshallers, without needing to construct JAXB context,
JiBX binding factories, etc. The marshallers can be configured as any other bean in your application
context. Additionally, XML Schema-based configuration is available for a number of marshallers, making
the configuration even simpler.
</para>
</formalpara>
<formalpara>
<title>Consistent Interfaces</title>
<para>
Spring's O/X mapping operates through two global interfaces: the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
These abstractions allow you to switch O/X mapping
frameworks with relative ease, with little or no changes required on the classes that do the
marshalling. This approach has the additional benefit of making it possible to do XML marshalling with
a mix-and-match approach (e.g. some marshalling performed using JAXB, other using XMLBeans) in a
non-intrusive fashion, leveraging the strength of each technology.
</para>
</formalpara>
<formalpara>
<title>Consistent Exception Hierarchy</title>
<para>
Spring provides a conversion from exceptions from the underlying O/X mapping tool to its own exception
hierarchy with the <classname>XmlMappingException</classname> as the root exception. As can be expected,
these runtime exceptions wrap the original exception so no information is lost.
</para>
</formalpara>
</section>
<section xml:id="oxm-marshaller-unmarshaller">
<title>Marshaller and Unmarshaller</title>
<para>
As stated in the introduction, a <emphasis>marshaller</emphasis> serializes an object to XML, and an
<emphasis>unmarshaller</emphasis> deserializes XML stream to an object. In this section, we will describe
the two Spring interfaces used for this purpose.
</para>
<section xml:id="oxm-marshaller">
<title>Marshaller</title>
<para>
Spring abstracts all marshalling operations behind the
<interfacename>org.springframework.oxm.Marshaller</interfacename> interface, the main methods of which
is listed below.
<programlisting language="java"><![CDATA[
public interface Marshaller {
/**
* Marshals the object graph with the given root into the provided Result.
*/
void marshal(Object graph, Result result)
throws XmlMappingException, IOException;
}]]></programlisting>
The <interfacename>Marshaller</interfacename> interface has one main method, which marshals the given
object to a given <interfacename>javax.xml.transform.Result</interfacename>. Result is a tagging
interface that basically represents an XML output abstraction: concrete implementations wrap various XML
representations, as indicated in the table below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry><interfacename>Result</interfacename> implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>DOMResult</classname></entry>
<entry><interfacename>org.w3c.dom.Node</interfacename></entry>
</row>
<row>
<entry><classname>SAXResult</classname></entry>
<entry><interfacename>org.xml.sax.ContentHandler</interfacename></entry>
</row>
<row>
<entry><interfacename>StreamResult</interfacename></entry>
<entry>
<classname>java.io.File</classname>,
<classname>java.io.OutputStream</classname>, or
<classname>java.io.Writer</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<note>
<para>
Although the <methodname>marshal()</methodname> method accepts a plain object as its first
parameter, most <classname>Marshaller</classname> implementations cannot handle arbitrary
objects. Instead, an object class must be mapped in a mapping file, marked with an annotation,
registered with the marshaller, or have a common base class. Refer to the further sections
in this chapter to determine how your O/X technology of choice manages this.
</para>
</note>
</para>
</section>
<section xml:id="oxm-unmarshaller">
<title>Unmarshaller</title>
<para>
Similar to the <interfacename>Marshaller</interfacename>, there is the
<interfacename>org.springframework.oxm.Unmarshaller</interfacename> interface.
<programlisting language="java"><![CDATA[
public interface Unmarshaller {
/**
* Unmarshals the given provided Source into an object graph.
*/
Object unmarshal(Source source)
throws XmlMappingException, IOException;
}]]></programlisting>
This interface also has one method, which reads from the given
<interfacename>javax.xml.transform.Source</interfacename> (an XML input abstraction), and returns the
object read. As with Result, Source is a tagging interface that has three concrete implementations. Each
wraps a different XML representation, as indicated in the table below.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry><interfacename>Source</interfacename> implementation</entry>
<entry>Wraps XML representation</entry>
</row>
</thead>
<tbody>
<row>
<entry><classname>DOMSource</classname></entry>
<entry><interfacename>org.w3c.dom.Node</interfacename></entry>
</row>
<row>
<entry><classname>SAXSource</classname></entry>
<entry>
<classname>org.xml.sax.InputSource</classname>, and
<interfacename>org.xml.sax.XMLReader</interfacename>
</entry>
</row>
<row>
<entry><classname>StreamSource</classname></entry>
<entry>
<classname>java.io.File</classname>,
<classname>java.io.InputStream</classname>, or
<classname>java.io.Reader</classname>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Even though there are two separate marshalling interfaces (<interfacename>Marshaller</interfacename>
and <interfacename>Unmarshaller</interfacename>), all implementations found in Spring-WS implement both in
one class. This means that you can wire up one marshaller class and refer to it both as a marshaller and an
unmarshaller in your <filename>applicationContext.xml</filename>.
</para>
</section>
<section xml:id="oxm-xmlmappingexception">
<title>XmlMappingException</title>
<para>
Spring converts exceptions from the underlying O/X mapping tool to its own exception hierarchy with the
<classname>XmlMappingException</classname> as the root exception. As can be expected, these runtime
exceptions wrap the original exception so no information will be lost.
</para>
<para>
Additionally, the <classname>MarshallingFailureException</classname> and
<classname>UnmarshallingFailureException</classname> provide a distinction between marshalling and
unmarshalling operations, even though the underlying O/X mapping tool does not do so.
</para>
<para>
The O/X Mapping exception hierarchy is shown in the following figure:
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/oxm-exceptions.png"
format="PNG" width="400"/>
</imageobject>
<caption>O/X Mapping exception hierarchy</caption>
</mediaobject>
</para>
</section>
</section>
<section xml:id="oxm-usage">
<title>Using Marshaller and Unmarshaller</title>
<para>
Spring's OXM can be used for a wide variety of situations. In the following example, we will use it to
marshal the settings of a Spring-managed application as an XML file. We will use a simple JavaBean to
represent the settings:
<programlisting language="java"><![CDATA[
public class Settings {
private boolean fooEnabled;
public boolean isFooEnabled() {
return fooEnabled;
}
public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}]]></programlisting>
</para>
<para>
The application class uses this bean to store its settings. Besides a main method, the class has two
methods: <methodname>saveSettings()</methodname> saves the settings bean to a file named
<filename>settings.xml</filename>, and <methodname>loadSettings()</methodname> loads these settings again. A
<methodname>main()</methodname> method constructs a Spring application context, and calls these two methods.
<programlisting language="java"><![CDATA[
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
public class Application {
private static final String FILE_NAME = "settings.xml";
private Settings settings = new Settings();
private Marshaller marshaller;
private Unmarshaller unmarshaller;
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public void saveSettings() throws IOException {
FileOutputStream os = null;
try {
os = new FileOutputStream(FILE_NAME);
this.marshaller.marshal(settings, new StreamResult(os));
} finally {
if (os != null) {
os.close();
}
}
}
public void loadSettings() throws IOException {
FileInputStream is = null;
try {
is = new FileInputStream(FILE_NAME);
this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}
public static void main(String[] args) throws IOException {
ApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Application application = (Application) appContext.getBean("application");
application.saveSettings();
application.loadSettings();
}
}]]></programlisting>
The <classname>Application</classname> requires both a <property>marshaller</property>
and <property>unmarshaller</property> property to be set. We can do so using the following
<filename>applicationContext.xml</filename>:
<programlisting language="xml"><![CDATA[
<beans>
<bean id="application" class="Application">
<property name="marshaller" ref="castorMarshaller" />
<property name="unmarshaller" ref="castorMarshaller" />
</bean>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
</beans>
]]></programlisting>
This application context uses Castor, but we could have used any of the other marshaller instances described
later in this chapter. Note that Castor does not require any further configuration by default, so the bean
definition is rather simple. Also note that the <classname>CastorMarshaller</classname> implements both
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>, so we can refer
to the <varname>castorMarshaller</varname> bean in both the <property>marshaller</property> and
<property>unmarshaller</property> property of the application.
</para>
<para>
This sample application produces the following <filename>settings.xml</filename> file:
<programlisting language="xml"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>
]]></programlisting>
</para>
</section>
<section xml:id="oxm-schema-based-config">
<title>XML Schema-based Configuration</title>
<para>
Marshallers could be configured more concisely using tags from the OXM namespace.
To make these tags available, the appropriate schema has to be referenced first in the preamble of the XML configuration file.
Note the 'oxm' related text below:
</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
]]><emphasis role="bold"><![CDATA[xmlns:oxm="http://www.springframework.org/schema/oxm"]]></emphasis>
<![CDATA[xsi:schemaLocation="http://www.springframework.org/schema/beans
]]><![CDATA[http://www.springframework.org/schema/beans/spring-beans.xsd
]]><emphasis role="bold"><![CDATA[http://www.springframework.org/schema/oxm
]]><![CDATA[http://www.springframework.org/schema/oxm/spring-oxm.xsd"]]></emphasis><![CDATA[>
]]></programlisting>
<para>
Currently, the following tags are available:
<itemizedlist>
<listitem>
<para><link linkend="oxm-jaxb2-xsd"><literal>jaxb2-marshaller</literal></link></para>
</listitem>
<listitem>
<para><link linkend="oxm-xmlbeans-xsd"><literal>xmlbeans-marshaller</literal></link></para>
</listitem>
<listitem>
<para><link linkend="oxm-castor-xsd"><literal>castor-marshaller</literal></link></para>
</listitem>
<listitem>
<para><link linkend="oxm-jibx-xsd"><literal>jibx-marshaller</literal></link></para>
</listitem>
</itemizedlist>
</para>
<para>
Each tag will be explained in its respective marshaller's section. As an example though, here is how
the configuration of a JAXB2 marshaller might look like:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>]]></programlisting>
</section>
<section xml:id="oxm-jaxb">
<title>JAXB</title>
<para>
The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a
<filename>jaxb.properties</filename> file, and possibly some resource files. JAXB also offers a
way to generate a schema from annotated Java classes.
</para>
<para>
Spring supports the JAXB 2.0 API as XML marshalling strategies, following the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>
interfaces described in <xref linkend="oxm-marshaller-unmarshaller"/>. The corresponding integration
classes reside in the <package>org.springframework.oxm.jaxb</package> package.
</para>
<section xml:id="oxm-jaxb2">
<title>Jaxb2Marshaller</title>
<para>
The <classname>Jaxb2Marshaller</classname> class implements both the Spring
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename>interface. It
requires a context path to operate, which you can set using the <property>contextPath</property>
property. The context path is a list of colon (:) separated Java package names that contain schema
derived classes. It also offers a <property>classesToBeBound</property> property, which allows you to set an array of
classes to be supported by the marshaller. Schema validation is performed by specifying one or more
schema resource to the bean, like so:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>org.springframework.oxm.jaxb.Flight</value>
<value>org.springframework.oxm.jaxb.Flights</value>
</list>
</property>
<property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/>
</bean>
...
</beans>]]></programlisting>
<section xml:id="oxm-jaxb2-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>jaxb2-marshaller</literal> tag configures a <classname>org.springframework.oxm.jaxb.Jaxb2Marshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>]]></programlisting>
<para>
Alternatively, the list of classes to bind can be provided to the marshaller via the <literal>class-to-be-bound</literal> child tag:
</para>
<programlisting language="xml"><![CDATA[<oxm:jaxb2-marshaller id="marshaller">
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>
<oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/>
...
</oxm:jaxb2-marshaller>
]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>contextPath</literal></entry>
<entry>the JAXB Context path</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section xml:id="oxm-castor">
<title>Castor</title>
<para>
Castor XML mapping is an open source XML binding framework. It allows you to transform the data contained in
a java object model into/from an XML document. By default, it does not require any further configuration,
though a mapping file can be used to have more control over the behavior of Castor.
</para>
<para>
For more information on Castor, refer to the <link xl:href="http://castor.codehaus.org/xml-framework.html">
<citetitle>Castor web site</citetitle></link>. The Spring integration classes reside in the
<package>org.springframework.oxm.castor</package> package.
</para>
<section xml:id="oxm-castor-marshaller">
<title>CastorMarshaller</title>
<para>
As with JAXB, the <classname>CastorMarshaller</classname> implements both the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
It can be wired up as follows:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
...
</beans>]]></programlisting>
</section>
<section xml:id="oxm-castor-mapping">
<title>Mapping</title>
<para>
Although it is possible to rely on Castor's default marshalling behavior, it might be necessary to have
more control over it. This can be accomplished using a Castor mapping file. For more information, refer
to <link xl:href="http://castor.codehaus.org/xml-mapping.html">Castor XML Mapping</link>.
</para>
<para>
The mapping can be set using the <property>mappingLocation</property> resource property, indicated
below with a classpath resource.
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
<property name="mappingLocation" value="classpath:mapping.xml" />
</bean>
</beans>
]]></programlisting>
<section xml:id="oxm-castor-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>castor-marshaller</literal> tag configures a
<classname>org.springframework.oxm.castor.CastorMarshaller</classname>.
Here is an example:
</para>
<programlisting language="xml">
<![CDATA[<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>]]></programlisting>
<para>
The marshaller instance can be configured in two ways, by specifying either the location of
a mapping file (through the <property>mapping-location</property> property), or by
identifying Java POJOs (through the <property>target-class</property> or
<property>target-package</property> properties) for which there exist corresponding
XML descriptor classes. The latter way is usually used in conjunction with XML code generation
from XML schemas.
</para>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>id</literal>
</entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry>
<literal>encoding</literal>
</entry>
<entry>the encoding to use for unmarshalling from XML</entry>
<entry>no</entry>
</row>
<row>
<entry>
<literal>target-class</literal>
</entry>
<entry>a Java class name for a POJO for which an XML class descriptor is available (as
generated through code generation)
</entry>
<entry>no</entry>
</row>
<row>
<entry>
<literal>target-package</literal>
</entry>
<entry>a Java package name that identifies a package that contains POJOs and their
corresponding Castor
XML descriptor classes (as generated through code generation from XML schemas)
</entry>
<entry>no</entry>
</row>
<row>
<entry>
<literal>mapping-location</literal>
</entry>
<entry>location of a Castor XML mapping file</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section xml:id="oxm-xmlbeans">
<title>XMLBeans</title>
<para>
XMLBeans is an XML binding tool that has full XML Schema support, and offers full XML Infoset
fidelity. It takes a different approach to that of most other O/X mapping frameworks, in that
all classes that are generated from an XML Schema are all derived from
<interfacename>XmlObject</interfacename>, and contain XML binding information in them.
</para>
<para>
For more information on XMLBeans, refer to the <link xl:href="http://xmlbeans.apache.org/">
<citetitle>XMLBeans web site </citetitle></link>. The Spring-WS integration classes reside
in the <package>org.springframework.oxm.xmlbeans</package> package.
</para>
<section xml:id="oxm-xmlbeans-marshaller">
<title>XmlBeansMarshaller</title>
<para>
The <classname>XmlBeansMarshaller</classname>
implements both the <interfacename>Marshaller</interfacename>
and <interfacename>Unmarshaller</interfacename>
interfaces. It can be configured as follows:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
...
</beans>]]></programlisting>
<note>
<para>
Note that the <classname>XmlBeansMarshaller</classname>
can only marshal objects of type <interfacename>XmlObject</interfacename>,
and not every <classname>java.lang.Object</classname>.
</para>
</note>
<section xml:id="oxm-xmlbeans-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>xmlbeans-marshaller</literal> tag configures a <classname>org.springframework.oxm.xmlbeans.XmlBeansMarshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:xmlbeans-marshaller id="marshaller"/>]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>options</literal></entry>
<entry>the bean name of the XmlOptions that is to be used for this marshaller. Typically a
<classname>XmlOptionsFactoryBean</classname> definition</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section xml:id="oxm-jibx">
<title>JiBX</title>
<para>
The JiBX framework offers a solution similar to that which JDO provides for ORM: a binding definition defines the
rules for how your Java objects are converted to or from XML. After preparing the binding and compiling the
classes, a JiBX binding compiler enhances the class files, and adds code to handle converting instances of
the classes from or to XML.
</para>
<para>
For more information on JiBX, refer to the <link xl:href="http://jibx.sourceforge.net/">
<citetitle>JiBX web site</citetitle></link>. The Spring integration classes reside in the
<package>org.springframework.oxm.jibx</package> package.
</para>
<section xml:id="oxm-jibx-marshaller">
<title>JibxMarshaller</title>
<para>
The <classname>JibxMarshaller</classname> class implements both the
<interfacename>Marshaller</interfacename> and <interfacename>Unmarshaller</interfacename> interface.
To operate, it requires the name of the class to marshal in, which you can set using the
<property>targetClass</property> property. Optionally, you can set the binding name using the
<property>bindingName</property> property. In the next sample, we bind the
<classname>Flights</classname> class:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
<property name="targetClass">org.springframework.oxm.jibx.Flights</property>
</bean>
...
]]></programlisting>
<para>
A <classname>JibxMarshaller</classname> is configured for a single class. If you want to marshal
multiple classes, you have to configure multiple <classname>JibxMarshaller</classname>s with
different <property>targetClass</property> property values.
</para>
<section xml:id="oxm-jibx-xsd">
<title>XML Schema-based Configuration</title>
<para>
The <literal>jibx-marshaller</literal> tag configures a <classname>org.springframework.oxm.jibx.JibxMarshaller</classname>.
Here is an example:
</para>
<programlisting language="xml"><![CDATA[<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>]]></programlisting>
<para>
Available attributes are:
<informaltable>
<tgroup cols="3">
<colspec colwidth="1.5*"/>
<colspec colwidth="4*"/>
<colspec colwidth="1*"/>
<thead>
<row>
<entry>Attribute</entry>
<entry>Description</entry>
<entry>Required</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>id</literal></entry>
<entry>the id of the marshaller</entry>
<entry>no</entry>
</row>
<row>
<entry><literal>target-class</literal></entry>
<entry>the target class for this marshaller</entry>
<entry>yes</entry>
</row>
<row>
<entry><literal>bindingName</literal></entry>
<entry>the binding name used by this marshaller</entry>
<entry>no</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</section>
</section>
</section>
<section xml:id="oxm-xstream">
<title>XStream</title>
<para>
XStream is a simple library to serialize objects to XML and back again. It does not require any mapping, and
generates clean XML.
</para>
<para>
For more information on XStream, refer to the <link xl:href="http://xstream.codehaus.org/">
<citetitle>XStream web site</citetitle></link>. The Spring integration classes reside in the
<package>org.springframework.oxm.xstream</package> package.
</para>
<section xml:id="oxm-xstream-marshaller">
<title>XStreamMarshaller</title>
<para>
The <classname>XStreamMarshaller</classname> does not require any configuration, and can be configured
in an application context directly. To further customize the XML, you can set an
<emphasis>alias map</emphasis>, which consists of string aliases mapped to classes:
</para>
<programlisting language="xml"><![CDATA[
<beans>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<props>
<prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
</props>
</property>
</bean>
...
</beans>]]></programlisting>
<warning>
<para>
By default, XStream allows for arbitrary classes to be unmarshalled, which can result in security
vulnerabilities.
As such, it is <emphasis>not recommended to use the <classname>XStreamMarshaller</classname> to
unmarshal XML from external sources</emphasis> (i.e. the Web), as this can result in
<emphasis>security vulnerabilities</emphasis>.
If you do use the <classname>XStreamMarshaller</classname> to unmarshal XML from an external source,
set the <property>supportedClasses</property> property on the
<classname>XStreamMarshaller</classname>, like so:
<programlisting language="xml"><![CDATA[<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/>
...
</bean>]]></programlisting>
This will make sure that only the registered classes are eligible for unmarshalling.
</para>
<para>
Additionally, you can register <link xl:href="http://static.springsource.org/spring/docs/current/api/org/springframework/oxm/xstream/XStreamMarshaller.html#setConverters(com.thoughtworks.xstream.converters.ConverterMatcher[])">
custom converters</link> to make sure that only your supported classes can be unmarshalled.
You might want to add a <classname>CatchAllConverter</classname> as the last converter in the list,
in addition to converters that explicitly support the domain classes that should be supported.
As a result, default XStream converters with lower priorities and possible security vulnerabilities do not get invoked.
</para>
</warning>
<note>
<para>
Note that XStream is an XML serialization library, not a data binding library. Therefore, it has
limited namespace support. As such, it is rather unsuitable for usage within Web services.
</para>
</note>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<preface xml:id="preface"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Preface</title>
<para>Developing software applications is hard enough even with good tools
and technologies. Implementing applications using platforms which promise
everything but turn out to be heavy-weight, hard to control and not very
efficient during the development cycle makes it even harder. Spring provides
a light-weight solution for building enterprise-ready applications, while
still supporting the possibility of using declarative transaction
management, remote access to your logic using RMI or web services, and
various options for persisting your data to a database. Spring provides a
full-featured <link linkend="mvc-introduction">MVC framework</link>, and
transparent ways of integrating <link linkend="aop-introduction">AOP</link>
into your software.</para>
<para>Spring could potentially be a one-stop-shop for all your enterprise
applications; however, Spring is modular, allowing you to use just those
parts of it that you need, without having to bring in the rest. You can use
the IoC container, with Struts on top, but you could also choose to use just
the <link linkend="orm-hibernate">Hibernate integration code</link> or the
<link linkend="jdbc-introduction">JDBC abstraction layer</link></para>
<para>Spring has been (and continues to be) designed to be non-intrusive,
meaning dependencies, from your domain logic code, on the framework itself
are generally none. For your integration layer like the data access layer
there will of course be some dependencies on the data access technology in
use and also on the Spring libraries, but these dependencies should be easy
to isolate from the rest of your code base.</para>
<para>This document provides a reference guide to Spring's features. If you
have any requests or comments, please add an issue at
<link xl:href="http://jira.springsource.org/SPR" />.
</para>
</preface>

File diff suppressed because it is too large Load Diff

View File

@ -1,746 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="resources"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Resources</title>
<section xml:id="resources-introduction">
<title>Introduction</title>
<para>Java's standard <classname>java.net.URL</classname> class and
standard handlers for various URL prefixes unfortunately are not quite
adequate enough for all access to low-level resources. For example,
there is no standardized <classname>URL</classname> implementation
that may be used to access a resource that needs to be obtained from
the classpath, or relative to a
<interfacename>ServletContext</interfacename>. While it is possible
to register new handlers for specialized <classname>URL</classname>
prefixes (similar to existing handlers for prefixes such as
<literal>http:</literal>), this is generally quite complicated, and the
<classname>URL</classname> interface still lacks some desirable
functionality, such as a method to check for the existence of the
resource being pointed to.</para>
</section>
<section xml:id="resources-resource">
<title>The <interfacename>Resource</interfacename> interface</title>
<para>Spring's <interfacename>Resource</interfacename> interface is meant
to be a more capable interface for abstracting access to low-level
resources.</para>
<programlisting language="java"><![CDATA[public interface Resource extends InputStreamSource {
boolean exists();
boolean isOpen();
URL getURL() throws IOException;
File getFile() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}]]></programlisting>
<programlisting language="java"><![CDATA[public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}]]></programlisting>
<para>Some of the most important methods from the
<interfacename>Resource</interfacename> interface are:</para>
<itemizedlist>
<listitem>
<para><methodname>getInputStream()</methodname>: locates and opens the
resource, returning an <classname>InputStream</classname> for reading
from the resource. It is expected that each invocation returns a
fresh <classname>InputStream</classname>. It is the responsibility of
the caller to close the stream.</para>
</listitem>
<listitem>
<para><methodname>exists()</methodname>: returns a
<literal>boolean</literal> indicating whether this resource actually
exists in physical form.</para>
</listitem>
<listitem>
<para><methodname>isOpen()</methodname>: returns a
<literal>boolean</literal> indicating whether this resource represents
a handle with an open stream. If <literal>true</literal>, the
<classname>InputStream</classname> cannot be read multiple times, and
must be read once only and then closed to avoid resource leaks. Will
be <literal>false</literal> for all usual resource implementations,
with the exception of
<classname>InputStreamResource</classname>.</para>
</listitem>
<listitem>
<para><methodname>getDescription()</methodname>: returns a description
for this resource, to be used for error output when working with the
resource. This is often the fully qualified file name or the actual
URL of the resource.</para>
</listitem>
</itemizedlist>
<para>Other methods allow you to obtain an actual
<classname>URL</classname> or <classname>File</classname> object
representing the resource (if the underlying implementation is compatible,
and supports that functionality).</para>
<para>The <interfacename>Resource</interfacename> abstraction is used
extensively in Spring itself, as an argument type in many method
signatures when a resource is needed. Other methods in some Spring APIs
(such as the constructors to various
<interfacename>ApplicationContext</interfacename> implementations), take a
<classname>String</classname> which in unadorned or simple form is used to
create a <interfacename>Resource</interfacename> appropriate to that
context implementation, or via special prefixes on the
<classname>String</classname> path, allow the caller to specify that a
specific <interfacename>Resource</interfacename> implementation must be
created and used.</para>
<para>While the <interfacename>Resource</interfacename> interface is used
a lot with Spring and by Spring, it's actually very useful to use as a
general utility class by itself in your own code, for access to resources,
even when your code doesn't know or care about any other parts of Spring.
While this couples your code to Spring, it really only couples it to this
small set of utility classes, which are serving as a more capable
replacement for <classname>URL</classname>, and can be considered
equivalent to any other library you would use for this purpose.</para>
<para>It is important to note that the
<interfacename>Resource</interfacename> abstraction does not replace
functionality: it wraps it where possible. For example, a
<classname>UrlResource</classname> wraps a URL, and uses the wrapped
<classname>URL</classname> to do its work.</para>
</section>
<section xml:id="resources-implementations">
<title>Built-in <interfacename>Resource</interfacename> implementations</title>
<para>There are a number of <interfacename>Resource</interfacename>
implementations that come supplied straight out of the box in
Spring:</para>
<section xml:id="resources-implementations-urlresource">
<title><classname>UrlResource</classname></title>
<para>The <classname>UrlResource</classname> wraps a
<classname>java.net.URL</classname>, and may be used to access any
object that is normally accessible via a URL, such as files, an HTTP
target, an FTP target, etc. All URLs have a standardized
<classname>String</classname> representation, such that appropriate
standardized prefixes are used to indicate one URL type from another.
This includes <literal>file:</literal> for accessing filesystem paths,
<literal>http:</literal> for accessing resources via the HTTP protocol,
<literal>ftp:</literal> for accessing resources via FTP, etc.</para>
<para>A <classname>UrlResource</classname> is created by Java code
explicitly using the <classname>UrlResource</classname> constructor, but
will often be created implicitly when you call an API method which takes
a <classname>String</classname> argument which is meant to represent a
path. For the latter case, a JavaBeans
<interfacename>PropertyEditor</interfacename> will ultimately decide
which type of <interfacename>Resource</interfacename> to create. If the
path string contains a few well-known (to it, that is) prefixes such as
<literal>classpath:</literal>, it will create an appropriate specialized
<interfacename>Resource</interfacename> for that prefix. However, if it
doesn't recognize the prefix, it will assume the this is just a standard
URL string, and will create a <classname>UrlResource</classname>.</para>
</section>
<section xml:id="resources-implementations-classpathresource">
<title><classname>ClassPathResource</classname></title>
<para>This class represents a resource which should be obtained from the
classpath. This uses either the thread context class loader, a given
class loader, or a given class for loading resources.</para>
<para>This <interfacename>Resource</interfacename> implementation
supports resolution as <classname>java.io.File</classname> if the class
path resource resides in the file system, but not for classpath
resources which reside in a jar and have not been expanded (by the
servlet engine, or whatever the environment is) to the filesystem. To
address this the various <interfacename>Resource</interfacename>
implementations always support resolution as a
<classname>java.net.URL</classname>.</para>
<para>A <classname>ClassPathResource</classname> is created by Java code
explicitly using the <classname>ClassPathResource</classname>
constructor, but will often be created implicitly when you call an API
method which takes a <classname>String</classname> argument which is
meant to represent a path. For the latter case, a JavaBeans
<interfacename>PropertyEditor</interfacename> will recognize the special
prefix <literal>classpath:</literal>on the string path, and create a
<classname>ClassPathResource</classname> in that case.</para>
</section>
<section xml:id="resources-implementations-filesystemresource">
<title><classname>FileSystemResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for <classname>java.io.File</classname> handles. It obviously supports
resolution as a <classname>File</classname>, and as a
<classname>URL</classname>.</para>
</section>
<section xml:id="resources-implementations-servletcontextresource">
<title><classname>ServletContextResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for <interfacename>ServletContext</interfacename> resources,
interpreting relative paths within the relevant web application's root
directory.</para>
<para>This always supports stream access and URL access, but only allows
<classname>java.io.File</classname> access when the web application
archive is expanded and the resource is physically on the filesystem.
Whether or not it's expanded and on the filesystem like this, or
accessed directly from the JAR or somewhere else like a DB (it's
conceivable) is actually dependent on the Servlet container.</para>
</section>
<section xml:id="resources-implementations-inputstreamresource">
<title><classname>InputStreamResource</classname></title>
<para>A <interfacename>Resource</interfacename> implementation for a
given <interfacename>InputStream</interfacename>. This should only be
used if no specific <interfacename>Resource</interfacename>
implementation is applicable. In particular, prefer
<classname>ByteArrayResource</classname> or any of the file-based
<interfacename>Resource</interfacename> implementations where
possible.</para>
<para>In contrast to other <interfacename>Resource</interfacename>
implementations, this is a descriptor for an
<emphasis>already</emphasis> opened resource - therefore returning
<literal>true</literal> from <methodname>isOpen()</methodname>. Do not
use it if you need to keep the resource descriptor somewhere, or if you
need to read a stream multiple times.</para>
</section>
<section xml:id="resources-implementations-bytearrayresource">
<title><classname>ByteArrayResource</classname></title>
<para>This is a <interfacename>Resource</interfacename> implementation
for a given byte array. It creates a
<classname>ByteArrayInputStream</classname> for the given byte
array.</para>
<para>It's useful for loading content from any given byte array, without
having to resort to a single-use
<classname>InputStreamResource</classname>.</para>
</section>
</section>
<section xml:id="resources-resourceloader">
<title>The <interfacename>ResourceLoader</interfacename></title>
<para>The <interfacename>ResourceLoader</interfacename> interface is meant
to be implemented by objects that can return (i.e. load)
<interfacename>Resource</interfacename> instances.</para>
<programlisting language="java">public interface ResourceLoader {
Resource getResource(String location);
}</programlisting>
<para>All application contexts implement the
<interfacename>ResourceLoader</interfacename> interface, and therefore all
application contexts may be used to obtain
<interfacename>Resource</interfacename> instances.</para>
<para>When you call <methodname>getResource()</methodname> on a specific
application context, and the location path specified doesn't have a
specific prefix, you will get back a
<interfacename>Resource</interfacename> type that is appropriate to that
particular application context. For example, assume the following snippet
of code was executed against a
<classname>ClassPathXmlApplicationContext</classname> instance:</para>
<programlisting language="java">Resource template = ctx.getResource("some/resource/path/myTemplate.txt");</programlisting>
<para>What would be returned would be a
<classname>ClassPathResource</classname>; if the same method was executed
against a <classname>FileSystemXmlApplicationContext</classname> instance,
you'd get back a <classname>FileSystemResource</classname>. For a
<classname>WebApplicationContext</classname>, you'd get back a
<classname>ServletContextResource</classname>, and so on.</para>
<para>As such, you can load resources in a fashion appropriate to the
particular application context.</para>
<para>On the other hand, you may also force
<classname>ClassPathResource</classname> to be used, regardless of the
application context type, by specifying the special
<literal>classpath:</literal> prefix:</para>
<programlisting language="java">Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");</programlisting>
<para>Similarly, one can force a <classname>UrlResource</classname> to be
used by specifying any of the standard <classname>java.net.URL</classname>
prefixes:</para>
<programlisting language="java">Resource template = ctx.getResource("file:/some/resource/path/myTemplate.txt");</programlisting>
<programlisting language="java">Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");</programlisting>
<para>The following table summarizes the strategy for converting
<classname>String</classname>s to
<interfacename>Resource</interfacename>s:</para>
<table pgwide="1" xml:id="resources-resource-strings">
<title>Resource strings</title>
<tgroup cols="3">
<colspec align="left" />
<thead>
<row>
<entry align="center">Prefix</entry>
<entry align="center">Example</entry>
<entry align="center">Explanation</entry>
</row>
</thead>
<tbody>
<row>
<entry><para>classpath:</para></entry>
<entry><para> <literal>classpath:com/myapp/config.xml</literal>
</para></entry>
<entry><para>Loaded from the classpath.</para></entry>
</row>
<row>
<entry><para>file:</para></entry>
<entry><para> <literal>file:/data/config.xml</literal>
</para></entry>
<entry><para> Loaded as a <classname>URL</classname>, from the
filesystem. <footnote>
<para>But see also
<xref linkend="resources-filesystemresource-caveats" />.</para>
</footnote> </para></entry>
</row>
<row>
<entry><para>http:</para></entry>
<entry><para> <literal>http://myserver/logo.png</literal>
</para></entry>
<entry><para>Loaded as a
<classname>URL</classname>.</para></entry>
</row>
<row>
<entry><para>(none)</para></entry>
<entry><para> <literal>/data/config.xml</literal> </para></entry>
<entry><para> Depends on the underlying
<interfacename>ApplicationContext</interfacename>. </para></entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="resources-resourceloaderaware">
<title>The <interfacename>ResourceLoaderAware</interfacename> interface</title>
<para>The <interfacename>ResourceLoaderAware</interfacename> interface is
a special marker interface, identifying objects that expect to be provided
with a <interfacename>ResourceLoader</interfacename> reference.</para>
<programlisting language="java"><![CDATA[public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}]]></programlisting>
<para>When a class implements
<interfacename>ResourceLoaderAware</interfacename> and is deployed into an
application context (as a Spring-managed bean), it is recognized as
<interfacename>ResourceLoaderAware</interfacename> by the application
context. The application context will then invoke the
<methodname>setResourceLoader(ResourceLoader)</methodname>, supplying
itself as the argument (remember, all application contexts in Spring
implement the <interfacename>ResourceLoader</interfacename>
interface).</para>
<para>Of course, since an
<interfacename>ApplicationContext</interfacename> is a
<interfacename>ResourceLoader</interfacename>, the bean could also
implement the <interfacename>ApplicationContextAware</interfacename>
interface and use the supplied application context directly to load
resources, but in general, it's better to use the specialized
<interfacename>ResourceLoader</interfacename> interface if that's all
that's needed. The code would just be coupled to the resource loading
interface, which can be considered a utility interface, and not the whole
Spring <interfacename>ApplicationContext</interfacename> interface.</para>
<para>As of Spring 2.5, you can rely upon autowiring of the
<interfacename>ResourceLoader</interfacename> as an alternative to
implementing the <interfacename>ResourceLoaderAware</interfacename> interface.
The "traditional" <literal>constructor</literal> and <literal>byType</literal>
autowiring modes (as described in <xref linkend="beans-factory-autowire"/>)
are now capable of providing a dependency of type
<interfacename>ResourceLoader</interfacename> for either a
constructor argument or setter method parameter respectively. For more flexibility
(including the ability to autowire fields and multiple parameter methods), consider
using the new annotation-based autowiring features. In that case, the
<interfacename>ResourceLoader</interfacename> will be autowired into a field,
constructor argument, or method parameter that is expecting the
<interfacename>ResourceLoader</interfacename> type as long as the field,
constructor, or method in question carries the
<interfacename>@Autowired</interfacename> annotation. For more information,
see <xref linkend="beans-autowired-annotation"/>.</para>
</section>
<section xml:id="resources-as-dependencies">
<title><literal>Resources</literal> as dependencies</title>
<para>If the bean itself is going to determine and supply the resource
path through some sort of dynamic process, it probably makes sense for the
bean to use the <interfacename>ResourceLoader</interfacename> interface to
load resources. Consider as an example the loading of a template of some
sort, where the specific resource that is needed depends on the role of
the user. If the resources are static, it makes sense to eliminate the use
of the <interfacename>ResourceLoader</interfacename> interface completely,
and just have the bean expose the <interfacename>Resource</interfacename>
properties it needs, and expect that they will be injected into it.</para>
<para>What makes it trivial to then inject these properties, is that all
application contexts register and use a special JavaBeans
<interfacename>PropertyEditor</interfacename> which can convert
<classname>String</classname> paths to
<interfacename>Resource</interfacename> objects. So if
<literal>myBean</literal> has a template property of type
<interfacename>Resource</interfacename>, it can be configured with a
simple string for that resource, as follows:</para>
<programlisting language="xml"><![CDATA[<bean id="myBean" class="...">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>]]></programlisting>
<para>Note that the resource path has no prefix, so because the
application context itself is going to be used as the
<interfacename>ResourceLoader</interfacename>, the resource itself will be
loaded via a <classname>ClassPathResource</classname>,
<literal>FileSystemResource</literal>, or
<classname>ServletContextResource</classname> (as appropriate)
depending on the exact type of the context.</para>
<para>If there is a need to force a specific
<interfacename>Resource</interfacename> type to be used, then a prefix may
be used. The following two examples show how to force a
<classname>ClassPathResource</classname> and a
<classname>UrlResource</classname> (the latter being used to access a
filesystem file).</para>
<programlisting language="xml"><![CDATA[<property name="template" value="classpath:some/resource/path/myTemplate.txt">]]></programlisting>
<programlisting language="xml"><![CDATA[<property name="template" value="file:/some/resource/path/myTemplate.txt"/>]]></programlisting>
</section>
<section xml:id="resources-app-ctx">
<title>Application contexts and <interfacename>Resource</interfacename> paths</title>
<section xml:id="resources-app-ctx-construction">
<title>Constructing application contexts</title>
<para>An application context constructor (for a specific application
context type) generally takes a string or array of strings as the
location path(s) of the resource(s) such as XML files that make up the
definition of the context.</para>
<para>When such a location path doesn't have a prefix, the specific
<interfacename>Resource</interfacename> type built from that path and
used to load the bean definitions, depends on and is appropriate to the
specific application context. For example, if you create a
<classname>ClassPathXmlApplicationContext</classname> as follows:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");]]></programlisting>
<para>The bean definitions will be loaded from the classpath, as a
<classname></classname><classname>ClassPathResource</classname> will be
used. But if you create a
<classname>FileSystemXmlApplicationContext</classname> as
follows:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");]]></programlisting>
<para>The bean definition will be loaded from a filesystem location, in
this case relative to the current working directory.</para>
<para>Note that the use of the special classpath prefix or a standard
URL prefix on the location path will override the default type of
<interfacename>Resource</interfacename> created to load the definition.
So this <classname>FileSystemXmlApplicationContext</classname>...</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");]]></programlisting>
<para>... will actually load its bean definitions from the classpath.
However, it is still a <classname>FileSystemXmlApplicationContext</classname>. If it is
subsequently used as a <interfacename>ResourceLoader</interfacename>,
any unprefixed paths will still be treated as filesystem paths.</para>
<section xml:id="resources-app-ctx-classpathxml">
<title>Constructing <classname>ClassPathXmlApplicationContext</classname> instances - shortcuts</title>
<para>The <classname>ClassPathXmlApplicationContext</classname>
exposes a number of constructors to enable convenient instantiation.
The basic idea is that one supplies merely a string array containing
just the filenames of the XML files themselves (without the leading
path information), and one <emphasis>also</emphasis> supplies a
<classname>Class</classname>; the
<classname>ClassPathXmlApplicationContext</classname> will derive the
path information from the supplied class.</para>
<para>An example will hopefully make this clear. Consider a directory
layout that looks like this:</para>
<programlisting><![CDATA[com/
foo/
services.xml
daos.xml
MessengerService.class]]></programlisting>
<para>A <classname>ClassPathXmlApplicationContext</classname> instance
composed of the beans defined in the <literal>'services.xml'</literal>
and <literal>'daos.xml'</literal> could be instantiated like
so...</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class);]]></programlisting>
<para>Please do consult the Javadocs for the
<classname>ClassPathXmlApplicationContext</classname> class for
details of the various constructors.</para>
</section>
</section>
<section xml:id="resources-app-ctx-wildcards-in-resource-paths">
<title>Wildcards in application context constructor resource paths</title>
<para>The resource paths in application context constructor values may
be a simple path (as shown above) which has a one-to-one mapping to a
target Resource, or alternately may contain the special "classpath*:"
prefix and/or internal Ant-style regular expressions (matched using
Spring's <classname>PathMatcher</classname> utility). Both of the latter
are effectively wildcards</para>
<para>One use for this mechanism is when doing component-style
application assembly. All components can 'publish' context definition
fragments to a well-known location path, and when the final application
context is created using the same path prefixed via
<literal>classpath*:</literal>, all component fragments will be picked
up automatically.</para>
<para>Note that this wildcarding is specific to use of resource paths in
application context constructors (or when using the
<classname>PathMatcher</classname> utility class hierarchy directly),
and is resolved at construction time. It has nothing to do with the
<interfacename>Resource</interfacename> type itself. It's not possible
to use the <literal>classpath*:</literal> prefix to construct an actual
<interfacename>Resource</interfacename>, as a resource points to just
one resource at a time.</para>
<section xml:id="resources-app-ctx-ant-patterns-in-paths">
<title>Ant-style Patterns</title>
<para>When the path location contains an Ant-style pattern, for example:</para>
<programlisting><![CDATA[ /WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml]]></programlisting>
<para>... the resolver follows a more complex but defined procedure to
try to resolve the wildcard. It produces a Resource for the path up to
the last non-wildcard segment and obtains a URL from it. If this URL
is not a "jar:" URL or container-specific variant (e.g.
"<literal>zip:</literal>" in WebLogic, "<literal>wsjar</literal>" in
WebSphere, etc.), then a <classname>java.io.File</classname> is
obtained from it and used to resolve the wildcard by traversing the
filesystem. In the case of a jar URL, the resolver either gets a
<classname>java.net.JarURLConnection</classname> from it or manually
parses the jar URL and then traverses the contents of the jar file
to resolve the wildcards.</para>
<section xml:id="resources-app-ctx-portability">
<title>Implications on portability</title>
<para>If the specified path is already a file URL (either
explicitly, or implicitly because the base
<interfacename>ResourceLoader</interfacename> is a
filesystem one, then wildcarding is guaranteed to work in a
completely portable fashion.</para>
<para>If the specified path is a classpath location, then the
resolver must obtain the last non-wildcard path segment URL via a
<methodname>Classloader.getResource()</methodname> call. Since this
is just a node of the path (not the file at the end) it is actually
undefined (in the <classname>ClassLoader</classname> Javadocs)
exactly what sort of a URL is returned in this case. In practice, it
is always a <classname>java.io.File</classname> representing the
directory, where the classpath resource resolves to a filesystem
location, or a jar URL of some sort, where the classpath resource
resolves to a jar location. Still, there is a portability concern on
this operation.</para>
<para>If a jar URL is obtained for the last non-wildcard segment,
the resolver must be able to get a
<classname>java.net.JarURLConnection</classname> from it, or
manually parse the jar URL, to be able to walk the contents of the
jar, and resolve the wildcard. This will work in most environments,
but will fail in others, and it is strongly recommended that the
wildcard resolution of resources coming from jars be thoroughly
tested in your specific environment before you rely on it.</para>
</section>
</section>
<section xml:id="resources-classpath-wildcards">
<title>The <literal>classpath*:</literal> prefix</title>
<para>When constructing an XML-based application context, a location
string may use the special <literal>classpath*:</literal>
prefix:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");]]></programlisting>
<para>This special prefix specifies that all classpath resources that
match the given name must be obtained (internally, this essentially
happens via a <methodname>ClassLoader.getResources(...)</methodname>
call), and then merged to form the final application context
definition.</para>
<note>
<title>Classpath*: portability</title>
<para>The wildcard classpath relies on the <literal>getResources()</literal> method of the
underlying classloader. As most application servers nowadays supply
their own classloader implementation, the behavior might differ
especially when dealing with jar files. A simple test to check if
<literal>classpath*</literal> works is to use the classloader to load a file from
within a jar on the classpath:
<literal>getClass().getClassLoader().getResources("&lt;someFileInsideTheJar&gt;")</literal>.
Try this test with files that have the same name but are placed
inside two different locations. In case an inappropriate result is
returned, check the application server documentation for settings
that might affect the classloader behavior.</para>
</note>
<para>The "<literal>classpath*:</literal>" prefix can also be combined
with a <literal>PathMatcher</literal> pattern in the rest of the location path, for
example "<literal>classpath*:META-INF/*-beans.xml</literal>". In this
case, the resolution strategy is fairly simple: a
ClassLoader.getResources() call is used on the last non-wildcard path
segment to get all the matching resources in the class loader
hierarchy, and then off each resource the same PathMatcher resolution
strategy described above is used for the wildcard subpath.</para>
</section>
<section xml:id="resources-wildcards-in-path-other-stuff">
<title>Other notes relating to wildcards</title>
<para>Please note that "<literal>classpath*:</literal>" when
combined with Ant-style patterns will only work reliably with at least
one root directory before the pattern starts, unless the actual target
files reside in the file system. This means that a pattern like
"<literal>classpath*:*.xml</literal>" will not retrieve files from the
root of jar files but rather only from the root of expanded
directories. This originates from a limitation in the JDK's
<methodname>ClassLoader.getResources()</methodname> method which only
returns file system locations for a passed-in empty string (indicating
potential roots to search).</para>
<para>Ant-style patterns with "<literal>classpath:</literal>"
resources are not guaranteed to find matching resources if the root
package to search is available in multiple class path locations. This
is because a resource such as</para>
<programlisting><![CDATA[ com/mycompany/package1/service-context.xml]]></programlisting>
<para>may be in only one location, but when a path such as</para>
<programlisting><![CDATA[ classpath:com/mycompany/**/service-context.xml]]></programlisting>
<para>is used to try to resolve it, the resolver will work off the (first) URL
returned by <methodname>getResource("com/mycompany")</methodname>;. If
this base package node exists in multiple classloader locations, the
actual end resource may not be underneath. Therefore, preferably, use
"<literal>classpath*:</literal>" with the same Ant-style pattern in
such a case, which will search all class path locations that contain
the root package.</para>
</section>
</section>
<section xml:id="resources-filesystemresource-caveats">
<title><classname>FileSystemResource</classname> caveats</title>
<para>A <classname>FileSystemResource</classname> that is not attached
to a <classname>FileSystemApplicationContext</classname> (that is, a
<classname>FileSystemApplicationContext</classname> is not the actual
<interfacename>ResourceLoader</interfacename>) will treat absolute vs.
relative paths as you would expect. Relative paths are relative to the
current working directory, while absolute paths are relative to the root
of the filesystem.</para>
<para>For backwards compatibility (historical) reasons however, this
changes when the <classname>FileSystemApplicationContext</classname> is
the <literal>ResourceLoader</literal>. The
<classname>FileSystemApplicationContext</classname> simply forces all
attached <classname>FileSystemResource</classname> instances to treat
all location paths as relative, whether they start with a leading slash
or not. In practice, this means the following are equivalent:</para>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/context.xml");]]></programlisting>
<programlisting language="java"><![CDATA[ApplicationContext ctx =
new FileSystemXmlApplicationContext("/conf/context.xml");]]></programlisting>
<para>As are the following: (Even though it would make sense for them to
be different, as one case is relative and the other absolute.)</para>
<programlisting language="java"><![CDATA[FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");]]></programlisting>
<programlisting language="java"><![CDATA[FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");]]></programlisting>
<para>In practice, if true absolute filesystem paths are needed, it is
better to forgo the use of absolute paths with
<classname>FileSystemResource</classname> /
<classname>FileSystemXmlApplicationContext</classname>, and just force
the use of a <classname>UrlResource</classname>, by using the
<literal>file:</literal> URL prefix.</para>
<programlisting language="java"><lineannotation>// actual context type doesn't matter, the Resource will always be UrlResource</lineannotation><![CDATA[
ctx.getResource("file:/some/resource/path/myTemplate.txt");]]></programlisting>
<programlisting language="java"><lineannotation>// force this FileSystemXmlApplicationContext to load its definition via a UrlResource</lineannotation><![CDATA[
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:/conf/context.xml");]]></programlisting>
</section>
</section>
</chapter>

View File

@ -1,891 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xml:id="scheduling"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Task Execution and Scheduling</title>
<section xml:id="scheduling-introduction">
<title>Introduction</title>
<para>The Spring Framework provides abstractions for asynchronous
execution and scheduling of tasks with the
<interfacename>TaskExecutor</interfacename> and
<interfacename>TaskScheduler</interfacename> interfaces, respectively.
Spring also features implementations of those interfaces that support
thread pools or delegation to CommonJ within an application server
environment. Ultimately the use of these implementations behind the common
interfaces abstracts away the differences between Java SE 5, Java SE 6 and
Java EE environments.</para>
<para>Spring also features integration classes for supporting scheduling
with the <classname>Timer</classname>, part of the JDK since 1.3, and the
Quartz Scheduler (<link
xl:href="http://quartz-scheduler.org"></link>). Both of those
schedulers are set up using a <interfacename>FactoryBean</interfacename>
with optional references to <classname>Timer</classname> or
<classname>Trigger</classname> instances, respectively. Furthermore, a
convenience class for both the Quartz Scheduler and the
<classname>Timer</classname> is available that allows you to invoke a
method of an existing target object (analogous to the normal
<classname>MethodInvokingFactoryBean</classname> operation).</para>
</section>
<section xml:id="scheduling-task-executor">
<title>The Spring <interfacename>TaskExecutor</interfacename>
abstraction</title>
<para>Spring 2.0 introduces a new abstraction for dealing with executors.
Executors are the Java 5 name for the concept of thread pools. The
"executor" naming is due to the fact that there is no guarantee that the
underlying implementation is actually a pool; an executor may be
single-threaded or even synchronous. Spring's abstraction hides
implementation details between Java SE 1.4, Java SE 5 and Java EE
environments.</para>
<para>Spring's <interfacename>TaskExecutor</interfacename> interface is
identical to the <classname>java.util.concurrent.Executor</classname>
interface. In fact, its primary reason for existence is to abstract away
the need for Java 5 when using thread pools. The interface has a single
method <classname>execute(Runnable task)</classname> that accepts a task
for execution based on the semantics and configuration of the thread
pool.</para>
<para>The <interfacename>TaskExecutor</interfacename> was originally
created to give other Spring components an abstraction for thread pooling
where needed. Components such as the
<classname>ApplicationEventMulticaster</classname>, JMS's
<classname>AbstractMessageListenerContainer</classname>, and Quartz
integration all use the <interfacename>TaskExecutor</interfacename>
abstraction to pool threads. However, if your beans need thread pooling
behavior, it is possible to use this abstraction for your own
needs.</para>
<section xml:id="scheduling-task-executor-types">
<title><interfacename>TaskExecutor</interfacename> types</title>
<para>There are a number of pre-built implementations of
<interfacename>TaskExecutor</interfacename> included with the Spring
distribution. In all likelihood, you shouldn't ever need to implement
your own.</para>
<itemizedlist>
<listitem>
<para><classname>SimpleAsyncTaskExecutor</classname></para>
<para>This implementation does not reuse any threads, rather it
starts up a new thread for each invocation. However, it does support
a concurrency limit which will block any invocations that are over
the limit until a slot has been freed up. If you're looking for true
pooling, keep scrolling further down the page.</para>
</listitem>
<listitem xml:id="syncTaskExecutor">
<para><classname>SyncTaskExecutor</classname></para>
<para>This implementation doesn't execute invocations
asynchronously. Instead, each invocation takes place in the calling
thread. It is primarily used in situations where multithreading
isn't necessary such as simple test cases.</para>
</listitem>
<listitem xml:id="concurrentTaskExecutor">
<para><classname>ConcurrentTaskExecutor</classname></para>
<para>This implementation is a wrapper for a Java 5
<classname>java.util.concurrent.Executor</classname>. There is an
alternative, <classname>ThreadPoolTaskExecutor</classname>, that
exposes the <classname>Executor</classname> configuration parameters
as bean properties. It is rare to need to use the
<classname>ConcurrentTaskExecutor</classname> but if the <link
linkend="threadPoolTaskExecutor"><classname>ThreadPoolTaskExecutor</classname></link>
isn't robust enough for your needs, the
<classname>ConcurrentTaskExecutor</classname> is an
alternative.</para>
</listitem>
<listitem xml:id="simpleThreadPoolTaskExecutor">
<para><classname>SimpleThreadPoolTaskExecutor</classname></para>
<para>This implementation is actually a subclass of Quartz's
<classname>SimpleThreadPool</classname> which listens to Spring's
lifecycle callbacks. This is typically used when you have a thread
pool that may need to be shared by both Quartz and non-Quartz
components.</para>
</listitem>
<listitem xml:id="threadPoolTaskExecutor">
<para><classname>ThreadPoolTaskExecutor</classname></para>
<sidebar>
<para>It is not possible to use any backport or alternate versions
of the <classname>java.util.concurrent</classname> package with
this implementation. Both Doug Lea's and Dawid Kurzyniec's
implementations use different package structures which will
prevent them from working correctly.</para>
</sidebar>
<para>This implementation can only be used in a Java 5 environment
but is also the most commonly used one in that environment. It
exposes bean properties for configuring a
<classname>java.util.concurrent.ThreadPoolExecutor</classname> and
wraps it in a <interfacename>TaskExecutor</interfacename>. If you
need something advanced such as a
<classname>ScheduledThreadPoolExecutor</classname>, it is
recommended that you use a <link
linkend="concurrentTaskExecutor"><classname>ConcurrentTaskExecutor</classname></link>
instead.</para>
</listitem>
<listitem>
<para><classname>TimerTaskExecutor</classname></para>
<para>This implementation uses a single
<classname>TimerTask</classname> as its backing implementation. It's
different from the <link
linkend="syncTaskExecutor"><classname>SyncTaskExecutor</classname></link>
in that the method invocations are executed in a separate thread,
although they are synchronous in that thread.</para>
</listitem>
<listitem>
<para><classname>WorkManagerTaskExecutor</classname></para>
<sidebar>
<para>CommonJ is a set of specifications jointly developed between
BEA and IBM. These specifications are not Java EE standards, but
are standard across BEA's and IBM's Application Server
implementations.</para>
</sidebar>
<para>This implementation uses the CommonJ WorkManager as its
backing implementation and is the central convenience class for
setting up a CommonJ WorkManager reference in a Spring context.
Similar to the <link
linkend="simpleThreadPoolTaskExecutor"><classname>SimpleThreadPoolTaskExecutor</classname></link>,
this class implements the WorkManager interface and therefore can be
used directly as a WorkManager as well.</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="scheduling-task-executor-usage">
<title>Using a <interfacename>TaskExecutor</interfacename></title>
<para>Spring's <interfacename>TaskExecutor</interfacename>
implementations are used as simple JavaBeans. In the example below, we
define a bean that uses the
<classname>ThreadPoolTaskExecutor</classname> to asynchronously print
out a set of messages.</para>
<programlisting language="java">import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private String message;
public MessagePrinterTask(String message) {
this.message = message;
}
public void run() {
System.out.println(message);
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i &lt; 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
}</programlisting>
<para>As you can see, rather than retrieving a thread from the pool and
executing yourself, you add your <classname>Runnable</classname> to the
queue and the <interfacename>TaskExecutor</interfacename> uses its
internal rules to decide when the task gets executed.</para>
<para>To configure the rules that the
<interfacename>TaskExecutor</interfacename> will use, simple bean
properties have been exposed.</para>
<programlisting language="xml">&lt;bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"&gt;
&lt;property name="corePoolSize" value="5" /&gt;
&lt;property name="maxPoolSize" value="10" /&gt;
&lt;property name="queueCapacity" value="25" /&gt;
&lt;/bean&gt;
&lt;bean id="taskExecutorExample" class="TaskExecutorExample"&gt;
&lt;constructor-arg ref="taskExecutor" /&gt;
&lt;/bean&gt;</programlisting>
</section>
</section>
<section xml:id="scheduling-task-scheduler">
<title>The Spring <interfacename>TaskScheduler</interfacename>
abstraction</title>
<para>In addition to the <interfacename>TaskExecutor</interfacename>
abstraction, Spring 3.0 introduces a
<interfacename>TaskScheduler</interfacename> with a variety of methods for
scheduling tasks to run at some point in the future.</para>
<programlisting language="java">public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
ScheduledFuture schedule(Runnable task, Date startTime);
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}</programlisting>
<para>The simplest method is the one named 'schedule' that takes a
<interfacename>Runnable</interfacename> and <classname>Date</classname>
only. That will cause the task to run once after the specified time. All
of the other methods are capable of scheduling tasks to run repeatedly.
The fixed-rate and fixed-delay methods are for simple, periodic execution,
but the method that accepts a Trigger is much more flexible.</para>
<section xml:id="scheduling-trigger-interface">
<title>The <interfacename>Trigger</interfacename> interface</title>
<para>The <interfacename>Trigger</interfacename> interface is
essentially inspired by JSR-236, which, as of Spring 3.0, has not yet
been officially implemented. The basic idea of the
<interfacename>Trigger</interfacename> is that execution times may be
determined based on past execution outcomes or even arbitrary
conditions. If these determinations do take into account the outcome of
the preceding execution, that information is available within a
<interfacename>TriggerContext</interfacename>. The
<interfacename>Trigger</interfacename> interface itself is quite
simple:</para>
<programlisting language="java">public interface Trigger {
Date nextExecutionTime(TriggerContext triggerContext);
}</programlisting>
<para>As you can see, the <interfacename>TriggerContext</interfacename>
is the most important part. It encapsulates all of the relevant data,
and is open for extension in the future if necessary. The
<interfacename>TriggerContext</interfacename> is an interface (a
<classname>SimpleTriggerContext</classname> implementation is used by
default). Here you can see what methods are available for
<interfacename>Trigger</interfacename> implementations.</para>
<programlisting language="java">public interface TriggerContext {
Date lastScheduledExecutionTime();
Date lastActualExecutionTime();
Date lastCompletionTime();
}</programlisting>
</section>
<section xml:id="scheduling-trigger-implementations">
<title><interfacename>Trigger</interfacename> implementations</title>
<para>Spring provides two implementations of the
<interfacename>Trigger</interfacename> interface. The most interesting
one is the <classname>CronTrigger</classname>. It enables the scheduling
of tasks based on cron expressions. For example the following task is
being scheduled to run 15 minutes past each hour but only during the
9-to-5 "business hours" on weekdays.</para>
<programlisting language="java">scheduler.schedule(task, new CronTrigger("* 15 9-17 * * MON-FRI"));</programlisting>
<para>The other out-of-the-box implementation is a
<classname>PeriodicTrigger</classname> that accepts a fixed period, an
optional initial delay value, and a boolean to indicate whether the
period should be interpreted as a fixed-rate or a fixed-delay. Since the
<interfacename>TaskScheduler</interfacename> interface already defines
methods for scheduling tasks at a fixed-rate or with a fixed-delay,
those methods should be used directly whenever possible. The value of
the <classname>PeriodicTrigger</classname> implementation is that it can
be used within components that rely on the
<interfacename>Trigger</interfacename> abstraction. For example, it may
be convenient to allow periodic triggers, cron-based triggers, and even
custom trigger implementations to be used interchangeably. Such a
component could take advantage of dependency injection so that such
<interfacename>Triggers</interfacename> could be configured
externally.</para>
</section>
<section xml:id="scheduling-task-scheduler-implementations">
<title><interfacename>TaskScheduler</interfacename>
implementations</title>
<para>As with Spring's <interfacename>TaskExecutor</interfacename>
abstraction, the primary benefit of the
<interfacename>TaskScheduler</interfacename> is that code relying on
scheduling behavior need not be coupled to a particular scheduler
implementation. The flexibility this provides is particularly relevant
when running within Application Server environments where threads should
not be created directly by the application itself. For such cases,
Spring provides a <classname>TimerManagerTaskScheduler</classname> that
delegates to a CommonJ TimerManager instance, typically configured with
a JNDI-lookup.</para>
<para>A simpler alternative, the
<classname>ThreadPoolTaskScheduler</classname>, can be used whenever
external thread management is not a requirement. Internally, it
delegates to a <interfacename>ScheduledExecutorService</interfacename>
instance. <classname>ThreadPoolTaskScheduler</classname> actually
implements Spring's <interfacename>TaskExecutor</interfacename>
interface as well, so that a single instance can be used for
asynchronous execution <emphasis>as soon as possible</emphasis> as well
as scheduled, and potentially recurring, executions.</para>
</section>
</section>
<section xml:id="scheduling-annotation-support">
<title>Annotation Support for Scheduling and Asynchronous
Execution</title>
<para>Spring provides annotation support for both task scheduling and
asynchronous method execution.</para>
<section xml:id="scheduling-enable-annotation-support">
<title>Enable scheduling annotations</title>
<para>To enable support for <interfacename>@Scheduled</interfacename> and
<interfacename>@Async</interfacename> annotations add
<interfacename>@EnableScheduling</interfacename> and
<interfacename>@EnableAsync</interfacename> to one of your
<interfacename>@Configuration</interfacename> classes:</para>
<programlisting language="java">@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}</programlisting>
<para>You are free to pick and choose the relevant annotations
for your application. For example, if you only need support
for <interfacename>@Scheduled</interfacename>, simply omit
<interfacename>@EnableAsync</interfacename>. For more fine-grained
control you can additionally implement the
<interfacename>SchedulingConfigurer</interfacename> and/or
<interfacename>AsyncConfigurer</interfacename> interfaces. See
the Javadoc for full details.</para>
<para>If you prefer XML configuration use the
<literal>&lt;task:annotation-driven&gt;</literal> element.</para>
<programlisting language="xml">&lt;task:annotation-driven executor="myExecutor" scheduler="myScheduler"/&gt;
&lt;task:executor id="myExecutor" pool-size="5"/&gt;
&lt;task:scheduler id="myScheduler" pool-size="10"/&gt;}</programlisting>
<para>Notice with the above XML that an executor reference is provided
for handling those tasks that correspond to methods with the
<interfacename>@Async</interfacename> annotation, and the scheduler
reference is provided for managing those methods annotated
with <interfacename>@Scheduled</interfacename>.</para>
</section>
<section xml:id="scheduling-annotation-support-scheduled">
<title>The @Scheduled Annotation</title>
<para>The @Scheduled annotation can be added to a method along with
trigger metadata. For example, the following method would be invoked
every 5 seconds with a fixed delay, meaning that the period will be
measured from the completion time of each preceding invocation.</para>
<programlisting language="java">@Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
}</programlisting>
<para>If a fixed rate execution is desired, simply change the property
name specified within the annotation. The following would be executed
every 5 seconds measured between the successive start times of each
invocation.</para>
<programlisting language="java">@Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}</programlisting>
<para>For fixed-delay and fixed-rate tasks, an initial delay may be
specified indicating the number of milliseconds to wait before the first
execution of the method.
</para>
<programlisting language="java">@Scheduled(initialDelay=1000, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}</programlisting>
<para>If simple periodic scheduling is not expressive enough, then a
cron expression may be provided. For example, the following will only
execute on weekdays.</para>
<programlisting language="java">@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}</programlisting>
<para>Notice that the methods to be scheduled must have void returns and
must not expect any arguments. If the method needs to interact with
other objects from the Application Context, then those would typically
have been provided through dependency injection.</para>
<note>
<para>Make sure that you are not initializing multiple instances of
the same @Scheduled annotation class at runtime, unless you do want to
schedule callbacks to each such instance. Related to this, make sure
that you do not use @Configurable on bean classes which are annotated
with @Scheduled and registered as regular Spring beans with the
container: You would get double initialization otherwise, once through
the container and once through the @Configurable aspect, with the
consequence of each @Scheduled method being invoked twice.</para>
</note>
</section>
<section xml:id="scheduling-annotation-support-async">
<title>The @Async Annotation</title>
<para>The <interfacename>@Async</interfacename> annotation can be
provided on a method so that invocation of that method will occur
asynchronously. In other words, the caller will return immediately upon
invocation and the actual execution of the method will occur in a task
that has been submitted to a Spring
<interfacename>TaskExecutor</interfacename>. In the simplest case, the
annotation may be applied to a <literal>void</literal>-returning
method.</para>
<programlisting language="java">@Async
void doSomething() {
// this will be executed asynchronously
}</programlisting>
<para>Unlike the methods annotated with the
<interfacename>@Scheduled</interfacename> annotation, these methods can
expect arguments, because they will be invoked in the "normal" way by
callers at runtime rather than from a scheduled task being managed by
the container. For example, the following is a legitimate application of
the <interfacename>@Async</interfacename> annotation.</para>
<programlisting language="java">@Async
void doSomething(String s) {
// this will be executed asynchronously
}</programlisting>
<para>Even methods that return a value can be invoked asynchronously.
However, such methods are required to have a
<interfacename>Future</interfacename> typed return value. This still
provides the benefit of asynchronous execution so that the caller can
perform other tasks prior to calling <methodname>get()</methodname> on
that Future.</para>
<programlisting language="java">@Async
Future&lt;String&gt; returnSomething(int i) {
// this will be executed asynchronously
}</programlisting>
<para><interfacename>@Async</interfacename> can not be used in
conjunction with lifecycle callbacks such as
<interfacename>@PostConstruct</interfacename>. To asynchronously
initialize Spring beans you currently have to use a separate
initializing Spring bean that invokes the
<interfacename>@Async</interfacename> annotated method on the target
then.</para>
<programlisting language="java">public class SampleBeanImpl implements SampleBean {
@Async
void doSomething() { … }
}
public class SampleBeanInititalizer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
@PostConstruct
public void initialize() {
bean.doSomething();
}
}</programlisting>
</section>
<section xml:id="scheduling-annotation-support-qualification">
<title>Executor qualification with @Async</title>
<para>By default when specifying <interfacename>@Async</interfacename> on
a method, the executor that will be used is the one supplied to the
'annotation-driven' element as described above. However, the
<literal>value</literal> attribute of the
<interfacename>@Async</interfacename> annotation can be used when needing
to indicate that an executor other than the default should be used when
executing a given method.</para>
<programlisting language="java">@Async("otherExecutor")
void doSomething(String s) {
// this will be executed asynchronously by "otherExecutor"
}</programlisting>
<para>In this case, "otherExecutor" may be the name of any
<interfacename>Executor</interfacename> bean in the Spring container, or
may be the name of a <emphasis>qualifier</emphasis> associated with any
<interfacename>Executor</interfacename>, e.g. as specified with the
<literal>&lt;qualifier&gt;</literal> element or Spring's
<interfacename>@Qualifier</interfacename> annotation.</para>
</section>
</section>
<section xml:id="scheduling-task-namespace">
<title>The Task Namespace</title>
<para>Beginning with Spring 3.0, there is an XML namespace for configuring
<interfacename>TaskExecutor</interfacename> and
<interfacename>TaskScheduler</interfacename> instances. It also provides a
convenient way to configure tasks to be scheduled with a trigger.</para>
<section xml:id="scheduling-task-namespace-scheduler">
<title>The 'scheduler' element</title>
<para>The following element will create a
<classname>ThreadPoolTaskScheduler</classname> instance with the
specified thread pool size.</para>
<programlisting language="xml">&lt;task:scheduler id="scheduler" pool-size="10"/&gt;</programlisting>
<para>The value provided for the 'id' attribute will be used as the
prefix for thread names within the pool. The 'scheduler' element is
relatively straightforward. If you do not provide a 'pool-size'
attribute, the default thread pool will only have a single thread. There
are no other configuration options for the scheduler.</para>
</section>
<section xml:id="scheduling-task-namespace-executor">
<title>The 'executor' element</title>
<para>The following will create a
<classname>ThreadPoolTaskExecutor</classname> instance: <programlisting
language="xml">&lt;task:executor id="executor" pool-size="10"/&gt;</programlisting></para>
<para>As with the scheduler above, the value provided for the 'id'
attribute will be used as the prefix for thread names within the pool.
As far as the pool size is concerned, the 'executor' element supports
more configuration options than the 'scheduler' element. For one thing,
the thread pool for a <classname>ThreadPoolTaskExecutor</classname> is
itself more configurable. Rather than just a single size, an executor's
thread pool may have different values for the <emphasis>core</emphasis>
and the <emphasis>max</emphasis> size. If a single value is provided
then the executor will have a fixed-size thread pool (the core and max
sizes are the same). However, the 'executor' element's 'pool-size'
attribute also accepts a range in the form of "min-max". <programlisting
language="xml">&lt;task:executor id="executorWithPoolSizeRange"
pool-size="5-25"
queue-capacity="100"/&gt;</programlisting></para>
<para>As you can see from that configuration, a 'queue-capacity' value
has also been provided. The configuration of the thread pool should also
be considered in light of the executor's queue capacity. For the full
description of the relationship between pool size and queue capacity,
consult the documentation for <link
xl:href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html">ThreadPoolExecutor</link>.
The main idea is that when a task is submitted, the executor will first
try to use a free thread if the number of active threads is currently
less than the core size. If the core size has been reached, then the
task will be added to the queue as long as its capacity has not yet been
reached. Only then, if the queue's capacity <emphasis>has</emphasis>
been reached, will the executor create a new thread beyond the core
size. If the max size has also been reached, then the executor will
reject the task.</para>
<para>By default, the queue is <emphasis>unbounded</emphasis>, but this
is rarely the desired configuration, because it can lead to
<classname>OutOfMemoryErrors</classname> if enough tasks are added to
that queue while all pool threads are busy. Furthermore, if the queue is
unbounded, then the max size has no effect at all. Since the executor
will always try the queue before creating a new thread beyond the core
size, a queue must have a finite capacity for the thread pool to grow
beyond the core size (this is why a <emphasis>fixed size</emphasis> pool
is the only sensible case when using an unbounded queue).</para>
<para>In a moment, we will review the effects of the keep-alive setting
which adds yet another factor to consider when providing a pool size
configuration. First, let's consider the case, as mentioned above, when
a task is rejected. By default, when a task is rejected, a thread pool
executor will throw a <classname>TaskRejectedException</classname>.
However, the rejection policy is actually configurable. The exception is
thrown when using the default rejection policy which is the
<classname>AbortPolicy</classname> implementation. For applications
where some tasks can be skipped under heavy load, either the
<classname>DiscardPolicy</classname> or
<classname>DiscardOldestPolicy</classname> may be configured instead.
Another option that works well for applications that need to throttle
the submitted tasks under heavy load is the
<classname>CallerRunsPolicy</classname>. Instead of throwing an
exception or discarding tasks, that policy will simply force the thread
that is calling the submit method to run the task itself. The idea is
that such a caller will be busy while running that task and not able to
submit other tasks immediately. Therefore it provides a simple way to
throttle the incoming load while maintaining the limits of the thread
pool and queue. Typically this allows the executor to "catch up" on the
tasks it is handling and thereby frees up some capacity on the queue, in
the pool, or both. Any of these options can be chosen from an
enumeration of values available for the 'rejection-policy' attribute on
the 'executor' element.</para>
<programlisting language="xml">&lt;task:executor id="executorWithCallerRunsPolicy"
pool-size="5-25"
queue-capacity="100"
rejection-policy="CALLER_RUNS"/&gt;</programlisting>
</section>
<section xml:id="scheduling-task-namespace-scheduled-tasks">
<title>The 'scheduled-tasks' element</title>
<para>The most powerful feature of Spring's task namespace is the
support for configuring tasks to be scheduled within a Spring
Application Context. This follows an approach similar to other
"method-invokers" in Spring, such as that provided by the JMS namespace
for configuring Message-driven POJOs. Basically a "ref" attribute can
point to any Spring-managed object, and the "method" attribute provides
the name of a method to be invoked on that object. Here is a simple
example.</para>
<programlisting language="xml">&lt;task:scheduled-tasks scheduler="myScheduler"&gt;
&lt;task:scheduled ref="beanA" method="methodA" fixed-delay="5000"/&gt;
&lt;/task:scheduled-tasks&gt;
&lt;task:scheduler id="myScheduler" pool-size="10"/&gt;</programlisting>
<para>As you can see, the scheduler is referenced by the outer element,
and each individual task includes the configuration of its trigger
metadata. In the preceding example, that metadata defines a periodic
trigger with a fixed delay indicating the number of milliseconds to wait
after each task execution has completed. Another option is 'fixed-rate',
indicating how often the method should be executed regardless of how long
any previous execution takes. Additionally, for both fixed-delay and
fixed-rate tasks an 'initial-delay' parameter may be specified indicating
the number of milliseconds to wait before the first execution of the
method. For more control, a "cron" attribute may be provided instead.
Here is an example demonstrating these other options.</para>
<programlisting language="xml">&lt;task:scheduled-tasks scheduler="myScheduler"&gt;
&lt;task:scheduled ref="beanA" method="methodA" fixed-delay="5000" initial-delay="1000"/&gt;
&lt;task:scheduled ref="beanB" method="methodB" fixed-rate="5000"/&gt;
&lt;task:scheduled ref="beanC" method="methodC" cron="*/5 * * * * MON-FRI"/&gt;
&lt;/task:scheduled-tasks&gt;
&lt;task:scheduler id="myScheduler" pool-size="10"/&gt;</programlisting>
</section>
</section>
<section xml:id="scheduling-quartz">
<title>Using the Quartz Scheduler</title>
<para>Quartz uses <classname>Trigger</classname>,
<classname>Job</classname> and <classname>JobDetail</classname> objects to
realize scheduling of all kinds of jobs. For the basic concepts behind
Quartz, have a look at <link
xl:href="http://quartz-scheduler.org"></link>. For convenience
purposes, Spring offers a couple of classes that simplify the usage of
Quartz within Spring-based applications.</para>
<section xml:id="scheduling-quartz-jobdetail">
<title>Using the JobDetailBean</title>
<para><classname>JobDetail</classname> objects contain all information
needed to run a job. The Spring Framework provides a
<classname>JobDetailBean</classname> that makes the
<classname>JobDetail</classname> more of an actual JavaBean with
sensible defaults. Let's have a look at an example:</para>
<programlisting language="xml">
&lt;bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean"&gt;
&lt;property name="jobClass" value="example.ExampleJob" /&gt;
&lt;property name="jobDataAsMap"&gt;
&lt;map&gt;
&lt;entry key="timeout" value="5" /&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>The job detail bean has all information it needs to run the job
(<classname>ExampleJob</classname>). The timeout is specified in the job
data map. The job data map is available through the
<classname>JobExecutionContext</classname> (passed to you at execution
time), but the <classname>JobDetailBean</classname> also maps the
properties from the job data map to properties of the actual job. So in
this case, if the <classname>ExampleJob</classname> contains a property
named <literal>timeout</literal>, the
<classname>JobDetailBean</classname> will automatically apply it:</para>
<programlisting language="java">package example;
public class ExampleJob extends QuartzJobBean {
private int timeout;
/**
* Setter called after the ExampleJob is instantiated
* with the value from the JobDetailBean (5)
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
<lineannotation>// do the actual work</lineannotation>
}
}</programlisting>
<para>All additional settings from the job detail bean are of course
available to you as well.</para>
<para><emphasis>Note: Using the <literal>name</literal> and
<literal>group</literal> properties, you can modify the name and the
group of the job, respectively. By default, the name of the job matches
the bean name of the job detail bean (in the example above, this is
<literal>exampleJob</literal>).</emphasis></para>
</section>
<section xml:id="scheduling-quartz-method-invoking-job">
<title>Using the
<classname>MethodInvokingJobDetailFactoryBean</classname></title>
<para>Often you just need to invoke a method on a specific object. Using
the <classname>MethodInvokingJobDetailFactoryBean</classname> you can do
exactly this:</para>
<programlisting language="xml">&lt;bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"&gt;
&lt;property name="targetObject" ref="exampleBusinessObject" /&gt;
&lt;property name="targetMethod" value="doIt" /&gt;
&lt;/bean&gt;</programlisting>
<para>The above example will result in the <literal>doIt</literal>
method being called on the <literal>exampleBusinessObject</literal>
method (see below):</para>
<programlisting language="java">public class ExampleBusinessObject {
<lineannotation>// properties and collaborators</lineannotation>
public void doIt() {
<lineannotation>// do the actual work</lineannotation>
}
}</programlisting>
<programlisting language="xml">
&lt;bean id="exampleBusinessObject" class="examples.ExampleBusinessObject"/&gt;</programlisting>
<para>Using the
<classname>MethodInvokingJobDetailFactoryBean</classname>, you don't
need to create one-line jobs that just invoke a method, and you only
need to create the actual business object and wire up the detail
object.</para>
<para>By default, Quartz Jobs are stateless, resulting in the
possibility of jobs interfering with each other. If you specify two
triggers for the same <classname>JobDetail</classname>, it might be
possible that before the first job has finished, the second one will
start. If <classname>JobDetail</classname> classes implement the
<interfacename>Stateful</interfacename> interface, this won't happen.
The second job will not start before the first one has finished. To make
jobs resulting from the
<classname>MethodInvokingJobDetailFactoryBean</classname>
non-concurrent, set the <literal>concurrent</literal> flag to
<literal>false</literal>.</para>
<programlisting language="xml">
&lt;bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"&gt;
&lt;property name="targetObject" ref="exampleBusinessObject" /&gt;
&lt;property name="targetMethod" value="doIt" /&gt;
&lt;property name="concurrent" value="false" /&gt;
&lt;/bean&gt;</programlisting>
<note>
<para>By default, jobs will run in a concurrent fashion.</para>
</note>
</section>
<section xml:id="scheduling-quartz-cron">
<title>Wiring up jobs using triggers and the
<classname>SchedulerFactoryBean</classname></title>
<para>We've created job details and jobs. We've also reviewed the
convenience bean that allows you to invoke a method on a specific
object. Of course, we still need to schedule the jobs themselves. This
is done using triggers and a
<classname>SchedulerFactoryBean</classname>. Several triggers are
available within Quartz and Spring offers two Quartz <interfacename>FactoryBean</interfacename>
implementations with convenient defaults: <classname>CronTriggerFactoryBean</classname> and
<classname>SimpleTriggerFactoryBean</classname>.</para>
<para>Triggers need to be scheduled. Spring offers a
<classname>SchedulerFactoryBean</classname> that exposes triggers to be
set as properties. <classname>SchedulerFactoryBean</classname> schedules
the actual jobs with those triggers.</para>
<para>Find below a couple of examples:</para>
<programlisting language="xml">&lt;bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"&gt;
&lt;!-- see the example of method invoking job above --&gt;
&lt;property name="jobDetail" ref="jobDetail" /&gt;
&lt;!-- 10 seconds --&gt;
&lt;property name="startDelay" value="10000" /&gt;
&lt;!-- repeat every 50 seconds --&gt;
&lt;property name="repeatInterval" value="50000" /&gt;
&lt;/bean&gt;
&lt;bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"&gt;
&lt;property name="jobDetail" ref="exampleJob" /&gt;
&lt;!-- run every morning at 6 AM --&gt;
&lt;property name="cronExpression" value="0 0 6 * * ?" /&gt;
&lt;/bean&gt;</programlisting>
<para>Now we've set up two triggers, one running every 50 seconds with a
starting delay of 10 seconds and one every morning at 6 AM. To finalize
everything, we need to set up the
<classname>SchedulerFactoryBean</classname>:</para>
<programlisting language="xml">&lt;bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"&gt;
&lt;property name="triggers"&gt;
&lt;list&gt;
&lt;ref bean="cronTrigger" /&gt;
&lt;ref bean="simpleTrigger" /&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<para>More properties are available for the
<classname>SchedulerFactoryBean</classname> for you to set, such as the
calendars used by the job details, properties to customize Quartz with,
etc. Have a look at the <link
xl:href="http://static.springsource.org/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html">SchedulerFactoryBean
Javadoc</link> for more information.</para>
</section>
</section>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@ -1,969 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xml:id="spring.tld"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>spring.tld</title>
<section xml:id="spring.tld-intro">
<title>Introduction</title>
<para>One of the view technologies you can use with the Spring Framework
is Java Server Pages (JSPs). To help you implement views using Java Server Pages
the Spring Framework provides you with some tags for evaluating errors, setting
themes and outputting internationalized messages.</para>
<para>Please note that the various tags generated by this form tag library
are compliant with the <link xl:href="http://www.w3.org/TR/xhtml1/">XHTML-1.0-Strict specification</link> and attendant <link xl:href="http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_XHTML-1.0-Strict">DTD</link>.</para>
<para>This appendix describes the <literal>spring.tld</literal> tag library.</para>
<itemizedlist>
<listitem>
<xref linkend="spring.tld.bind"/>
</listitem>
<listitem>
<xref linkend="spring.tld.escapeBody"/>
</listitem>
<listitem>
<xref linkend="spring.tld.hasBindErrors"/>
</listitem>
<listitem>
<xref linkend="spring.tld.htmlEscape"/>
</listitem>
<listitem>
<xref linkend="spring.tld.message"/>
</listitem>
<listitem>
<xref linkend="spring.tld.nestedPath"/>
</listitem>
<listitem>
<xref linkend="spring.tld.theme"/>
</listitem>
<listitem>
<xref linkend="spring.tld.transform"/>
</listitem>
<listitem>
<xref linkend="spring.tld.url"/>
</listitem>
<listitem>
<xref linkend="spring.tld.eval"/>
</listitem>
</itemizedlist>
</section>
<section xml:id="spring.tld.bind">
<title>The <literal>bind</literal> tag</title>
<para>
Provides BindStatus object for the given bind path.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</para>
<table xml:id="spring.tld.bind.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value. Overrides
the default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>ignoreNestedPath</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set whether to ignore a nested path, if any. Default is to not ignore.</para>
</entry>
</row>
<row>
<entry>
<para>path</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The path to the bean or bean property to bind status
information for. For instance account.name, company.address.zipCode
or just employee. The status object will exported to the page scope,
specifically for this bean or bean property</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.escapeBody">
<title>The <literal>escapeBody</literal> tag</title>
<para>
Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</para>
<table xml:id="spring.tld.escapeBody.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value. Overrides the
default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>javaScriptEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set JavaScript escaping for this tag, as boolean value.
Default is false.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.hasBindErrors">
<title>The <literal>hasBindErrors</literal> tag</title>
<para>
Provides Errors instance in case of bind errors.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</para>
<table xml:id="spring.tld.hasBindErrors.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>name</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The name of the bean in the request, that needs to be
inspected for errors. If errors are available for this bean, they
will be bound under the 'errors' key.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.htmlEscape">
<title>The <literal>htmlEscape</literal> tag</title>
<para>
Sets default HTML escape value for the current page.
Overrides a "defaultHtmlEscape" context-param in web.xml, if any.
</para>
<table xml:id="spring.tld.htmlEscape.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>defaultHtmlEscape</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set the default value for HTML escaping, to be put
into the current PageContext.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.message">
<title>The <literal>message</literal> tag</title>
<para>
Retrieves the message with the given code, or text if code isn't resolvable.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</para>
<table xml:id="spring.tld.message.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>arguments</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set optional message arguments for this tag, as a
(comma-)delimited String (each String argument can contain JSP EL),
an Object array (used as argument array), or a single Object (used
as single argument).</para>
</entry>
</row>
<row>
<entry>
<para>argumentSeparator</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The separator character to be used for splitting the
arguments string value; defaults to a 'comma' (',').</para>
</entry>
</row>
<row>
<entry>
<para>code</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The code (key) to use when looking up the message.
If code is not provided, the text attribute will be used.</para>
</entry>
</row>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>javaScriptEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set JavaScript escaping for this tag, as boolean value. Default is false.</para>
</entry>
</row>
<row>
<entry>
<para>message</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>A MessageSourceResolvable argument (direct or through JSP EL).
Fits nicely when used in conjunction with Spring's own validation error
classes which all implement the MessageSourceResolvable interface. For
example, this allows you to iterate over all of the errors in a form,
passing each error (using a runtime expression) as the value of this
'message' attribute, thus effecting the easy display of such error
messages.</para>
</entry>
</row>
<row>
<entry>
<para>scope</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The scope to use when exporting the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.</para>
</entry>
</row>
<row>
<entry>
<para>text</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Default text to output when a message for the given code
could not be found. If both text and code are not set, the tag will
output null.</para>
</entry>
</row>
<row>
<entry>
<para>var</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result
gets outputted to the writer (i.e. typically directly to the JSP).</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.nestedPath">
<title>The <literal>nestedPath</literal> tag</title>
<para>
Sets a nested path to be used by the bind tag's path.
</para>
<table xml:id="spring.tld.nestedPath.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>path</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set the path that this tag should apply. E.g. 'customer'
to allow bind paths like 'address.street' rather than
'customer.address.street'.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.theme">
<title>The <literal>theme</literal> tag</title>
<para>
Retrieves the theme message with the given code, or text if code isn't resolvable.
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml).
</para>
<table xml:id="spring.tld.theme.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>arguments</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set optional message arguments for this tag, as a
(comma-)delimited String (each String argument can contain JSP EL),
an Object array (used as argument array), or a single Object (used
as single argument).</para>
</entry>
</row>
<row>
<entry>
<para>argumentSeparator</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The separator character to be used for splitting the
arguments string value; defaults to a 'comma' (',').</para>
</entry>
</row>
<row>
<entry>
<para>code</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The code (key) to use when looking up the message.
If code is not provided, the text attribute will be used.</para>
</entry>
</row>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value.
Overrides the default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>javaScriptEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set JavaScript escaping for this tag, as boolean value. Default is false.</para>
</entry>
</row>
<row>
<entry>
<para>message</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>A MessageSourceResolvable argument (direct or through JSP EL).</para>
</entry>
</row>
<row>
<entry>
<para>scope</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The scope to use when exporting the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.</para>
</entry>
</row>
<row>
<entry>
<para>text</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Default text to output when a message for the given code
could not be found. If both text and code are not set, the tag will
output null.</para>
</entry>
</row>
<row>
<entry>
<para>var</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result
gets outputted to the writer (i.e. typically directly to the JSP).</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.transform">
<title>The <literal>transform</literal> tag</title>
<para>
Provides transformation of variables to Strings, using an appropriate
custom PropertyEditor from BindTag (can only be used inside BindTag).
The HTML escaping flag participates in a page-wide or application-wide setting
(i.e. by HtmlEscapeTag or a 'defaultHtmlEscape' context-param in web.xml).
</para>
<table xml:id="spring.tld.transform.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as boolean value. Overrides
the default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>scope</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The scope to use when exported the result to a variable.
This attribute is only used when var is also set. Possible values are
page, request, session and application.</para>
</entry>
</row>
<row>
<entry>
<para>value</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The value to transform. This is the actual object you want
to have transformed (for instance a Date). Using the PropertyEditor that
is currently in use by the 'spring:bind' tag.</para>
</entry>
</row>
<row>
<entry>
<para>var</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The string to use when binding the result to the page,
request, session or application scope. If not specified, the result gets
outputted to the writer (i.e. typically directly to the JSP).</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.url">
<title>The <literal>url</literal> tag</title>
<para>
Creates URLs with support for URI template variables, HTML/XML escaping, and Javascript escaping.
Modeled after the JSTL c:url tag with backwards compatibility in mind.
</para>
<table xml:id="spring.tld.url.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>url</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The URL to build. This value can include template {placeholders}
that are replaced with the URL encoded value of the named parameter. Parameters
must be defined using the param tag inside the body of this tag.</para>
</entry>
</row>
<row>
<entry>
<para>context</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Specifies a remote application context path. The default is the
current application context path.</para>
</entry>
</row>
<row>
<entry>
<para>var</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The name of the variable to export the URL value to.
If not specified the URL is written as output.</para>
</entry>
</row>
<row>
<entry>
<para>scope</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The scope for the var. 'application', 'session', 'request' and
'page' scopes are supported. Defaults to page scope. This attribute has no
effect unless the var attribute is also defined.</para>
</entry>
</row>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as a boolean value. Overrides the
default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>javaScriptEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set JavaScript escaping for this tag, as a boolean value.
Default is false.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
<section xml:id="spring.tld.eval">
<title>The <literal>eval</literal> tag</title>
<para>
Evaluates a Spring expression (SpEL) and either prints the result or assigns it to a variable.
</para>
<table xml:id="spring.tld.eval.table">
<title>Attributes</title>
<tgroup cols="4">
<colspec align="center" colname="Attribute"/>
<colspec align="center" colname="Required"/>
<colspec align="center" colname="Runtime.Expression"/>
<colspec align="left" colname="Description"/>
<thead>
<row>
<entry align="center">Attribute</entry>
<entry align="center">Required?</entry>
<entry align="center">Runtime Expression?</entry>
<entry align="left">Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>expression</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The expression to evaluate.</para>
</entry>
</row>
<row>
<entry>
<para>var</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The name of the variable to export the evaluation result to.
If not specified the evaluation result is converted to a String and written as output.</para>
</entry>
</row>
<row>
<entry>
<para>scope</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>The scope for the var. 'application', 'session', 'request' and
'page' scopes are supported. Defaults to page scope. This attribute has no
effect unless the var attribute is also defined.</para>
</entry>
</row>
<row>
<entry>
<para>htmlEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set HTML escaping for this tag, as a boolean value. Overrides the
default HTML escaping setting for the current page.</para>
</entry>
</row>
<row>
<entry>
<para>javaScriptEscape</para>
</entry>
<entry>
<para>false</para>
</entry>
<entry>
<para>true</para>
</entry>
<entry>
<para>Set JavaScript escaping for this tag, as a boolean value.
Default is false.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
</section>
</appendix>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<sidebar
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Spring Web Flow</title>
<para>Spring Web Flow (SWF) aims to be the best solution for the management
of web application page flow.</para>
<para>SWF integrates with existing frameworks like Spring MVC, Struts, and
JSF, in both servlet and portlet environments. If you have a business
process (or processes) that would benefit from a conversational model as
opposed to a purely request model, then SWF may be the solution.</para>
<para>SWF allows you to capture logical page flows as self-contained modules
that are reusable in different situations, and as such is ideal for building
web application modules that guide the user through controlled navigations
that drive business processes.</para>
<para>For more information about SWF, consult the
<link xl:href="http://www.springframework.org/webflow">Spring Web Flow website</link>.
</para>
</sidebar>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,610 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<appendix xml:id="extensible-xml"
xmlns="http://docbook.org/ns/docbook" version="5.0"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd">
<title>Extensible XML authoring</title>
<section xml:id="extensible-xml-introduction">
<title>Introduction</title>
<para>Since version 2.0, Spring has featured a mechanism for schema-based extensions
to the basic Spring XML format for defining and configuring beans. This section is
devoted to detailing how you would go about writing your own custom XML bean definition
parsers and integrating such parsers into the Spring IoC container.</para>
<para>To facilitate the authoring of configuration files using a schema-aware XML editor,
Spring's extensible XML configuration mechanism is based on XML Schema. If you are
not familiar with Spring's current XML configuration extensions that come with the
standard Spring distribution, please first read the appendix entitled
<xref linkend="xsd-config"/>.</para>
<para>Creating new XML configuration extensions can be done by following these (relatively)
simple steps:</para>
<para>
<orderedlist numeration="arabic">
<listitem>
<para><link linkend="extensible-xml-schema">Authoring</link> an XML schema to describe your custom element(s).</para>
</listitem>
<listitem>
<para><link linkend="extensible-xml-namespacehandler">Coding</link> a custom <interfacename>NamespaceHandler</interfacename>
implementation (this is an easy step, don't worry).</para>
</listitem>
<listitem>
<para><link linkend="extensible-xml-parser">Coding</link> one or more <interfacename>BeanDefinitionParser</interfacename>
implementations (this is where the real work is done).</para>
</listitem>
<listitem>
<para><link linkend="extensible-xml-registration">Registering</link> the above artifacts with Spring (this too is an easy step).</para>
</listitem>
</orderedlist>
</para>
<para>What follows is a description of each of these steps. For the example, we will create
an XML extension (a custom XML element) that allows us to configure objects of the type
<classname>SimpleDateFormat</classname> (from the <literal>java.text</literal> package)
in an easy manner. When we are done, we will be able to define bean definitions of type
<classname>SimpleDateFormat</classname> like this:</para>
<programlisting language="xml"><![CDATA[<myns:dateformat id="dateFormat"
pattern="yyyy-MM-dd HH:mm"
lenient="true"/>
]]></programlisting>
<para><emphasis>(Don't worry about the fact that this example is very simple; much more
detailed examples follow afterwards. The intent in this first simple example is to walk
you through the basic steps involved.)</emphasis></para>
</section>
<section xml:id="extensible-xml-schema">
<title>Authoring the schema</title>
<para>Creating an XML configuration extension for use with Spring's IoC container
starts with authoring an XML Schema to describe the extension. What follows
is the schema we'll use to configure <classname>SimpleDateFormat</classname>
objects.</para>
<programlisting language="xml"><lineannotation>&lt;!-- myns.xsd (inside package org/springframework/samples/xml) --&gt;</lineannotation><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/myns"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.mycompany.com/schema/myns"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="dateformat">
<xsd:complexType>
<xsd:complexContent>]]>
<emphasis role="bold"><![CDATA[<xsd:extension base="beans:identifiedType">]]></emphasis><![CDATA[
<xsd:attribute name="lenient" type="xsd:boolean"/>
<xsd:attribute name="pattern" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>]]></programlisting>
<para>(The emphasized line contains an extension base for all tags that
will be identifiable (meaning they have an <literal>id</literal> attribute
that will be used as the bean identifier in the container). We are able to use this
attribute because we imported the Spring-provided <literal>'beans'</literal>
namespace.)</para>
<para>The above schema will be used to configure <classname>SimpleDateFormat</classname>
objects, directly in an XML application context file using the
<literal>&lt;myns:dateformat/&gt;</literal> element.</para>
<programlisting language="xml"><![CDATA[<myns:dateformat id="dateFormat"
pattern="yyyy-MM-dd HH:mm"
lenient="true"/>
]]></programlisting>
<para>Note that after we've created the infrastructure classes, the above snippet of XML
will essentially be exactly the same as the following XML snippet. In other words,
we're just creating a bean in the container, identified by the name
<literal>'dateFormat'</literal> of type <classname>SimpleDateFormat</classname>, with a
couple of properties set.</para>
<programlisting language="xml"><![CDATA[<bean id="dateFormat" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-HH-dd HH:mm"/>
<property name="lenient" value="true"/>
</bean>]]></programlisting>
<note>
<para>The schema-based approach to creating configuration format allows for
tight integration with an IDE that has a schema-aware XML editor. Using a properly
authored schema, you can use autocompletion to have a user choose between several
configuration options defined in the enumeration.</para>
</note>
</section>
<section xml:id="extensible-xml-namespacehandler">
<title>Coding a <interfacename>NamespaceHandler</interfacename></title>
<para>In addition to the schema, we need a <interfacename>NamespaceHandler</interfacename>
that will parse all elements of this specific namespace Spring encounters
while parsing configuration files. The <interfacename>NamespaceHandler</interfacename>
should in our case take care of the parsing of the <literal>myns:dateformat</literal>
element.</para>
<para>The <interfacename>NamespaceHandler</interfacename> interface is pretty simple in that
it features just three methods:</para>
<itemizedlist spacing="compact">
<listitem>
<para><methodname>init()</methodname> - allows for initialization of
the <interfacename>NamespaceHandler</interfacename> and will be called by Spring
before the handler is used</para>
</listitem>
<listitem>
<para><methodname>BeanDefinition parse(Element, ParserContext)</methodname> -
called when Spring encounters a top-level element (not nested inside a bean definition
or a different namespace). This method can register bean definitions itself and/or
return a bean definition.</para>
</listitem>
<listitem>
<para><methodname>BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)</methodname> -
called when Spring encounters an attribute or nested element of a different namespace.
The decoration of one or more bean definitions is used for example with the
<link linkend="beans-factory-scopes">out-of-the-box scopes Spring 2.0 supports</link>.
We'll start by highlighting a simple example, without using decoration, after which
we will show decoration in a somewhat more advanced example.</para>
</listitem>
</itemizedlist>
<para>Although it is perfectly possible to code your own
<interfacename>NamespaceHandler</interfacename> for the entire namespace
(and hence provide code that parses each and every element in the namespace),
it is often the case that each top-level XML element in a Spring XML
configuration file results in a single bean definition (as in our
case, where a single <literal>&lt;myns:dateformat/&gt;</literal> element
results in a single <classname>SimpleDateFormat</classname> bean definition).
Spring features a number of convenience classes that support this scenario.
In this example, we'll make use the <classname>NamespaceHandlerSupport</classname> class:</para>
<programlisting language="java"><![CDATA[package org.springframework.samples.xml;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
public void init() {]]><emphasis role="bold"><![CDATA[
registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
]]></emphasis>}
}</programlisting>
<para>The observant reader will notice that there isn't actually a whole lot of
parsing logic in this class. Indeed... the <classname>NamespaceHandlerSupport</classname>
class has a built in notion of delegation. It supports the registration of any number
of <interfacename>BeanDefinitionParser</interfacename> instances, to which it will delegate
to when it needs to parse an element in its namespace. This clean separation of concerns
allows a <interfacename>NamespaceHandler</interfacename> to handle the orchestration
of the parsing of <emphasis>all</emphasis> of the custom elements in its namespace,
while delegating to <literal>BeanDefinitionParsers</literal> to do the grunt work of the
XML parsing; this means that each <interfacename>BeanDefinitionParser</interfacename> will
contain just the logic for parsing a single custom element, as we can see in the next step</para>
</section>
<section xml:id="extensible-xml-parser">
<title>Coding a <interfacename>BeanDefinitionParser</interfacename></title>
<para>A <interfacename>BeanDefinitionParser</interfacename> will be used if the
<interfacename>NamespaceHandler</interfacename> encounters an XML element of the type
that has been mapped to the specific bean definition parser (which is <literal>'dateformat'</literal>
in this case). In other words, the <interfacename>BeanDefinitionParser</interfacename> is
responsible for parsing <emphasis>one</emphasis> distinct top-level XML element defined in the
schema. In the parser, we'll have access to the XML element (and thus its subelements too)
so that we can parse our custom XML content, as can be seen in the following example:</para>
<programlisting language="java"><![CDATA[package org.springframework.samples.xml;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
import java.text.SimpleDateFormat;
public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { ]]><co xml:id="extensible-xml-parser-simpledateformat-co-1"/><![CDATA[
protected Class getBeanClass(Element element) {
return SimpleDateFormat.class; ]]><co xml:id="extensible-xml-parser-simpledateformat-co-2"/><![CDATA[
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
]]><lineannotation>// this will never be null since the schema explicitly requires that a value be supplied</lineannotation><![CDATA[
String pattern = element.getAttribute("pattern");
bean.addConstructorArg(pattern);
]]><lineannotation>// this however is an optional property</lineannotation><![CDATA[
String lenient = element.getAttribute("lenient");
if (StringUtils.hasText(lenient)) {
bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
}
}
}]]></programlisting>
<calloutlist>
<callout arearefs="extensible-xml-parser-simpledateformat-co-1">
<para>We use the Spring-provided <classname>AbstractSingleBeanDefinitionParser</classname>
to handle a lot of the basic grunt work of creating a <emphasis>single</emphasis>
<interfacename>BeanDefinition</interfacename>.</para>
</callout>
<callout arearefs="extensible-xml-parser-simpledateformat-co-2">
<para>We supply the <classname>AbstractSingleBeanDefinitionParser</classname> superclass
with the type that our single <interfacename>BeanDefinition</interfacename> will represent.</para>
</callout>
</calloutlist>
<para>In this simple case, this is all that we need to do. The creation of our single
<interfacename>BeanDefinition</interfacename> is handled by the <classname>AbstractSingleBeanDefinitionParser</classname>
superclass, as is the extraction and setting of the bean definition's unique identifier.</para>
</section>
<section xml:id="extensible-xml-registration">
<title>Registering the handler and the schema</title>
<para>The coding is finished! All that remains to be done is to somehow make the Spring XML
parsing infrastructure aware of our custom element; we do this by registering our custom
<interfacename>namespaceHandler</interfacename> and custom XSD file in two special purpose
properties files. These properties files are both placed in a
<filename class="directory">'META-INF'</filename> directory in your application, and can, for
example, be distributed alongside your binary classes in a JAR file. The Spring XML parsing
infrastructure will automatically pick up your new extension by consuming these special
properties files, the formats of which are detailed below.</para>
<section xml:id="extensible-xml-registration-spring-handlers">
<title><filename>'META-INF/spring.handlers'</filename></title>
<para>The properties file called <filename>'spring.handlers'</filename> contains a mapping
of XML Schema URIs to namespace handler classes. So for our example, we need to write the
following:</para>
<programlisting><![CDATA[http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler]]></programlisting>
<para><emphasis>(The <literal>':'</literal> character is a valid delimiter in the Java properties format,
and so the <literal>':'</literal> character in the URI needs to be escaped with a backslash.)</emphasis></para>
<para>The first part (the key) of the key-value pair is the URI associated with your custom namespace
extension, and needs to <emphasis>match exactly</emphasis> the value of the
<literal>'targetNamespace'</literal> attribute as specified in your custom XSD schema.</para>
</section>
<section xml:id="extensible-xml-registration-spring-schemas">
<title><filename>'META-INF/spring.schemas'</filename></title>
<para>The properties file called <filename>'spring.schemas'</filename> contains a mapping
of XML Schema locations (referred to along with the schema declaration in XML files
that use the schema as part of the <literal>'xsi:schemaLocation'</literal> attribute)
to <emphasis>classpath</emphasis> resources. This file is needed to prevent Spring from
absolutely having to use a default <interfacename>EntityResolver</interfacename> that requires
Internet access to retrieve the schema file. If you specify the mapping in this properties file,
Spring will search for the schema on the classpath (in this case <literal>'myns.xsd'</literal>
in the <literal>'org.springframework.samples.xml'</literal> package):</para>
<programlisting><![CDATA[http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd]]></programlisting>
<para>The upshot of this is that you are encouraged to deploy your XSD file(s) right alongside
the <interfacename>NamespaceHandler</interfacename> and <interfacename>BeanDefinitionParser</interfacename>
classes on the classpath.</para>
</section>
</section>
<section xml:id="extensible-xml-using">
<title>Using a custom extension in your Spring XML configuration</title>
<para>Using a custom extension that you yourself have implemented is no different from
using one of the 'custom' extensions that Spring provides straight out of the box. Find below
an example of using the custom <literal>&lt;dateformat/&gt;</literal> element developed in the
previous steps in a Spring XML configuration file.</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:myns="http://www.mycompany.com/schema/myns"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd">
]]><lineannotation>&lt;!-- as a top-level bean --&gt;</lineannotation><![CDATA[
<myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/>
<bean id="jobDetailTemplate" abstract="true">
<property name="dateFormat">
]]><lineannotation>&lt;!-- as an inner bean --&gt;</lineannotation><![CDATA[
<myns:dateformat pattern="HH:mm MM-dd-yyyy"/>
</property>
</bean>
</beans>]]></programlisting>
</section>
<section xml:id="extensible-xml-meat">
<title>Meatier examples</title>
<para>Find below some much meatier examples of custom XML extensions.</para>
<section xml:id="extensible-xml-custom-nested">
<title>Nesting custom tags within custom tags</title>
<para>This example illustrates how you might go about writing the various artifacts
required to satisfy a target of the following configuration:</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo="http://www.foo.com/schema/component"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.foo.com/schema/component http://www.foo.com/schema/component/component.xsd">
]]><lineannotation><![CDATA[<foo:component id="bionic-family" name="Bionic-1">
<foo:component name="Mother-1">
<foo:component name="Karate-1"/>
<foo:component name="Sport-1"/>
</foo:component>
<foo:component name="Rock-1"/>
</foo:component>]]></lineannotation><![CDATA[
</beans>]]></programlisting>
<para>The above configuration actually nests custom extensions within each other. The class
that is actually configured by the above <literal>&lt;foo:component/&gt;</literal>
element is the <classname>Component</classname> class (shown directly below). Notice
how the <classname>Component</classname> class does <emphasis>not</emphasis> expose
a setter method for the <literal>'components'</literal> property; this makes it hard
(or rather impossible) to configure a bean definition for the <classname>Component</classname>
class using setter injection.</para>
<programlisting language="java"><![CDATA[package com.foo;
import java.util.ArrayList;
import java.util.List;
public class Component {
private String name;
private List<Component> components = new ArrayList<Component> ();
]]><lineannotation>// mmm, there is no setter method for the 'components'</lineannotation><![CDATA[
public void addComponent(Component component) {
this.components.add(component);
}
public List<Component> getComponents() {
return components;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}]]></programlisting>
<para>The typical solution to this issue is to create a custom <interfacename>FactoryBean</interfacename>
that exposes a setter property for the <literal>'components'</literal> property.</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.springframework.beans.factory.FactoryBean;
import java.util.List;
public class ComponentFactoryBean implements FactoryBean<Component> {
private Component parent;
private List<Component> children;
public void setParent(Component parent) {
this.parent = parent;
}
public void setChildren(List<Component> children) {
this.children = children;
}
public Component getObject() throws Exception {
if (this.children != null && this.children.size() > 0) {
for (Component child : children) {
this.parent.addComponent(child);
}
}
return this.parent;
}
public Class<Component> getObjectType() {
return Component.class;
}
public boolean isSingleton() {
return true;
}
}]]></programlisting>
<para>This is all very well, and does work nicely, but exposes a lot of Spring plumbing to the
end user. What we are going to do is write a custom extension that hides away all of this
Spring plumbing. If we stick to <link linkend="extensible-xml-introduction">the steps described
previously</link>, we'll start off by creating the XSD schema to define the structure of
our custom tag.</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.foo.com/schema/component"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/component"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:element name="component">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="component"/>
</xsd:choice>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="name" use="required" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
]]></programlisting>
<para>We'll then create a custom <interfacename>NamespaceHandler</interfacename>.</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class ComponentNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser());
}
}]]></programlisting>
<para>Next up is the custom <interfacename>BeanDefinitionParser</interfacename>. Remember
that what we are creating is a <interfacename>BeanDefinition</interfacename> describing
a <classname>ComponentFactoryBean</classname>.</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import java.util.List;
public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser {
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
return parseComponentElement(element);
}
private static AbstractBeanDefinition parseComponentElement(Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);
factory.addPropertyValue("parent", parseComponent(element));
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "component");
if (childElements != null && childElements.size() > 0) {
parseChildComponents(childElements, factory);
}
return factory.getBeanDefinition();
}
private static BeanDefinition parseComponent(Element element) {
BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class);
component.addPropertyValue("name", element.getAttribute("name"));
return component.getBeanDefinition();
}
private static void parseChildComponents(List<Element> childElements, BeanDefinitionBuilder factory) {
ManagedList<BeanDefinition> children = new ManagedList<BeanDefinition>(childElements.size());
for (Element element : childElements) {
children.add(parseComponentElement(element));
}
factory.addPropertyValue("children", children);
}
}]]></programlisting>
<para>Lastly, the various artifacts need to be registered with the Spring XML infrastructure.</para>
<programlisting><lineannotation># in 'META-INF/spring.handlers'</lineannotation><![CDATA[
http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler]]></programlisting>
<programlisting><lineannotation># in 'META-INF/spring.schemas'</lineannotation><![CDATA[
http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd]]></programlisting>
</section>
<section xml:id="extensible-xml-custom-just-attributes">
<title>Custom attributes on 'normal' elements</title>
<para>Writing your own custom parser and the associated artifacts isn't hard, but sometimes it
is not the right thing to do. Consider the scenario where you need to add metadata to already
existing bean definitions. In this case you certainly don't want to have to go off and write
your own entire custom extension; rather you just want to add an additional attribute
to the existing bean definition element.</para>
<para>By way of another example, let's say that the service class that you are defining a bean
definition for a service object that will (unknown to it) be accessing a clustered
<link xl:href="http://jcp.org/en/jsr/detail?id=107">JCache</link>, and you want to ensure that
the named JCache instance is eagerly started within the surrounding cluster:</para>
<programlisting language="xml"><![CDATA[<bean id="checkingAccountService" class="com.foo.DefaultCheckingAccountService"
]]><lineannotation>jcache:cache-name="checking.account"&gt;</lineannotation><![CDATA[
]]><lineannotation>&lt;!-- other dependencies here... --&gt;</lineannotation><![CDATA[
</bean>]]></programlisting>
<para>What we are going to do here is create another <interfacename>BeanDefinition</interfacename>
when the <literal>'jcache:cache-name'</literal> attribute is parsed; this
<interfacename>BeanDefinition</interfacename> will then initialize the named JCache
for us. We will also modify the existing <interfacename>BeanDefinition</interfacename> for the
<literal>'checkingAccountService'</literal> so that it will have a dependency on this
new JCache-initializing <interfacename>BeanDefinition</interfacename>.</para>
<programlisting language="java"><![CDATA[package com.foo;
public class JCacheInitializer {
private String name;
public JCacheInitializer(String name) {
this.name = name;
}
public void initialize() {
]]><lineannotation>// lots of JCache API calls to initialize the named cache...</lineannotation><![CDATA[
}
}]]></programlisting>
<para>Now onto the custom extension. Firstly, the authoring of the XSD schema describing the
custom attribute (quite easy in this case).</para>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.foo.com/schema/jcache"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/jcache"
elementFormDefault="qualified">
<xsd:attribute name="cache-name" type="xsd:string"/>
</xsd:schema>
]]></programlisting>
<para>Next, the associated <interfacename>NamespaceHandler</interfacename>.</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class JCacheNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
super.registerBeanDefinitionDecoratorForAttribute("cache-name",
new JCacheInitializingBeanDefinitionDecorator());
}
}
]]></programlisting>
<para>Next, the parser. Note that in this case, because we are going to be parsing an XML
attribute, we write a <interfacename>BeanDefinitionDecorator</interfacename> rather than a
<interfacename>BeanDefinitionParser</interfacename>.</para>
<programlisting language="java"><![CDATA[package com.foo;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class JCacheInitializingBeanDefinitionDecorator implements BeanDefinitionDecorator {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
public BeanDefinitionHolder decorate(
Node source, BeanDefinitionHolder holder, ParserContext ctx) {
String initializerBeanName = registerJCacheInitializer(source, ctx);
createDependencyOnJCacheInitializer(holder, initializerBeanName);
return holder;
}
private void createDependencyOnJCacheInitializer(BeanDefinitionHolder holder, String initializerBeanName) {
AbstractBeanDefinition definition = ((AbstractBeanDefinition) holder.getBeanDefinition());
String[] dependsOn = definition.getDependsOn();
if (dependsOn == null) {
dependsOn = new String[]{initializerBeanName};
} else {
List dependencies = new ArrayList(Arrays.asList(dependsOn));
dependencies.add(initializerBeanName);
dependsOn = (String[]) dependencies.toArray(EMPTY_STRING_ARRAY);
}
definition.setDependsOn(dependsOn);
}
private String registerJCacheInitializer(Node source, ParserContext ctx) {
String cacheName = ((Attr) source).getValue();
String beanName = cacheName + "-initializer";
if (!ctx.getRegistry().containsBeanDefinition(beanName)) {
BeanDefinitionBuilder initializer = BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class);
initializer.addConstructorArg(cacheName);
ctx.getRegistry().registerBeanDefinition(beanName, initializer.getBeanDefinition());
}
return beanName;
}
}
]]></programlisting>
<para>Lastly, the various artifacts need to be registered with the Spring XML infrastructure.</para>
<programlisting><lineannotation># in 'META-INF/spring.handlers'</lineannotation><![CDATA[
http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler]]></programlisting>
<programlisting><lineannotation># in 'META-INF/spring.schemas'</lineannotation><![CDATA[
http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd]]></programlisting>
</section>
</section>
<section xml:id="extensible-xml-resources">
<title>Further Resources</title>
<para>Find below links to further resources concerning XML Schema and the extensible XML support
described in this chapter.</para>
<itemizedlist>
<listitem>
<para>The <link xl:href="http://www.w3.org/TR/2004/REC-xmlschema-1-20041028/">XML Schema Part 1: Structures Second Edition</link></para>
</listitem>
<listitem>
<para>The <link xl:href="http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/">XML Schema Part 2: Datatypes Second Edition</link></para>
</listitem>
</itemizedlist>
</section>
</appendix>

File diff suppressed because it is too large Load Diff