diff --git a/spring-framework-reference/build.xml b/spring-framework-reference/build.xml
new file mode 100644
index 00000000000..46d851c1729
--- /dev/null
+++ b/spring-framework-reference/build.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/css/html/stylesheet.css b/spring-framework-reference/css/html/stylesheet.css
new file mode 100644
index 00000000000..54e4ba762ca
--- /dev/null
+++ b/spring-framework-reference/css/html/stylesheet.css
@@ -0,0 +1,56 @@
+html {
+ padding: 0pt;
+ margin: 0pt;
+}
+
+body {
+ margin-left: 10%;
+ margin-right: 10%;
+ font-family: Arial, Sans-serif;
+}
+
+div {
+ margin: 0pt;
+}
+
+p {
+ text-align: justify;
+}
+
+hr {
+ border: 1px solid gray;
+ background: gray;
+}
+
+h1,h2,h3 {
+ color: #234623;
+ font-family: Arial, Sans-serif;
+}
+
+pre {
+ line-height: 1.0;
+ color: black;
+}
+
+pre.programlisting {
+ font-size: 10pt;
+ padding: 7pt 3pt;
+ border: 1pt solid black;
+ background: #eeeeee;
+}
+
+div.table {
+ margin: 1em;
+ padding: 0.5em;
+ text-align: center;
+}
+
+div.table table {
+ display: table;
+ width: 100%;
+}
+
+div.table td {
+ padding-left: 7px;
+ padding-right: 7px;
+}
diff --git a/spring-framework-reference/images/DataAccessException.gif b/spring-framework-reference/images/DataAccessException.gif
new file mode 100644
index 00000000000..ece7393f33f
Binary files /dev/null and b/spring-framework-reference/images/DataAccessException.gif differ
diff --git a/spring-framework-reference/images/aop-proxy-call.png b/spring-framework-reference/images/aop-proxy-call.png
new file mode 100644
index 00000000000..af7b42f8ca8
Binary files /dev/null and b/spring-framework-reference/images/aop-proxy-call.png differ
diff --git a/spring-framework-reference/images/aop-proxy-plain-pojo-call.png b/spring-framework-reference/images/aop-proxy-plain-pojo-call.png
new file mode 100644
index 00000000000..2f7585d23f8
Binary files /dev/null and b/spring-framework-reference/images/aop-proxy-plain-pojo-call.png differ
diff --git a/spring-framework-reference/images/aop-uml.gif b/spring-framework-reference/images/aop-uml.gif
new file mode 100644
index 00000000000..09bde26cc7f
Binary files /dev/null and b/spring-framework-reference/images/aop-uml.gif differ
diff --git a/spring-framework-reference/images/banner4.jpg b/spring-framework-reference/images/banner4.jpg
new file mode 100644
index 00000000000..ef33d2aefed
Binary files /dev/null and b/spring-framework-reference/images/banner4.jpg differ
diff --git a/spring-framework-reference/images/bean-lifecycle-overview.gif b/spring-framework-reference/images/bean-lifecycle-overview.gif
new file mode 100644
index 00000000000..a9b21c64af4
Binary files /dev/null and b/spring-framework-reference/images/bean-lifecycle-overview.gif differ
diff --git a/spring-framework-reference/images/bind1.jpg b/spring-framework-reference/images/bind1.jpg
new file mode 100644
index 00000000000..8eed64501b8
Binary files /dev/null and b/spring-framework-reference/images/bind1.jpg differ
diff --git a/spring-framework-reference/images/bind2.jpg b/spring-framework-reference/images/bind2.jpg
new file mode 100644
index 00000000000..be6cdd0ed8c
Binary files /dev/null and b/spring-framework-reference/images/bind2.jpg differ
diff --git a/spring-framework-reference/images/container-magic.png b/spring-framework-reference/images/container-magic.png
new file mode 100644
index 00000000000..2628e59b00e
Binary files /dev/null and b/spring-framework-reference/images/container-magic.png differ
diff --git a/spring-framework-reference/images/eclipse-setup-1.png b/spring-framework-reference/images/eclipse-setup-1.png
new file mode 100644
index 00000000000..5372954d433
Binary files /dev/null and b/spring-framework-reference/images/eclipse-setup-1.png differ
diff --git a/spring-framework-reference/images/eclipse-setup-2.png b/spring-framework-reference/images/eclipse-setup-2.png
new file mode 100644
index 00000000000..332d4df4d58
Binary files /dev/null and b/spring-framework-reference/images/eclipse-setup-2.png differ
diff --git a/spring-framework-reference/images/eclipse-setup-3.png b/spring-framework-reference/images/eclipse-setup-3.png
new file mode 100644
index 00000000000..027df4d5baf
Binary files /dev/null and b/spring-framework-reference/images/eclipse-setup-3.png differ
diff --git a/spring-framework-reference/images/ejb.gif b/spring-framework-reference/images/ejb.gif
new file mode 100644
index 00000000000..5bf168a447c
Binary files /dev/null and b/spring-framework-reference/images/ejb.gif differ
diff --git a/spring-framework-reference/images/ejb.png b/spring-framework-reference/images/ejb.png
new file mode 100644
index 00000000000..106a782e0fd
Binary files /dev/null and b/spring-framework-reference/images/ejb.png differ
diff --git a/spring-framework-reference/images/ejb.svg b/spring-framework-reference/images/ejb.svg
new file mode 100644
index 00000000000..d8b275784a3
--- /dev/null
+++ b/spring-framework-reference/images/ejb.svg
@@ -0,0 +1,95 @@
+
+
+
+
diff --git a/spring-framework-reference/images/full.gif b/spring-framework-reference/images/full.gif
new file mode 100644
index 00000000000..5c0126c55fa
Binary files /dev/null and b/spring-framework-reference/images/full.gif differ
diff --git a/spring-framework-reference/images/full.png b/spring-framework-reference/images/full.png
new file mode 100644
index 00000000000..e28ea946e1e
Binary files /dev/null and b/spring-framework-reference/images/full.png differ
diff --git a/spring-framework-reference/images/full.svg b/spring-framework-reference/images/full.svg
new file mode 100644
index 00000000000..31b18f916fa
--- /dev/null
+++ b/spring-framework-reference/images/full.svg
@@ -0,0 +1,254 @@
+
+
+
+
diff --git a/spring-framework-reference/images/html-logo.png b/spring-framework-reference/images/html-logo.png
new file mode 100644
index 00000000000..d69dc105bbd
Binary files /dev/null and b/spring-framework-reference/images/html-logo.png differ
diff --git a/spring-framework-reference/images/idea-setup-1.png b/spring-framework-reference/images/idea-setup-1.png
new file mode 100644
index 00000000000..ceb7fc2b701
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-1.png differ
diff --git a/spring-framework-reference/images/idea-setup-2.png b/spring-framework-reference/images/idea-setup-2.png
new file mode 100644
index 00000000000..a86c3fb945f
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-2.png differ
diff --git a/spring-framework-reference/images/idea-setup-3.png b/spring-framework-reference/images/idea-setup-3.png
new file mode 100644
index 00000000000..bb009d68760
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-3.png differ
diff --git a/spring-framework-reference/images/idea-setup-4.png b/spring-framework-reference/images/idea-setup-4.png
new file mode 100644
index 00000000000..a1402b3e82d
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-4.png differ
diff --git a/spring-framework-reference/images/idea-setup-5.png b/spring-framework-reference/images/idea-setup-5.png
new file mode 100644
index 00000000000..fce7a51e099
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-5.png differ
diff --git a/spring-framework-reference/images/idea-setup-6.png b/spring-framework-reference/images/idea-setup-6.png
new file mode 100644
index 00000000000..0a38d04c077
Binary files /dev/null and b/spring-framework-reference/images/idea-setup-6.png differ
diff --git a/spring-framework-reference/images/logo-pdf.png b/spring-framework-reference/images/logo-pdf.png
new file mode 100644
index 00000000000..5b8acfd2dc6
Binary files /dev/null and b/spring-framework-reference/images/logo-pdf.png differ
diff --git a/spring-framework-reference/images/logo.gif b/spring-framework-reference/images/logo.gif
new file mode 100644
index 00000000000..0f24308619e
Binary files /dev/null and b/spring-framework-reference/images/logo.gif differ
diff --git a/spring-framework-reference/images/logo.jpg b/spring-framework-reference/images/logo.jpg
new file mode 100644
index 00000000000..8a70e6af172
Binary files /dev/null and b/spring-framework-reference/images/logo.jpg differ
diff --git a/spring-framework-reference/images/logo.psd b/spring-framework-reference/images/logo.psd
new file mode 100644
index 00000000000..d1f337ee475
Binary files /dev/null and b/spring-framework-reference/images/logo.psd differ
diff --git a/spring-framework-reference/images/logo.xcf b/spring-framework-reference/images/logo.xcf
new file mode 100644
index 00000000000..3cc4933ddb1
Binary files /dev/null and b/spring-framework-reference/images/logo.xcf differ
diff --git a/spring-framework-reference/images/mvc-contexts.gif b/spring-framework-reference/images/mvc-contexts.gif
new file mode 100644
index 00000000000..15b28d0d39a
Binary files /dev/null and b/spring-framework-reference/images/mvc-contexts.gif differ
diff --git a/spring-framework-reference/images/mvc.png b/spring-framework-reference/images/mvc.png
new file mode 100644
index 00000000000..b8f5675c63c
Binary files /dev/null and b/spring-framework-reference/images/mvc.png differ
diff --git a/spring-framework-reference/images/pdf-logo.png b/spring-framework-reference/images/pdf-logo.png
new file mode 100644
index 00000000000..845b835eb0e
Binary files /dev/null and b/spring-framework-reference/images/pdf-logo.png differ
diff --git a/spring-framework-reference/images/prototype.png b/spring-framework-reference/images/prototype.png
new file mode 100644
index 00000000000..c88bdacdac9
Binary files /dev/null and b/spring-framework-reference/images/prototype.png differ
diff --git a/spring-framework-reference/images/remoting.gif b/spring-framework-reference/images/remoting.gif
new file mode 100644
index 00000000000..b8f0ec10bc0
Binary files /dev/null and b/spring-framework-reference/images/remoting.gif differ
diff --git a/spring-framework-reference/images/remoting.png b/spring-framework-reference/images/remoting.png
new file mode 100644
index 00000000000..4fc8aa6a38b
Binary files /dev/null and b/spring-framework-reference/images/remoting.png differ
diff --git a/spring-framework-reference/images/remoting.svg b/spring-framework-reference/images/remoting.svg
new file mode 100644
index 00000000000..2b2d59337bd
--- /dev/null
+++ b/spring-framework-reference/images/remoting.svg
@@ -0,0 +1,143 @@
+
+
+
+
diff --git a/spring-framework-reference/images/singleton.png b/spring-framework-reference/images/singleton.png
new file mode 100644
index 00000000000..3008c040df5
Binary files /dev/null and b/spring-framework-reference/images/singleton.png differ
diff --git a/spring-framework-reference/images/spring-overview.gif b/spring-framework-reference/images/spring-overview.gif
new file mode 100644
index 00000000000..61545ff1ebc
Binary files /dev/null and b/spring-framework-reference/images/spring-overview.gif differ
diff --git a/spring-framework-reference/images/spring-overview.png b/spring-framework-reference/images/spring-overview.png
new file mode 100644
index 00000000000..f5aac2d1a85
Binary files /dev/null and b/spring-framework-reference/images/spring-overview.png differ
diff --git a/spring-framework-reference/images/spring-overview.svg b/spring-framework-reference/images/spring-overview.svg
new file mode 100644
index 00000000000..dc5f41612fc
--- /dev/null
+++ b/spring-framework-reference/images/spring-overview.svg
@@ -0,0 +1,198 @@
+
+
+
+
diff --git a/spring-framework-reference/images/spring-overview.vsd b/spring-framework-reference/images/spring-overview.vsd
new file mode 100644
index 00000000000..8ac8620a90f
Binary files /dev/null and b/spring-framework-reference/images/spring-overview.vsd differ
diff --git a/spring-framework-reference/images/spring.sxd b/spring-framework-reference/images/spring.sxd
new file mode 100644
index 00000000000..40c1a9e42d9
Binary files /dev/null and b/spring-framework-reference/images/spring.sxd differ
diff --git a/spring-framework-reference/images/springsource-banner-rhs.png b/spring-framework-reference/images/springsource-banner-rhs.png
new file mode 100644
index 00000000000..a9f6d959e77
Binary files /dev/null and b/spring-framework-reference/images/springsource-banner-rhs.png differ
diff --git a/spring-framework-reference/images/thirdparty-web.gif b/spring-framework-reference/images/thirdparty-web.gif
new file mode 100644
index 00000000000..061ab1ba37c
Binary files /dev/null and b/spring-framework-reference/images/thirdparty-web.gif differ
diff --git a/spring-framework-reference/images/thirdparty-web.png b/spring-framework-reference/images/thirdparty-web.png
new file mode 100644
index 00000000000..5dcb84bbd0e
Binary files /dev/null and b/spring-framework-reference/images/thirdparty-web.png differ
diff --git a/spring-framework-reference/images/thirdparty-web.svg b/spring-framework-reference/images/thirdparty-web.svg
new file mode 100644
index 00000000000..a3966dbefb9
--- /dev/null
+++ b/spring-framework-reference/images/thirdparty-web.svg
@@ -0,0 +1,131 @@
+
+
+
+
diff --git a/spring-framework-reference/images/tx.png b/spring-framework-reference/images/tx.png
new file mode 100644
index 00000000000..06f2e77c76f
Binary files /dev/null and b/spring-framework-reference/images/tx.png differ
diff --git a/spring-framework-reference/images/tx_prop_required.png b/spring-framework-reference/images/tx_prop_required.png
new file mode 100644
index 00000000000..218790aca63
Binary files /dev/null and b/spring-framework-reference/images/tx_prop_required.png differ
diff --git a/spring-framework-reference/images/tx_prop_requires_new.png b/spring-framework-reference/images/tx_prop_requires_new.png
new file mode 100644
index 00000000000..a8ece48193f
Binary files /dev/null and b/spring-framework-reference/images/tx_prop_requires_new.png differ
diff --git a/spring-framework-reference/images/xdev-spring_logo.jpg b/spring-framework-reference/images/xdev-spring_logo.jpg
new file mode 100644
index 00000000000..622962ee3c8
Binary files /dev/null and b/spring-framework-reference/images/xdev-spring_logo.jpg differ
diff --git a/spring-framework-reference/src/aop-api.xml b/spring-framework-reference/src/aop-api.xml
new file mode 100644
index 00000000000..1225181c839
--- /dev/null
+++ b/spring-framework-reference/src/aop-api.xml
@@ -0,0 +1,1956 @@
+
+
+ Spring AOP APIs
+
+
+ Introduction
+
+ The previous chapter described the Spring 2.0 support for AOP using
+ @AspectJ and schema-based aspect definitions. In this chapter we discuss
+ the lower-level Spring AOP APIs and the AOP support used in Spring 1.2 applications.
+ For new applications, we recommend the use of the Spring 2.0 AOP support
+ described in the previous chapter, but when working with existing applications,
+ or when reading books and articles, you may come across Spring 1.2 style examples.
+ Spring 2.0 is fully backwards compatible with Spring 1.2 and everything described
+ in this chapter is fully supported in Spring 2.0.
+
+
+
+
+
+ Pointcut API in Spring
+
+ Let's look at how Spring handles the crucial pointcut concept.
+
+
+ Concepts
+
+ Spring's pointcut model enables pointcut reuse independent of
+ advice types. It's possible to target different advice using the same
+ pointcut.
+
+ The org.springframework.aop.Pointcut interface
+ is the central interface, used to target advices to particular classes
+ and methods. The complete interface is shown below:
+
+
+
+ Splitting the Pointcut interface into two parts
+ allows reuse of class and method matching parts, and fine-grained
+ composition operations (such as performing a "union" with another method
+ matcher).
+
+ The ClassFilter interface is used to restrict
+ the pointcut to a given set of target classes. If the
+ matches() method always returns true, all target
+ classes will be matched:
+
+
+
+ The MethodMatcher interface is normally more
+ important. The complete interface is shown below:
+
+
+
+ The matches(Method, Class) method is used to
+ test whether this pointcut will ever match a given method on a target
+ class. This evaluation can be performed when an AOP proxy is created, to
+ avoid the need for a test on every method invocation. If the 2-argument
+ matches method returns true for a given method, and the
+ isRuntime() method for the MethodMatcher returns
+ true, the 3-argument matches method will be invoked on every method
+ invocation. This enables a pointcut to look at the arguments passed to
+ the method invocation immediately before the target advice is to
+ execute.
+
+ Most MethodMatchers are static, meaning that their
+ isRuntime() method returns false. In this case, the
+ 3-argument matches method will never be invoked.
+
+
+ If possible, try to make pointcuts static, allowing the AOP
+ framework to cache the results of pointcut evaluation when an AOP proxy
+ is created.
+
+
+
+
+ Operations on pointcuts
+
+ Spring supports operations on pointcuts: notably,
+ union and intersection.
+
+
+
+ Union means the methods that either pointcut matches.
+
+
+ Intersection means the methods that both pointcuts match.
+
+
+ Union is usually more useful.
+
+
+ Pointcuts can be composed using the static methods in the
+ org.springframework.aop.support.Pointcuts class, or
+ using the ComposablePointcut class in the same
+ package. However, using AspectJ pointcut expressions is usually a
+ simpler approach.
+
+
+
+
+
+
+ AspectJ expression pointcuts
+
+ Since 2.0, the most important type of pointcut used by Spring is
+ org.springframework.aop.aspectj.AspectJExpressionPointcut.
+ This is a pointcut that uses an AspectJ supplied library to parse an AspectJ
+ pointcut expression string.
+
+ See the previous chapter for a discussion of supported AspectJ pointcut
+ primitives.
+
+
+
+
+ Convenience pointcut implementations
+
+ Spring provides several convenient pointcut implementations. Some
+ can be used out of the box; others are intended to be subclassed in
+ application-specific pointcuts.
+
+
+ Static pointcuts
+
+ Static pointcuts are based on method and target class, and
+ cannot take into account the method's arguments. Static pointcuts are
+ sufficient - and best - for most usages. It's possible for Spring to
+ evaluate a static pointcut only once, when a method is first invoked:
+ after that, there is no need to evaluate the pointcut again with each
+ method invocation.
+
+ Let's consider some static pointcut implementations included
+ with Spring.
+
+
+ Regular expression pointcuts
+
+ One obvious way to specify static pointcuts is regular
+ expressions. Several AOP frameworks besides Spring make this
+ possible.
+ org.springframework.aop.support.Perl5RegexpMethodPointcut
+ is a generic regular expression pointcut, using Perl 5 regular
+ expression syntax. The Perl5RegexpMethodPointcut
+ class depends on Jakarta ORO for regular expression matching. Spring
+ also provides the JdkRegexpMethodPointcut class
+ that uses the regular expression support in JDK 1.4+.
+
+ Using the Perl5RegexpMethodPointcut class,
+ you can provide a list of pattern Strings. If any of these is a
+ match, the pointcut will evaluate to true. (So the result is
+ effectively the union of these pointcuts.)
+
+ The usage is shown below:
+
+ <bean id="settersAndAbsquatulatePointcut"
+ class="org.springframework.aop.support.Perl5RegexpMethodPointcut">
+ <property name="patterns">
+ <list>
+ <value>.*set.*</value>
+ <value>.*absquatulate</value>
+ </list>
+ </property>
+</bean>
+
+ Spring provides a convenience class,
+ RegexpMethodPointcutAdvisor, that allows us to
+ also reference an Advice (remember that an Advice can be an
+ interceptor, before advice, throws advice etc.). Behind the scenes,
+ Spring will use a JdkRegexpMethodPointcut. Using
+ RegexpMethodPointcutAdvisor simplifies wiring,
+ as the one bean encapsulates both pointcut and advice, as shown
+ below:
+
+ <bean id="settersAndAbsquatulateAdvisor"
+ class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
+ <property name="advice">
+ <ref local="beanNameOfAopAllianceInterceptor"/>
+ </property>
+ <property name="patterns">
+ <list>
+ <value>.*set.*</value>
+ <value>.*absquatulate</value>
+ </list>
+ </property>
+</bean>
+
+ RegexpMethodPointcutAdvisor can be used
+ with any Advice type.
+
+
+
+ Attribute-driven pointcuts
+
+ An important type of static pointcut is a
+ metadata-driven pointcut. This uses the values
+ of metadata attributes: typically, source-level metadata.
+
+
+
+
+ Dynamic pointcuts
+
+ Dynamic pointcuts are costlier to evaluate than static
+ pointcuts. They take into account method
+ arguments, as well as static information. This
+ means that they must be evaluated with every method invocation; the
+ result cannot be cached, as arguments will vary.
+
+ The main example is the control flow
+ pointcut.
+
+
+ Control flow pointcuts
+
+ Spring control flow pointcuts are conceptually similar to
+ AspectJ cflow pointcuts, although less
+ powerful. (There is currently no way to specify that a pointcut
+ executes below a join point matched by another pointcut.)
+ A control flow pointcut matches
+ the current call stack. For example, it might fire if the join point
+ was invoked by a method in the com.mycompany.web
+ package, or by the SomeCaller class. Control flow
+ pointcuts are specified using the
+ org.springframework.aop.support.ControlFlowPointcut
+ class.
+ Control flow pointcuts are significantly more expensive to
+ evaluate at runtime than even other dynamic pointcuts. In Java 1.4,
+ the cost is about 5 times that of other dynamic pointcuts.
+
+
+
+
+
+
+ Pointcut superclasses
+
+ Spring provides useful pointcut superclasses to help you to
+ implement your own pointcuts.
+
+ Because static pointcuts are most useful, you'll probably subclass
+ StaticMethodMatcherPointcut, as shown below. This requires implementing
+ just one abstract method (although it's possible to override other
+ methods to customize behavior):
+
+ class TestStaticPointcut extends StaticMethodMatcherPointcut {
+
+ public boolean matches(Method m, Class targetClass) {
+ // return true if custom criteria match
+ }
+}There are also superclasses for dynamic pointcuts.
+
+ You can use custom pointcuts with any advice type in Spring 1.0
+ RC2 and above.
+
+
+
+ Custom pointcuts
+
+ Because pointcuts in Spring AOP are Java classes, rather than
+ language features (as in AspectJ) it's possible to declare custom
+ pointcuts, whether static or dynamic. Custom pointcuts in Spring can be
+ arbitrarily complex. However, using the AspectJ pointcut expression
+ language is recommended if possible.
+
+
+ Later versions of Spring may offer support for "semantic
+ pointcuts" as offered by JAC: for example, "all methods that change
+ instance variables in the target object."
+
+
+
+
+
+ Advice API in Spring
+
+ Let's now look at how Spring AOP handles advice.
+
+
+ Advice lifecycles
+
+ Each advice is a Spring bean. An advice instance can be shared across all
+ advised objects, or unique
+ to each advised object. This corresponds to
+ per-class or per-instance
+ advice.
+
+ Per-class advice is used most often. It is appropriate for generic
+ advice such as transaction advisors. These do not depend on the state of
+ the proxied object or add new state; they merely act on the method and
+ arguments.
+
+ Per-instance advice is appropriate for introductions, to support
+ mixins. In this case, the advice adds state to the proxied
+ object.
+
+ It's possible to use a mix of shared and per-instance advice in
+ the same AOP proxy.
+
+
+
+ Advice types in Spring
+
+ Spring provides several advice types out of the box, and is
+ extensible to support arbitrary advice types. Let us look at the basic
+ concepts and standard advice types.
+
+
+ Interception around advice
+
+ The most fundamental advice type in Spring is
+ interception around advice.
+
+ Spring is compliant with the AOP Alliance interface for around
+ advice using method interception. MethodInterceptors implementing
+ around advice should implement the following interface:
+
+ public interface MethodInterceptor extends Interceptor {
+
+ Object invoke(MethodInvocation invocation) throws Throwable;
+}
+
+ The MethodInvocation argument to the
+ invoke() method exposes the method being invoked;
+ the target join point; the AOP proxy; and the arguments to the method.
+ The invoke() method should return the
+ invocation's result: the return value of the join point.
+
+ A simple MethodInterceptor implementation
+ looks as follows:
+
+ public class DebugInterceptor implements MethodInterceptor {
+
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ System.out.println("Before: invocation=[" + invocation + "]");
+ Object rval = invocation.proceed();
+ System.out.println("Invocation returned");
+ return rval;
+ }
+}
+
+ Note the call to the MethodInvocation's
+ proceed() method. This proceeds down the
+ interceptor chain towards the join point. Most interceptors will invoke
+ this method, and return its return value. However, a
+ MethodInterceptor, like any around advice, can return a different
+ value or throw an exception rather than invoke the proceed method.
+ However, you don't want to do this without good reason!
+
+ MethodInterceptors offer interoperability with other AOP
+ Alliance-compliant AOP implementations. The other advice types
+ discussed in the remainder of this section implement common AOP
+ concepts, but in a Spring-specific way. While there is an advantage in
+ using the most specific advice type, stick with MethodInterceptor
+ around advice if you are likely to want to run the aspect in another
+ AOP framework. Note that pointcuts are not currently interoperable
+ between frameworks, and the AOP Alliance does not currently define
+ pointcut interfaces.
+
+
+
+ Before advice
+
+ A simpler advice type is a before
+ advice. This does not need a
+ MethodInvocation object, since it will only be
+ called before entering the method.
+
+ The main advantage of a before advice is that there is no need
+ to invoke the proceed() method, and therefore no
+ possibility of inadvertently failing to proceed down the interceptor
+ chain.
+
+ The MethodBeforeAdvice interface is shown
+ below. (Spring's API design would allow for field before advice,
+ although the usual objects apply to field interception and it's
+ unlikely that Spring will ever implement it).
+
+ public interface MethodBeforeAdvice extends BeforeAdvice {
+
+ void before(Method m, Object[] args, Object target) throws Throwable;
+}
+
+ Note the return type is void. Before
+ advice can insert custom behavior before the join point executes, but
+ cannot change the return value. If a before advice throws an
+ exception, this will abort further execution of the interceptor chain.
+ The exception will propagate back up the interceptor chain. If it is
+ unchecked, or on the signature of the invoked method, it will be
+ passed directly to the client; otherwise it will be wrapped in an
+ unchecked exception by the AOP proxy.
+
+ An example of a before advice in Spring, which counts all method
+ invocations:
+
+ public class CountingBeforeAdvice implements MethodBeforeAdvice {
+
+ private int count;
+
+ public void before(Method m, Object[] args, Object target) throws Throwable {
+ ++count;
+ }
+
+ public int getCount() {
+ return count;
+ }
+}
+
+ Before advice can be used with any pointcut.
+
+
+
+ Throws advice
+
+ Throws advice is invoked after
+ the return of the join point if the join point threw an exception.
+ Spring offers typed throws advice. Note that this means that the
+ org.springframework.aop.ThrowsAdvice interface does
+ not contain any methods: It is a tag interface identifying that the
+ given object implements one or more typed throws advice methods. These
+ should be in the form of:
+
+ afterThrowing([Method, args, target], subclassOfThrowable)
+
+ Only the last argument is required. The method signatures may
+ have either one or four arguments, depending on whether the advice
+ method is interested in the method and arguments. The following
+ classes are examples of throws advice.
+
+ The advice below is invoked if a RemoteException
+ is thrown (including subclasses):
+
+ // Do something with remote exception
+
+ The following advice is invoked if a
+ ServletException is thrown. Unlike the above
+ advice, it declares 4 arguments, so that it has access to the invoked
+ method, method arguments and target object:
+
+ // Do something with all arguments
+
+ The final example illustrates how these two methods could be
+ used in a single class, which handles both
+ RemoteException and
+ ServletException. Any number of throws advice
+ methods can be combined in a single class.
+
+ public static class CombinedThrowsAdvice implements ThrowsAdvice {
+
+ public void afterThrowing(RemoteException ex) throws Throwable {
+ // Do something with remote exception
+ }
+
+ public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
+ // Do something with all arguments
+ }
+}
+
+ Note: If a throws-advice method throws an exception itself,
+ it will override the original exception (i.e. change the exception thrown to the user).
+ The overriding exception will typically be a RuntimeException; this is compatible with
+ any method signature. However, if a throws-advice method throws a checked exception,
+ it will have to match the declared exceptions of the target method and is hence to some
+ degree coupled to specific target method signatures. Do not throw an undeclared
+ checked exception that is incompatible with the target method's signature!
+
+ Throws advice can be used with any pointcut.
+
+
+
+ After Returning advice
+
+ An after returning advice in Spring must implement the
+ org.springframework.aop.AfterReturningAdvice
+ interface, shown below:
+
+ public interface AfterReturningAdvice extends Advice {
+
+ void afterReturning(Object returnValue, Method m, Object[] args, Object target)
+ throws Throwable;
+}
+
+ An after returning advice has access to the return value (which
+ it cannot modify), invoked method, methods arguments and
+ target.
+
+ The following after returning advice counts all successful
+ method invocations that have not thrown exceptions:
+
+ public class CountingAfterReturningAdvice implements AfterReturningAdvice {
+
+ private int count;
+
+ public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
+ throws Throwable {
+ ++count;
+ }
+
+ public int getCount() {
+ return count;
+ }
+}
+
+ This advice doesn't change the execution path. If it throws an
+ exception, this will be thrown up the interceptor chain instead of the
+ return value.
+
+ After returning advice can be used with any pointcut.
+
+
+
+ Introduction advice
+ Spring treats introduction advice as a special kind of
+ interception advice.
+ Introduction requires an IntroductionAdvisor,
+ and an IntroductionInterceptor, implementing the
+ following interface:
+
+ public interface IntroductionInterceptor extends MethodInterceptor {
+
+ boolean implementsInterface(Class intf);
+}
+
+ The invoke() method inherited from the AOP
+ Alliance MethodInterceptor interface must implement
+ the introduction: that is, if the invoked method is on an introduced
+ interface, the introduction interceptor is responsible for handling
+ the method call - it cannot invoke proceed().
+
+
+
+ Introduction advice cannot be used with any pointcut, as it
+ applies only at class, rather than method, level. You can only use
+ introduction advice with the IntroductionAdvisor,
+ which has the following methods:
+
+
+
+ public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
+
+ ClassFilter getClassFilter();
+
+ void validateInterfaces() throws IllegalArgumentException;
+}
+
+public interface IntroductionInfo {
+
+ Class[] getInterfaces();
+}
+
+
+
+ There is no MethodMatcher, and hence no
+ Pointcut, associated with introduction advice. Only
+ class filtering is logical.
+
+
+
+ The getInterfaces() method returns the
+ interfaces introduced by this advisor.
+
+ The
+
+ validateInterfaces()
+
+ method is used internally to see whether or not the introduced interfaces can be implemented by the configured
+
+ IntroductionInterceptor
+
+ .
+
+ Let's look at a simple example from the Spring test suite. Let's
+ suppose we want to introduce the following interface to one or more
+ objects:
+
+
+
+
+ public interface Lockable {
+ void lock();
+ void unlock();
+ boolean locked();
+}
+
+
+
+
+ This illustrates a mixin. We
+ want to be able to cast advised objects to Lockable, whatever their
+ type, and call lock and unlock methods. If we call the lock() method,
+ we want all setter methods to throw a
+ LockedException. Thus we can add an aspect that
+ provides the ability to make objects immutable, without them having
+ any knowledge of it: a good example of AOP.
+
+
+
+ Firstly, we'll need an
+ IntroductionInterceptor that does the heavy
+ lifting. In this case, we extend the
+ org.springframework.aop.support.DelegatingIntroductionInterceptor
+ convenience class. We could implement IntroductionInterceptor
+ directly, but using
+ DelegatingIntroductionInterceptor is best for most
+ cases.
+
+
+
+ The DelegatingIntroductionInterceptor is
+ designed to delegate an introduction to an actual implementation of
+ the introduced interface(s), concealing the use of interception to do
+ so. The delegate can be set to any object using a constructor
+ argument; the default delegate (when the no-arg constructor is used)
+ is this. Thus in the example below, the delegate is the
+ LockMixin subclass of
+ DelegatingIntroductionInterceptor. Given a delegate
+ (by default itself), a
+ DelegatingIntroductionInterceptor instance looks
+ for all interfaces implemented by the delegate (other than
+ IntroductionInterceptor), and will support introductions against any
+ of them. It's possible for subclasses such as
+ LockMixin to call the
+ suppressInterface(Class intf) method to suppress
+ interfaces that should not be exposed. However, no matter how many
+ interfaces an IntroductionInterceptor is prepared
+ to support, the IntroductionAdvisor used will
+ control which interfaces are actually exposed. An introduced interface
+ will conceal any implementation of the same interface by the
+ target.
+
+
+
+ Thus LockMixin subclasses
+ DelegatingIntroductionInterceptor and implements
+ Lockable itself. The superclass automatically picks up that Lockable
+ can be supported for introduction, so we don't need to specify that.
+ We could introduce any number of interfaces in this way.
+
+
+
+ Note the use of the locked instance variable.
+ This effectively adds additional state to that held in the target
+ object.
+
+
+
+
+ public class LockMixin extends DelegatingIntroductionInterceptor
+ implements Lockable {
+
+ private boolean locked;
+
+ public void lock() {
+ this.locked = true;
+ }
+
+ public void unlock() {
+ this.locked = false;
+ }
+
+ public boolean locked() {
+ return this.locked;
+ }
+
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
+ throw new LockedException();
+ return super.invoke(invocation);
+ }
+
+}
+
+
+
+
+ Often it isn't necessary to override the invoke()
+ method: the
+ DelegatingIntroductionInterceptor
+ implementation - which calls the delegate method if the method is
+ introduced, otherwise proceeds towards the join point - is usually
+ sufficient. In the present case, we need to add a check: no setter
+ method can be invoked if in locked mode.
+
+
+
+ The introduction advisor required is simple. All it needs to do
+ is hold a distinct LockMixin instance, and specify
+ the introduced interfaces - in this case, just
+ Lockable. A more complex example might take a
+ reference to the introduction interceptor (which would be defined as a
+ prototype): in this case, there's no configuration relevant for a
+ LockMixin, so we simply create it using
+ new.
+
+
+
+
+ public class LockMixinAdvisor extends DefaultIntroductionAdvisor {
+
+ public LockMixinAdvisor() {
+ super(new LockMixin(), Lockable.class);
+ }
+}
+
+
+
+
+ We can apply this advisor very simply: it requires no
+ configuration. (However, it is necessary: It's
+ impossible to use an IntroductionInterceptor
+ without an IntroductionAdvisor.) As usual with
+ introductions, the advisor must be per-instance, as it is stateful. We
+ need a different instance of LockMixinAdvisor, and
+ hence LockMixin, for each advised object. The
+ advisor comprises part of the advised object's state.
+
+
+
+ We can apply this advisor programmatically, using the
+ Advised.addAdvisor() method, or (the recommended
+ way) in XML configuration, like any other advisor. All proxy creation
+ choices discussed below, including "auto proxy creators," correctly
+ handle introductions and stateful mixins.
+
+
+
+
+
+
+
+ Advisor API in Spring
+
+ In Spring, an Advisor is an aspect that contains just a single advice
+ object associated with a pointcut expression.
+
+ Apart from the special case of introductions, any advisor can be
+ used with any advice.
+ org.springframework.aop.support.DefaultPointcutAdvisor
+ is the most commonly used advisor class. For example, it can be used with
+ a MethodInterceptor, BeforeAdvice or
+ ThrowsAdvice.
+
+ It is possible to mix advisor and advice types in Spring in the same
+ AOP proxy. For example, you could use a interception around advice, throws
+ advice and before advice in one proxy configuration: Spring will
+ automatically create the necessary interceptor chain.
+
+
+
+ Using the ProxyFactoryBean to create AOP proxies
+
+ If you're using the Spring IoC container (an ApplicationContext or
+ BeanFactory) for your business objects - and you should be! - you will want
+ to use one of Spring's AOP FactoryBeans. (Remember that a factory bean
+ introduces a layer of indirection, enabling it to create objects of a
+ different type.)
+
+
+ The Spring 2.0 AOP support also uses factory beans under the covers.
+
+
+ The basic way to create an AOP proxy in Spring is to use the
+ org.springframework.aop.framework.ProxyFactoryBean.
+ This gives complete control over the pointcuts and advice that will apply,
+ and their ordering. However, there are simpler options that are preferable
+ if you don't need such control.
+
+
+ Basics
+
+ The ProxyFactoryBean, like other Spring
+ FactoryBean implementations, introduces a level of
+ indirection. If you define a ProxyFactoryBean with
+ name foo, what objects referencing
+ foo see is not the
+ ProxyFactoryBean instance itself, but an object
+ created by the ProxyFactoryBean's implementation of
+ the getObject() method. This method will create an
+ AOP proxy wrapping a target object.
+
+ One of the most important benefits of using a
+ ProxyFactoryBean or another IoC-aware class to create
+ AOP proxies, is that it means that advices and pointcuts can also be
+ managed by IoC. This is a powerful feature, enabling certain approaches
+ that are hard to achieve with other AOP frameworks. For example, an
+ advice may itself reference application objects (besides the target,
+ which should be available in any AOP framework), benefiting from all the
+ pluggability provided by Dependency Injection.
+
+
+
+ JavaBean properties
+
+ In common with most FactoryBean implementations
+ provided with Spring, the ProxyFactoryBean class is
+ itself a JavaBean. Its properties are used to:
+
+
+
+ Specify the target you want to proxy.
+
+
+ Specify whether to use CGLIB (see below and also the section entitled
+ ).
+
+
+
+ Some key properties are inherited from
+ org.springframework.aop.framework.ProxyConfig (the
+ superclass for all AOP proxy factories in Spring). These key properties include:
+
+
+
+
+ proxyTargetClass: true if the
+ target class is to be proxied, rather than the target class' interfaces.
+ If this property value is set to true, then CGLIB proxies
+ will be created (but see also below the section entitled
+ ).
+
+
+
+
+ optimize: controls whether or not aggressive
+ optimizations are applied to proxies created via CGLIB.
+ One should not blithely use this setting unless one fully understands
+ how the relevant AOP proxy handles optimization. This is currently used only
+ for CGLIB proxies; it has no effect with JDK dynamic proxies.
+
+
+
+ frozen: if a proxy configuration is frozen,
+ then changes to the configuration are no longer allowed. This is useful both as
+ a slight optimization and for those cases when you don't want callers to be able
+ to manipulate the proxy (via the Advised interface)
+ after the proxy has been created. The default value of this property is
+ false, so changes such as adding additional advice are allowed.
+
+
+
+ exposeProxy: determines whether or not the current
+ proxy should be exposed in a ThreadLocal so that
+ it can be accessed by the target. If a target needs to obtain
+ the proxy and the exposeProxy property is set to
+ true, the target can use the
+ AopContext.currentProxy() method.
+
+
+
+
+ aopProxyFactory: the implementation of
+ AopProxyFactory to use. Offers a way of
+ customizing whether to use dynamic proxies, CGLIB or any other proxy
+ strategy. The default implementation will choose dynamic proxies or
+ CGLIB appropriately. There should be no need to use this property;
+ it is intended to allow the addition of new proxy types in Spring 1.1.
+
+
+
+
+ Other properties specific to ProxyFactoryBean include:
+
+
+
+
+ proxyInterfaces: array of String interface
+ names. If this isn't supplied, a CGLIB proxy for the target class
+ will be used (but see also below the section entitled
+ ).
+
+
+
+
+ interceptorNames: String array of
+ Advisor, interceptor or other advice
+ names to apply. Ordering is significant, on a first come-first served
+ basis. That is to say that the first interceptor in the list
+ will be the first to be able to intercept the invocation.
+
+
+ The names are bean names in the current factory, including
+ bean names from ancestor factories. You can't mention bean
+ references here since doing so would result in the
+ ProxyFactoryBean ignoring the singleton
+ setting of the advice.
+
+
+ You can append an interceptor name with an asterisk
+ (*). This will result in the application of all
+ advisor beans with names starting with the part before the asterisk
+ to be applied. An example of using this feature can be found in
+ .
+
+
+
+
+ singleton: whether or not the factory should return a single
+ object, no matter how often the getObject()
+ method is called. Several FactoryBean
+ implementations offer such a method. The default value is
+ true. If you want to use stateful advice -
+ for example, for stateful mixins - use prototype advices along
+ with a singleton value of false.
+
+
+
+
+
+
+ JDK- and CGLIB-based proxies
+
+ This section serves as the definitive documentation on how the
+ ProxyFactoryBean chooses to create one of
+ either a JDK- and CGLIB-based proxy for a particular target object
+ (that is to be proxied).
+
+
+
+ The behavior of the ProxyFactoryBean with regard
+ to creating JDK- or CGLIB-based proxies changed between versions 1.2.x and
+ 2.0 of Spring. The ProxyFactoryBean now
+ exhibits similar semantics with regard to auto-detecting interfaces
+ as those of the TransactionProxyFactoryBean class.
+
+
+
+ If the class of a target object that is to be proxied (hereafter simply
+ referred to as the target class) doesn't implement any interfaces, then
+ a CGLIB-based proxy will be created. This is the easiest scenario, because
+ JDK proxies are interface based, and no interfaces means JDK proxying
+ isn't even possible. One simply plugs in the target bean, and specifies the
+ list of interceptors via the interceptorNames property.
+ Note that a CGLIB-based proxy will be created even if the
+ proxyTargetClass property of the
+ ProxyFactoryBean has been set to false.
+ (Obviously this makes no sense, and is best removed from the bean
+ definition because it is at best redundant, and at worst confusing.)
+
+
+ If the target class implements one (or more) interfaces, then the type of
+ proxy that is created depends on the configuration of the
+ ProxyFactoryBean.
+
+
+ If the proxyTargetClass property of the
+ ProxyFactoryBean has been set to true,
+ then a CGLIB-based proxy will be created. This makes sense, and is in
+ keeping with the principle of least surprise. Even if the
+ proxyInterfaces property of the
+ ProxyFactoryBean has been set to one or more
+ fully qualified interface names, the fact that the
+ proxyTargetClass property is set to
+ truewill cause
+ CGLIB-based proxying to be in effect.
+
+
+ If the proxyInterfaces property of the
+ ProxyFactoryBean has been set to one or more
+ fully qualified interface names, then a JDK-based proxy will be created.
+ The created proxy will implement all of the interfaces that were specified
+ in the proxyInterfaces property; if the target class
+ happens to implement a whole lot more interfaces than those specified in
+ the proxyInterfaces property, that is all well and
+ good but those additional interfaces will not be implemented by the
+ returned proxy.
+
+
+ If the proxyInterfaces property of the
+ ProxyFactoryBean has not been
+ set, but the target class does implement one (or more)
+ interfaces, then the ProxyFactoryBean will auto-detect
+ the fact that the target class does actually implement at least one interface,
+ and a JDK-based proxy will be created. The interfaces that are actually
+ proxied will be all of the interfaces that the target
+ class implements; in effect, this is the same as simply supplying a list
+ of each and every interface that the target class implements to the
+ proxyInterfaces property. However, it is significantly less
+ work, and less prone to typos.
+
+
+
+
+
+ Proxying interfaces
+
+
+ Let's look at a simple example of ProxyFactoryBean
+ in action. This example involves:
+
+
+
+
+ A target bean that will be proxied. This
+ is the "personTarget" bean definition in the example below.
+
+
+
+ An Advisor and an Interceptor used to provide advice.
+
+
+
+ An AOP proxy bean definition specifying the target object (the
+ personTarget bean) and the interfaces to proxy, along with the
+ advices to apply.
+
+
+
+ <bean id="personTarget" class="com.mycompany.PersonImpl">
+ <property name="name"><value>Tony</value></property>
+ <property name="age"><value>51</value></property>
+</bean>
+
+<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
+ <property name="someProperty"><value>Custom string property value</value></property>
+</bean>
+
+<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor">
+</bean>
+
+<bean id="person"
+ class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="proxyInterfaces"><value>com.mycompany.Person</value></property>
+
+ <property name="target"><ref local="personTarget"/></property>
+ <property name="interceptorNames">
+ <list>
+ <value>myAdvisor</value>
+ <value>debugInterceptor</value>
+ </list>
+ </property>
+</bean>
+
+ Note that the interceptorNames property takes a
+ list of String: the bean names of the interceptor or advisors in the
+ current factory. Advisors, interceptors, before, after returning and
+ throws advice objects can be used. The ordering of advisors is
+ significant.
+
+
+ You might be wondering why the list doesn't hold bean
+ references. The reason for this is that if the ProxyFactoryBean's
+ singleton property is set to false, it must be able to return
+ independent proxy instances. If any of the advisors is itself a
+ prototype, an independent instance would need to be returned, so it's
+ necessary to be able to obtain an instance of the prototype from the
+ factory; holding a reference isn't sufficient.
+
+
+ The "person" bean definition above can be used in place of a
+ Person implementation, as follows:
+
+ Person person = (Person) factory.getBean("person");
+
+ Other beans in the same IoC context can express a strongly typed
+ dependency on it, as with an ordinary Java object:
+
+ <bean id="personUser" class="com.mycompany.PersonUser">
+ <property name="person"><ref local="person" /></property>
+</bean>
+
+ The PersonUser class in this example would
+ expose a property of type Person. As far as it's concerned, the AOP
+ proxy can be used transparently in place of a "real" person
+ implementation. However, its class would be a dynamic proxy class. It
+ would be possible to cast it to the Advised interface
+ (discussed below).
+
+ It's possible to conceal the distinction between target and proxy
+ using an anonymous inner bean, as follows. Only the
+ ProxyFactoryBean definition is different; the advice
+ is included only for completeness:
+
+ <bean id="myAdvisor" class="com.mycompany.MyAdvisor">
+ <property name="someProperty"><value>Custom string property value</value></property>
+</bean>
+
+<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
+
+<bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="proxyInterfaces"><value>com.mycompany.Person</value></property>
+ <!-- Use inner bean, not local reference to target -->
+ <property name="target">
+ <bean class="com.mycompany.PersonImpl">
+ <property name="name"><value>Tony</value></property>
+ <property name="age"><value>51</value></property>
+ </bean>
+ </property>
+ <property name="interceptorNames">
+ <list>
+ <value>myAdvisor</value>
+ <value>debugInterceptor</value>
+ </list>
+ </property>
+</bean>
+
+ This has the advantage that there's only one object of type
+ Person: useful if we want to prevent users of the
+ application context from obtaining a reference to the un-advised object, or
+ need to avoid any ambiguity with Spring IoC
+ autowiring. There's also arguably an advantage in
+ that the ProxyFactoryBean definition is self-contained. However, there
+ are times when being able to obtain the un-advised target from the
+ factory might actually be an advantage: for
+ example, in certain test scenarios.
+
+
+
+ Proxying classes
+
+ What if you need to proxy a class, rather than one or more
+ interfaces?
+
+ Imagine that in our example above, there was no
+ Person interface: we needed to advise a class called
+ Person that didn't implement any business interface.
+ In this case, you can configure Spring to use CGLIB proxying, rather
+ than dynamic proxies. Simply set the proxyTargetClass
+ property on the ProxyFactoryBean above to true. While it's best to
+ program to interfaces, rather than classes, the ability to advise
+ classes that don't implement interfaces can be useful when working with
+ legacy code. (In general, Spring isn't prescriptive. While it makes it
+ easy to apply good practices, it avoids forcing a particular
+ approach.)
+
+ If you want to, you can force the use of CGLIB in any case, even if
+ you do have interfaces.
+
+ CGLIB proxying works by generating a subclass of the target class
+ at runtime. Spring configures this generated subclass to delegate method
+ calls to the original target: the subclass is used to implement the
+ Decorator pattern, weaving in the advice.
+
+ CGLIB proxying should generally be transparent to users. However,
+ there are some issues to consider:
+
+
+
+ Final methods can't be advised, as they
+ can't be overridden.
+
+
+
+ You'll need the CGLIB 2 binaries on your classpath; dynamic
+ proxies are available with the JDK.
+
+
+
+ There's little performance difference between CGLIB proxying and
+ dynamic proxies. As of Spring 1.0, dynamic proxies are slightly faster.
+ However, this may change in the future. Performance should not be a
+ decisive consideration in this case.
+
+
+
+ Using 'global' advisors
+
+ By appending an asterisk to an interceptor name, all advisors with
+ bean names matching the part before the asterisk, will be added to the
+ advisor chain. This can come in handy if you need to add a standard set
+ of 'global' advisors:
+<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="target" ref="service"/>
+ <property name="interceptorNames">
+ <list>
+ <value>global*</value>
+ </list>
+ </property>
+</bean>
+
+<bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/>
+<bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
+
+
+
+
+
+ Concise proxy definitions
+
+ Especially when defining transactional proxies, you may end up with
+ many similar proxy definitions. The use of parent and child bean
+ definitions, along with inner bean definitions, can result in much cleaner
+ and more concise proxy definitions.
+
+ First a parent, template, bean definition is
+ created for the proxy:
+
+ <bean id="txProxyTemplate" abstract="true"
+ class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
+ <property name="transactionManager" ref="transactionManager"/>
+ <property name="transactionAttributes">
+ <props>
+ <prop key="*">PROPAGATION_REQUIRED</prop>
+ </props>
+ </property>
+</bean>
+
+ This will never be instantiated itself, so may actually be
+ incomplete. Then each proxy which needs to be created is just a child bean
+ definition, which wraps the target of the proxy as an inner bean
+ definition, since the target will never be used on its own
+ anyway.<bean id="myService" parent="txProxyTemplate">
+ <property name="target">
+ <bean class="org.springframework.samples.MyServiceImpl">
+ </bean>
+ </property>
+</bean>
+
+ It is of course possible to override properties from the parent
+ template, such as in this case, the transaction propagation
+ settings:<bean id="mySpecialService" parent="txProxyTemplate">
+ <property name="target">
+ <bean class="org.springframework.samples.MySpecialServiceImpl">
+ </bean>
+ </property>
+ <property name="transactionAttributes">
+ <props>
+ <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
+ <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
+ <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
+ <prop key="store*">PROPAGATION_REQUIRED</prop>
+ </props>
+ </property>
+</bean>
+
+ Note that in the example above, we have explicitly marked the parent
+ bean definition as abstract by using the
+ abstract attribute, as described previously, so that it may
+ not actually ever be instantiated. Application contexts (but not simple
+ bean factories) will by default pre-instantiate all singletons. It is therefore
+ important (at least for singleton beans) that if you have a (parent)
+ bean definition which you intend to use only as a template, and this
+ definition specifies a class, you must make sure to set the
+ abstract attribute to true,
+ otherwise the application context will actually try to pre-instantiate
+ it.
+
+
+
+ Creating AOP proxies programmatically with the ProxyFactory
+
+ It's easy to create AOP proxies programmatically using Spring. This
+ enables you to use Spring AOP without dependency on Spring IoC.
+
+ The following listing shows creation of a proxy for a target object,
+ with one interceptor and one advisor. The interfaces implemented by the
+ target object will automatically be proxied:
+
+ ProxyFactory factory = new ProxyFactory(myBusinessInterfaceImpl);
+factory.addInterceptor(myMethodInterceptor);
+factory.addAdvisor(myAdvisor);
+MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy();
+
+ The first step is to construct an object of type
+ org.springframework.aop.framework.ProxyFactory. You can
+ create this with a target object, as in the above example, or specify the
+ interfaces to be proxied in an alternate constructor.
+
+ You can add interceptors or advisors, and manipulate them for the
+ life of the ProxyFactory. If you add an
+ IntroductionInterceptionAroundAdvisor you can cause the proxy to implement
+ additional interfaces.
+
+ There are also convenience methods on ProxyFactory (inherited from
+ AdvisedSupport) which allow you to add other advice types
+ such as before and throws advice. AdvisedSupport is the superclass of both
+ ProxyFactory and ProxyFactoryBean.
+
+
+ Integrating AOP proxy creation with the IoC framework is best
+ practice in most applications. We recommend that you externalize
+ configuration from Java code with AOP, as in general.
+
+
+
+
+ Manipulating advised objects
+
+ However you create AOP proxies, you can manipulate them using the
+ org.springframework.aop.framework.Advised interface.
+ Any AOP proxy can be cast to this interface, whichever other interfaces it
+ implements. This interface includes the following methods:
+
+ Advisor[] getAdvisors();
+
+void addAdvice(Advice advice) throws AopConfigException;
+
+void addAdvice(int pos, Advice advice)
+ throws AopConfigException;
+
+void addAdvisor(Advisor advisor) throws AopConfigException;
+
+void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
+
+int indexOf(Advisor advisor);
+
+boolean removeAdvisor(Advisor advisor) throws AopConfigException;
+
+void removeAdvisor(int index) throws AopConfigException;
+
+boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
+
+boolean isFrozen();
+
+ The getAdvisors() method will return an Advisor
+ for every advisor, interceptor or other advice type that has been added to
+ the factory. If you added an Advisor, the returned advisor at this index
+ will be the object that you added. If you added an interceptor or other
+ advice type, Spring will have wrapped this in an advisor with a pointcut
+ that always returns true. Thus if you added a
+ MethodInterceptor, the advisor returned for this index
+ will be an DefaultPointcutAdvisor returning your
+ MethodInterceptor and a pointcut that matches all
+ classes and methods.
+
+ The addAdvisor() methods can be used to add any
+ Advisor. Usually the advisor holding pointcut and advice will be the
+ generic DefaultPointcutAdvisor, which can be used with
+ any advice or pointcut (but not for introductions).
+
+ By default, it's possible to add or remove advisors or interceptors
+ even once a proxy has been created. The only restriction is that it's
+ impossible to add or remove an introduction advisor, as existing proxies
+ from the factory will not show the interface change. (You can obtain a new
+ proxy from the factory to avoid this problem.)
+
+ A simple example of casting an AOP proxy to the
+ Advised interface and examining and manipulating its
+ advice:
+
+ Advised advised = (Advised) myObject;
+Advisor[] advisors = advised.getAdvisors();
+int oldAdvisorCount = advisors.length;
+System.out.println(oldAdvisorCount + " advisors");
+
+// Add an advice like an interceptor without a pointcut
+// Will match all proxied methods
+// Can use for interceptors, before, after returning or throws advice
+advised.addAdvice(new DebugInterceptor());
+
+// Add selective advice using a pointcut
+advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
+
+assertEquals("Added two advisors",
+ oldAdvisorCount + 2, advised.getAdvisors().length);
+
+
+ It's questionable whether it's advisable (no pun intended) to
+ modify advice on a business object in production, although there are no
+ doubt legitimate usage cases. However, it can be very useful in
+ development: for example, in tests. I have sometimes found it very useful
+ to be able to add test code in the form of an interceptor or other advice,
+ getting inside a method invocation I want to test. (For example, the
+ advice can get inside a transaction created for that method: for example,
+ to run SQL to check that a database was correctly updated, before marking
+ the transaction for roll back.)
+
+
+ Depending on how you created the proxy, you can usually set a
+ frozen flag, in which case the
+ AdvisedisFrozen() method will
+ return true, and any attempts to modify advice through addition or removal
+ will result in an AopConfigException. The ability to
+ freeze the state of an advised object is useful in some cases, for
+ example, to prevent calling code removing a security interceptor. It may
+ also be used in Spring 1.1 to allow aggressive optimization if runtime
+ advice modification is known not to be required.
+
+
+
+ Using the "autoproxy" facility
+
+ So far we've considered explicit creation of AOP proxies using a
+ ProxyFactoryBean or similar factory bean.
+
+ Spring also allows us to use "autoproxy" bean definitions, which can
+ automatically proxy selected bean definitions. This is built on Spring
+ "bean post processor" infrastructure, which enables modification of any
+ bean definition as the container loads.
+
+ In this model, you set up some special bean definitions in your XML
+ bean definition file to configure the auto proxy infrastructure. This
+ allows you just to declare the targets eligible for autoproxying: you
+ don't need to use ProxyFactoryBean.
+
+ There are two ways to do this:
+
+
+
+ Using an autoproxy creator that refers to specific beans in the
+ current context.
+
+
+
+ A special case of autoproxy creation that deserves to be
+ considered separately; autoproxy creation driven by source-level
+ metadata attributes.
+
+
+
+
+ Autoproxy bean definitions
+
+ The org.springframework.aop.framework.autoproxy
+ package provides the following standard autoproxy creators.
+
+
+ BeanNameAutoProxyCreator
+
+ The BeanNameAutoProxyCreator class is a
+ BeanPostProcessor that automatically creates AOP proxies
+ for beans with names matching literal values or wildcards.
+
+ <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
+ <property name="beanNames"><value>jdk*,onlyJdk</value></property>
+ <property name="interceptorNames">
+ <list>
+ <value>myInterceptor</value>
+ </list>
+ </property>
+</bean>
+
+ As with ProxyFactoryBean, there is an
+ interceptorNames property rather than a list of interceptors, to allow
+ correct behavior for prototype advisors. Named "interceptors" can be
+ advisors or any advice type.
+
+ As with auto proxying in general, the main point of using
+ BeanNameAutoProxyCreator is to apply the same
+ configuration consistently to multiple objects, with minimal
+ volume of configuration. It is a popular choice for applying
+ declarative transactions to multiple objects.
+
+ Bean definitions whose names match, such as "jdkMyBean" and
+ "onlyJdk" in the above example, are plain old bean definitions with
+ the target class. An AOP proxy will be created automatically by the
+ BeanNameAutoProxyCreator. The same advice will be
+ applied to all matching beans. Note that if advisors are used (rather
+ than the interceptor in the above example), the pointcuts may apply
+ differently to different beans.
+
+
+
+ DefaultAdvisorAutoProxyCreator
+
+ A more general and extremely powerful auto proxy creator is
+ DefaultAdvisorAutoProxyCreator. This will
+ automagically apply eligible advisors in the current context, without
+ the need to include specific bean names in the autoproxy advisor's
+ bean definition. It offers the same merit of consistent configuration
+ and avoidance of duplication as
+ BeanNameAutoProxyCreator.
+
+ Using this mechanism involves:
+
+
+
+ Specifying a
+ DefaultAdvisorAutoProxyCreator bean
+ definition.
+
+
+
+ Specifying any number of Advisors in the same or related
+ contexts. Note that these must be Advisors,
+ not just interceptors or other advices. This is necessary because
+ there must be a pointcut to evaluate, to check the eligibility of
+ each advice to candidate bean definitions.
+
+
+
+ The DefaultAdvisorAutoProxyCreator will
+ automatically evaluate the pointcut contained in each advisor, to see
+ what (if any) advice it should apply to each business object (such as
+ "businessObject1" and "businessObject2" in the example).
+
+ This means that any number of advisors can be applied
+ automatically to each business object. If no pointcut in any of the
+ advisors matches any method in a business object, the object will not
+ be proxied. As bean definitions are added for new business objects,
+ they will automatically be proxied if necessary.
+
+ Autoproxying in general has the advantage of making it
+ impossible for callers or dependencies to obtain an un-advised object.
+ Calling getBean("businessObject1") on this ApplicationContext will
+ return an AOP proxy, not the target business object. (The "inner bean"
+ idiom shown earlier also offers this benefit.)
+
+ <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
+
+<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
+ <property name="transactionInterceptor" ref="transactionInterceptor"/>
+</bean>
+
+<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
+
+<bean id="businessObject1" class="com.mycompany.BusinessObject1">
+ <!-- Properties omitted -->
+</bean>
+
+<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
+
+
+ The DefaultAdvisorAutoProxyCreator is very
+ useful if you want to apply the same advice consistently to many
+ business objects. Once the infrastructure definitions are in place,
+ you can simply add new business objects without including specific
+ proxy configuration. You can also drop in additional aspects very
+ easily - for example, tracing or performance monitoring aspects - with
+ minimal change to configuration.
+
+ The DefaultAdvisorAutoProxyCreator offers support for filtering
+ (using a naming convention so that only certain advisors are
+ evaluated, allowing use of multiple, differently configured,
+ AdvisorAutoProxyCreators in the same factory) and ordering. Advisors
+ can implement the org.springframework.core.Ordered
+ interface to ensure correct ordering if this is an issue. The
+ TransactionAttributeSourceAdvisor used in the above example has a
+ configurable order value; the default setting is unordered.
+
+
+
+ AbstractAdvisorAutoProxyCreator
+
+ This is the superclass of DefaultAdvisorAutoProxyCreator. You
+ can create your own autoproxy creators by subclassing this class, in
+ the unlikely event that advisor definitions offer insufficient
+ customization to the behavior of the framework
+ DefaultAdvisorAutoProxyCreator.
+
+
+
+
+ Using metadata-driven auto-proxying
+
+ A particularly important type of autoproxying is driven by
+ metadata. This produces a similar programming model to .NET
+ ServicedComponents. Instead of using XML deployment
+ descriptors as in EJB, configuration for transaction management and
+ other enterprise services is held in source-level attributes.
+
+ In this case, you use the
+ DefaultAdvisorAutoProxyCreator, in combination with
+ Advisors that understand metadata attributes. The metadata specifics are
+ held in the pointcut part of the candidate advisors, rather than in the
+ autoproxy creation class itself.
+
+ This is really a special case of the
+ DefaultAdvisorAutoProxyCreator, but deserves
+ consideration on its own. (The metadata-aware code is in the pointcuts
+ contained in the advisors, not the AOP framework itself.)
+
+ The /attributes directory of the JPetStore
+ sample application shows the use of attribute-driven autoproxying. In
+ this case, there's no need to use the
+ TransactionProxyFactoryBean. Simply defining
+ transactional attributes on business objects is sufficient, because of
+ the use of metadata-aware pointcuts. The bean definitions include the
+ following code, in /WEB-INF/declarativeServices.xml.
+ Note that this is generic, and can be used outside the JPetStore:
+
+ <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
+
+<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
+ <property name="transactionInterceptor" ref="transactionInterceptor"/>
+</bean>
+
+<bean id="transactionInterceptor"
+ class="org.springframework.transaction.interceptor.TransactionInterceptor">
+ <property name="transactionManager" ref="transactionManager"/>
+ <property name="transactionAttributeSource">
+ <bean class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">
+ <property name="attributes" ref="attributes"/>
+ </bean>
+ </property>
+</bean>
+
+<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/>
+
+ The DefaultAdvisorAutoProxyCreator bean
+ definition (the name is not significant, hence it can even be omitted)
+ will pick up all eligible pointcuts in the current application context.
+ In this case, the "transactionAdvisor" bean definition, of type
+ TransactionAttributeSourceAdvisor, will apply to
+ classes or methods carrying a transaction attribute. The
+ TransactionAttributeSourceAdvisor depends on a TransactionInterceptor,
+ via constructor dependency. The example resolves this via autowiring.
+ The AttributesTransactionAttributeSource depends on
+ an implementation of the
+ org.springframework.metadata.Attributes interface. In
+ this fragment, the "attributes" bean satisfies this, using the Jakarta
+ Commons Attributes API to obtain attribute information. (The application
+ code must have been compiled using the Commons Attributes compilation
+ task.)
+
+ The /annotation directory of the JPetStore
+ sample application contains an analogous example for auto-proxying
+ driven by JDK 1.5+ annotations. The following configuration enables
+ automatic detection of Spring's Transactional
+ annotation, leading to implicit proxies for beans containing that
+ annotation:
+
+ <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
+
+<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
+ <property name="transactionInterceptor" ref="transactionInterceptor"/>
+</bean>
+
+<bean id="transactionInterceptor"
+ class="org.springframework.transaction.interceptor.TransactionInterceptor">
+ <property name="transactionManager" ref="transactionManager"/>
+ <property name="transactionAttributeSource">
+ <bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
+ </property>
+</bean>
+
+ The TransactionInterceptor defined here depends
+ on a PlatformTransactionManager definition, which is
+ not included in this generic file (although it could be) because it will
+ be specific to the application's transaction requirements (typically
+ JTA, as in this example, or Hibernate, JDO or JDBC):
+
+ <bean id="transactionManager"
+ class="org.springframework.transaction.jta.JtaTransactionManager"/>
+
+
+ If you require only declarative transaction management, using
+ these generic XML definitions will result in Spring automatically
+ proxying all classes or methods with transaction attributes. You won't
+ need to work directly with AOP, and the programming model is similar to
+ that of .NET ServicedComponents.
+
+
+ This mechanism is extensible. It's possible to do autoproxying
+ based on custom attributes. You need to:
+
+
+
+ Define your custom attribute.
+
+
+
+ Specify an Advisor with the necessary advice, including a
+ pointcut that is triggered by the presence of the custom attribute
+ on a class or method. You may be able to use an existing advice,
+ merely implementing a static pointcut that picks up the custom
+ attribute.
+
+
+
+ It's possible for such advisors to be unique to each advised class
+ (for example, mixins): they simply need to be defined as prototype,
+ rather than singleton, bean definitions. For example, the
+ LockMixin introduction interceptor from the Spring
+ test suite, shown above, could be used in conjunction with an
+ attribute-driven pointcut to target a mixin, as shown here. We use the
+ generic DefaultPointcutAdvisor, configured using
+ JavaBean properties:
+
+ <bean id="lockMixin" class="org.springframework.aop.LockMixin"
+ scope="prototype"/>
+
+<bean id="lockableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
+ scope="prototype">
+ <property name="pointcut" ref="myAttributeAwarePointcut"/>
+ <property name="advice" ref="lockMixin"/>
+</bean>
+
+<bean id="anyBean" class="anyclass" ...
+
+ If the attribute aware pointcut matches any methods in the
+ anyBean or other bean definitions, the mixin will be
+ applied. Note that both lockMixin and
+ lockableAdvisor definitions are prototypes. The
+ myAttributeAwarePointcut pointcut can be a singleton
+ definition, as it doesn't hold state for individual advised
+ objects.
+
+
+
+
+ Using TargetSources
+
+ Spring offers the concept of a TargetSource,
+ expressed in the org.springframework.aop.TargetSource
+ interface. This interface is responsible for returning the "target object"
+ implementing the join point. The TargetSource
+ implementation is asked for a target instance each time the AOP proxy
+ handles a method invocation.
+
+ Developers using Spring AOP don't normally need to work directly
+ with TargetSources, but this provides a powerful means of supporting
+ pooling, hot swappable and other sophisticated targets. For example, a
+ pooling TargetSource can return a different target instance for each
+ invocation, using a pool to manage instances.
+
+ If you do not specify a TargetSource, a default implementation is
+ used that wraps a local object. The same target is returned for each
+ invocation (as you would expect).
+
+ Let's look at the standard target sources provided with Spring, and
+ how you can use them.
+
+
+ When using a custom target source, your target will usually need
+ to be a prototype rather than a singleton bean definition. This allows
+ Spring to create a new target instance when required.
+
+
+
+ Hot swappable target sources
+
+ The
+ org.springframework.aop.target.HotSwappableTargetSource
+ exists to allow the target of an AOP proxy to be switched while allowing
+ callers to keep their references to it.
+
+ Changing the target source's target takes effect immediately. The
+ HotSwappableTargetSource is threadsafe.
+
+ You can change the target via the swap() method
+ on HotSwappableTargetSource as follows:
+
+ HotSwappableTargetSource swapper =
+ (HotSwappableTargetSource) beanFactory.getBean("swapper");
+Object oldTarget = swapper.swap(newTarget);
+
+ The XML definitions required look as follows:
+
+ <bean id="initialTarget" class="mycompany.OldTarget"/>
+
+<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource">
+ <constructor-arg ref="initialTarget"/>
+</bean>
+
+<bean id="swappable" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="targetSource" ref="swapper"/>
+</bean>
+
+ The above swap() call changes the target of the
+ swappable bean. Clients who hold a reference to that bean will be
+ unaware of the change, but will immediately start hitting the new
+ target.
+
+ Although this example doesn't add any advice - and it's not
+ necessary to add advice to use a TargetSource - of
+ course any TargetSource can be used in conjunction
+ with arbitrary advice.
+
+
+
+ Pooling target sources
+
+ Using a pooling target source provides a similar programming model
+ to stateless session EJBs, in which a pool of identical instances is
+ maintained, with method invocations going to free objects in the
+ pool.
+
+ A crucial difference between Spring pooling and SLSB pooling is
+ that Spring pooling can be applied to any POJO. As with Spring in
+ general, this service can be applied in a non-invasive way.
+
+ Spring provides out-of-the-box support for Jakarta Commons Pool
+ 1.3, which provides a fairly efficient pooling implementation. You'll
+ need the commons-pool Jar on your application's classpath to use this
+ feature. It's also possible to subclass
+ org.springframework.aop.target.AbstractPoolingTargetSource
+ to support any other pooling API.
+
+ Sample configuration is shown below:
+
+ <bean id="businessObjectTarget" class="com.mycompany.MyBusinessObject"
+ scope="prototype">
+ ... properties omitted
+</bean>
+
+<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
+ <property name="targetBeanName" value="businessObjectTarget"/>
+ <property name="maxSize" value="25"/>
+</bean>
+
+<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="targetSource" ref="poolTargetSource"/>
+ <property name="interceptorNames" value="myInterceptor"/>
+</bean>
+
+ Note that the target object - "businessObjectTarget" in the
+ example - must be a prototype. This allows the
+ PoolingTargetSource implementation to create new
+ instances of the target to grow the pool as necessary. See the havadoc
+ for AbstractPoolingTargetSource and the concrete
+ subclass you wish to use for information about its properties: "maxSize"
+ is the most basic, and always guaranteed to be present.
+
+ In this case, "myInterceptor" is the name of an interceptor that
+ would need to be defined in the same IoC context. However, it isn't
+ necessary to specify interceptors to use pooling. If you want only
+ pooling, and no other advice, don't set the interceptorNames property at
+ all.
+
+ It's possible to configure Spring so as to be able to cast any
+ pooled object to the
+ org.springframework.aop.target.PoolingConfig
+ interface, which exposes information about the configuration and current
+ size of the pool through an introduction. You'll need to define an
+ advisor like this:
+
+ <bean id="poolConfigAdvisor" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+ <property name="targetObject" ref="poolTargetSource"/>
+ <property name="targetMethod" value="getPoolingConfigMixin"/>
+</bean>
+
+ This advisor is obtained by calling a convenience method on the
+ AbstractPoolingTargetSource class, hence the use of
+ MethodInvokingFactoryBean. This advisor's name ("poolConfigAdvisor"
+ here) must be in the list of interceptors names in the ProxyFactoryBean
+ exposing the pooled object.
+
+ The cast will look as follows:
+
+
+
+
+ Pooling stateless service objects is not usually necessary. We
+ don't believe it should be the default choice, as most stateless objects
+ are naturally thread safe, and instance pooling is problematic if
+ resources are cached.
+
+
+ Simpler pooling is available using autoproxying. It's possible to
+ set the TargetSources used by any autoproxy creator.
+
+
+
+ Prototype target sources
+
+ Setting up a "prototype" target source is similar to a pooling
+ TargetSource. In this case, a new instance of the target will be created
+ on every method invocation. Although the cost of creating a new object
+ isn't high in a modern JVM, the cost of wiring up the new object
+ (satisfying its IoC dependencies) may be more expensive. Thus you
+ shouldn't use this approach without very good reason.
+
+ To do this, you could modify the
+ poolTargetSource definition shown above as follows.
+ (I've also changed the name, for clarity.)
+
+
+
+]]>
+
+ There's only one property: the name of the target bean.
+ Inheritance is used in the TargetSource implementations to ensure
+ consistent naming. As with the pooling target source, the target bean
+ must be a prototype bean definition.
+
+
+
+ ThreadLocal target sources
+
+ ThreadLocal target sources are useful if you need an object to be
+ created for each incoming request (per thread that is). The concept of a
+ ThreadLocal provide a JDK-wide facility to
+ transparently store resource alongside a thread. Setting up a
+ ThreadLocalTargetSource is pretty much the same as was explained for the
+ other types of target source:
+
+
+
+]]>
+
+
+ ThreadLocals come with serious issues (potentially
+ resulting in memory leaks) when incorrectly using them in a
+ multi-threaded and multi-classloader environments. One should always
+ consider wrapping a threadlocal in some other class and never directly
+ use the ThreadLocal itself (except of course in the wrapper class).
+ Also, one should always remember to correctly set and unset (where the
+ latter simply involved a call to ThreadLocal.set(null)) the resource
+ local to the thread. Unsetting should be done in any case since not
+ unsetting it might result in problematic behavior. Spring's ThreadLocal
+ support does this for you and should always be considered in favor
+ of using ThreadLocals without other proper handling
+ code.
+
+
+
+
+
+ Defining new Advice types
+
+ Spring AOP is designed to be extensible. While the interception
+ implementation strategy is presently used internally, it is possible to
+ support arbitrary advice types in addition to the out-of-the-box interception around advice,
+ before, throws advice and after returning advice.
+
+ The org.springframework.aop.framework.adapter
+ package is an SPI package allowing support for new custom advice types to
+ be added without changing the core framework. The only constraint on a
+ custom Advice type is that it must implement the
+ org.aopalliance.aop.Advice tag interface.
+
+ Please refer to the
+ org.springframework.aop.framework.adapter package's
+ Javadocs for further information.
+
+
+
+ Further resources
+
+ Please refer to the Spring sample applications for further examples
+ of Spring AOP:
+
+
+
+ The JPetStore's default configuration illustrates the use of the
+ TransactionProxyFactoryBean for declarative transaction
+ management.
+
+
+
+ The /attributes directory of the JPetStore
+ illustrates the use of attribute-driven declarative transaction management.
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/aop.xml b/spring-framework-reference/src/aop.xml
new file mode 100644
index 00000000000..1fd774a74ca
--- /dev/null
+++ b/spring-framework-reference/src/aop.xml
@@ -0,0 +1,3661 @@
+
+
+ Aspect Oriented Programming with Spring
+
+
+ Introduction
+
+ Aspect-Oriented Programming (AOP) complements
+ Object-Oriented Programming (OOP) by providing another way of thinking
+ about program structure. The key unit of modularity in OOP is the class,
+ whereas in AOP the unit of modularity is the aspect.
+ Aspects enable the modularization of concerns such as transaction
+ management that cut across multiple types and objects. (Such concerns are
+ often termed crosscutting concerns in AOP
+ literature.)
+
+ One of the key components of Spring is the AOP
+ framework. While the Spring IoC container does not depend on
+ AOP, meaning you do not need to use AOP if you don't want to, AOP
+ complements Spring IoC to provide a very capable middleware
+ solution.
+
+
+ Spring 2.0 AOP
+
+ Spring 2.0 introduces a simpler and more powerful way of writing
+ custom aspects using either a schema-based
+ approach or the @AspectJ annotation
+ style. Both of these styles offer fully typed advice and use of
+ the AspectJ pointcut language, while still using Spring AOP for
+ weaving.
+
+ The Spring 2.0 schema- and @AspectJ-based AOP support is discussed
+ in this chapter. Spring 2.0 AOP remains fully backwards compatible with
+ Spring 1.2 AOP, and the lower-level AOP support offered by the Spring
+ 1.2 APIs is discussed in the following
+ chapter.
+
+
+ AOP is used in the Spring Framework to...
+
+
+
+ ... provide declarative enterprise services, especially as a
+ replacement for EJB declarative services. The most important such
+ service is declarative transaction
+ management.
+
+
+
+ ... allow users to implement custom aspects, complementing their
+ use of OOP with AOP.
+
+
+
+ If you are interested only in generic declarative services
+ or other pre-packaged declarative middleware services such as pooling, you
+ do not need to work directly with Spring AOP, and can skip most of this
+ chapter.
+
+
+ AOP concepts
+
+ Let us begin by defining some central AOP concepts and
+ terminology. These terms are not Spring-specific... unfortunately, AOP
+ terminology is not particularly intuitive; however, it would be even
+ more confusing if Spring used its own terminology.
+
+
+
+ Aspect: a modularization of a concern
+ that cuts across multiple classes. Transaction management is a good
+ example of a crosscutting concern in J2EE applications. In Spring
+ AOP, aspects are implemented using regular classes (the schema-based approach) or regular
+ classes annotated with the @Aspect
+ annotation (the @AspectJ
+ style).
+
+
+
+ Join point: a point during the execution
+ of a program, such as the execution of a method or the handling of
+ an exception. In Spring AOP, a join point
+ always represents a method execution.
+
+
+
+ Advice: action taken by an aspect at a
+ particular join point. Different types of advice include "around,"
+ "before" and "after" advice. (Advice types are discussed below.)
+ Many AOP frameworks, including Spring, model an advice as an
+ interceptor, maintaining a chain of
+ interceptors around the join point.
+
+
+
+ Pointcut: a predicate that matches join
+ points. Advice is associated with a pointcut expression and runs at
+ any join point matched by the pointcut (for example, the execution
+ of a method with a certain name). The concept of join points as
+ matched by pointcut expressions is central to AOP, and Spring uses
+ the AspectJ pointcut expression language by default.
+
+
+
+ Introduction: declaring additional
+ methods or fields on behalf of a type. Spring AOP allows you to
+ introduce new interfaces (and a corresponding implementation) to any
+ advised object. For example, you could use an introduction to make a
+ bean implement an IsModified
+ interface, to simplify caching. (An introduction is known as an
+ inter-type declaration in the AspectJ community.)
+
+
+
+ Target object: object being advised by
+ one or more aspects. Also referred to as the
+ advised object. Since Spring AOP is implemented
+ using runtime proxies, this object will always be a
+ proxied object.
+
+
+
+ AOP proxy: an object created by the AOP
+ framework in order to implement the aspect contracts (advise method
+ executions and so on). In the Spring Framework, an AOP proxy will be
+ a JDK dynamic proxy or a CGLIB proxy.
+
+
+
+ Weaving: linking aspects with other
+ application types or objects to create an advised object. This can
+ be done at compile time (using the AspectJ compiler, for example),
+ load time, or at runtime. Spring AOP, like other pure Java AOP
+ frameworks, performs weaving at runtime.
+
+
+
+ Types of advice:
+
+
+
+ Before advice: Advice that executes
+ before a join point, but which does not have the ability to prevent
+ execution flow proceeding to the join point (unless it throws an
+ exception).
+
+
+
+ After returning advice: Advice to be
+ executed after a join point completes normally: for example, if a
+ method returns without throwing an exception.
+
+
+
+ After throwing advice: Advice to be
+ executed if a method exits by throwing an exception.
+
+
+
+ After (finally) advice: Advice to be
+ executed regardless of the means by which a join point exits (normal
+ or exceptional return).
+
+
+
+ Around advice: Advice that surrounds a
+ join point such as a method invocation. This is the most powerful
+ kind of advice. Around advice can perform custom behavior before and
+ after the method invocation. It is also responsible for choosing
+ whether to proceed to the join point or to shortcut the advised
+ method execution by returning its own return value or throwing an
+ exception.
+
+
+
+ Around advice is the most general kind of advice. Since Spring
+ AOP, like AspectJ, provides a full range of advice types, we recommend
+ that you use the least powerful advice type that can implement the
+ required behavior. For example, if you need only to update a cache with
+ the return value of a method, you are better off implementing an after
+ returning advice than an around advice, although an around advice can
+ accomplish the same thing. Using the most specific advice type provides
+ a simpler programming model with less potential for errors. For example,
+ you do not need to invoke the proceed() method
+ on the JoinPoint used for around advice,
+ and hence cannot fail to invoke it.
+
+ In Spring 2.0, all advice parameters are statically typed, so that
+ you work with advice parameters of the appropriate type (the type of the
+ return value from a method execution for example) rather than
+ Object arrays.
+
+ The concept of join points, matched by pointcuts, is the key to
+ AOP which distinguishes it from older technologies offering only
+ interception. Pointcuts enable advice to be targeted independently of
+ the Object-Oriented hierarchy. For example, an around advice providing
+ declarative transaction management can be applied to a set of methods
+ spanning multiple objects (such as all business operations in the
+ service layer).
+
+
+
+ Spring AOP capabilities and goals
+
+ Spring AOP is implemented in pure Java. There is no need for a
+ special compilation process. Spring AOP does not need to control the
+ class loader hierarchy, and is thus suitable for use in a J2EE web
+ container or application server.
+
+ Spring AOP currently supports only method execution join points
+ (advising the execution of methods on Spring beans). Field interception
+ is not implemented, although support for field interception could be
+ added without breaking the core Spring AOP APIs. If you need to advise
+ field access and update join points, consider a language such as
+ AspectJ.
+
+ Spring AOP's approach to AOP differs from that of most other AOP
+ frameworks. The aim is not to provide the most complete AOP
+ implementation (although Spring AOP is quite capable); it is rather to
+ provide a close integration between AOP implementation and Spring IoC to
+ help solve common problems in enterprise applications.
+
+ Thus, for example, the Spring Framework's AOP functionality is
+ normally used in conjunction with the Spring IoC container. Aspects are
+ configured using normal bean definition syntax (although this allows
+ powerful "autoproxying" capabilities): this is a crucial difference from
+ other AOP implementations. There are some things you cannot do easily or
+ efficiently with Spring AOP, such as advise very fine-grained objects
+ (such as domain objects typically): AspectJ is the best choice in such
+ cases. However, our experience is that Spring AOP provides an excellent
+ solution to most problems in J2EE applications that are amenable to
+ AOP.
+
+ Spring AOP will never strive to compete with AspectJ to provide a
+ comprehensive AOP solution. We believe that both proxy-based frameworks
+ like Spring AOP and full-blown frameworks such as AspectJ are valuable,
+ and that they are complementary, rather than in competition. Spring 2.0
+ seamlessly integrates Spring AOP and IoC with AspectJ, to enable all
+ uses of AOP to be catered for within a consistent Spring-based
+ application architecture. This integration does not affect the Spring
+ AOP API or the AOP Alliance API: Spring AOP remains backward-compatible.
+ See the following chapter for a
+ discussion of the Spring AOP APIs.
+
+
+ One of the central tenets of the Spring Framework is that of
+ non-invasiveness; this is the idea that you
+ should not be forced to introduce framework-specific classes and
+ interfaces into your business/domain model. However, in some places
+ the Spring Framework does give you the option to introduce Spring
+ Framework-specific dependencies into your codebase: the rationale in
+ giving you such options is because in certain scenarios it might be
+ just plain easier to read or code some specific piece of functionality
+ in such a way. The Spring Framework (almost) always offers you the
+ choice though: you have the freedom to make an informed decision as to
+ which option best suits your particular use case or scenario.
+
+ One such choice that is relevant to this chapter is that of
+ which AOP framework (and which AOP style) to choose. You have the
+ choice of AspectJ and/or Spring AOP, and you also have the choice of
+ either the @AspectJ annotation-style approach or the Spring XML
+ configuration-style approach. The fact that this chapter chooses to
+ introduce the @AspectJ-style approach first should not be taken as an
+ indication that the Spring team favors the @AspectJ annotation-style
+ approach over the Spring XML configuration-style.
+
+ See the section entitled for a
+ fuller discussion of the whys and wherefores of each style.
+
+
+
+
+ AOP Proxies
+
+ Spring AOP defaults to using standard J2SE dynamic
+ proxies for AOP proxies. This enables any interface (or set
+ of interfaces) to be proxied.
+
+ Spring AOP can also use CGLIB proxies. This is necessary to proxy
+ classes, rather than interfaces. CGLIB is used by default if a business
+ object does not implement an interface. As it is good practice to
+ program to interfaces rather than classes, business classes normally
+ will implement one or more business interfaces. It is possible to force the use of CGLIB, in
+ those (hopefully rare) cases where you need to advise a method that is
+ not declared on an interface, or where you need to pass a proxied object
+ to a method as a concrete type.
+
+ It is important to grasp the fact that Spring AOP is
+ proxy-based. See the section entitled for a thorough examination of
+ exactly what this implementation detail actually means.
+
+
+
+
+ @AspectJ support
+
+ @AspectJ refers to a style of declaring aspects as regular Java
+ classes annotated with Java 5 annotations. The @AspectJ style was
+ introduced by the AspectJ
+ project as part of the AspectJ 5 release. Spring 2.0 interprets
+ the same annotations as AspectJ 5, using a library supplied by AspectJ for
+ pointcut parsing and matching. The AOP runtime is still pure Spring AOP
+ though, and there is no dependency on the AspectJ compiler or
+ weaver.
+
+ Using the AspectJ compiler and weaver enables use of the
+ full AspectJ language, and is discussed in .
+
+
+ Enabling @AspectJ Support
+
+ To use @AspectJ aspects in a Spring configuration you need to
+ enable Spring support for configuring Spring AOP based on @AspectJ
+ aspects, and autoproxying beans based on whether or
+ not they are advised by those aspects. By autoproxying we mean that if
+ Spring determines that a bean is advised by one or more aspects, it will
+ automatically generate a proxy for that bean to intercept method
+ invocations and ensure that advice is executed as needed.
+
+ The @AspectJ support is enabled by including the following element
+ inside your spring configuration:
+
+ <aop:aspectj-autoproxy/>
+
+ This assumes that you are using schema support as described in
+ . See for how to import the tags in
+ the aop namespace.
+
+ If you are using the DTD, it is still possible to enable @AspectJ
+ support by adding the following definition to your application
+ context:
+
+ <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />
+
+ You will also need two AspectJ libraries on the classpath of your
+ application: aspectjweaver.jar
+ and aspectjrt.jar. These
+ libraries are available in the 'lib' directory of an AspectJ installation
+ (version 1.5.1 or later required), or in the 'lib/aspectj' directory of the
+ Spring-with-dependencies distribution.
+
+
+
+ Declaring an aspect
+
+ With the @AspectJ support enabled, any bean defined in your
+ application context with a class that is an @AspectJ aspect (has the
+ @Aspect annotation) will be automatically
+ detected by Spring and used to configure Spring AOP. The following
+ example shows the minimal definition required for a not-very-useful
+ aspect:
+
+ A regular bean definition in the application context, pointing to
+ a bean class that has the @Aspect
+ annotation:
+
+ <bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
+ <!-- configure properties of aspect here as normal -->
+</bean>
+
+
+ And the NotVeryUsefulAspect class
+ definition, annotated with
+ org.aspectj.lang.annotation.Aspect
+ annotation;
+
+ package org.xyz;
+import org.aspectj.lang.annotation.Aspect;
+
+@Aspect
+public class NotVeryUsefulAspect {
+
+}
+
+ Aspects (classes annotated with
+ @Aspect) may have methods and fields just
+ like any other class. They may also contain pointcut, advice, and
+ introduction (inter-type) declarations.
+
+
+ Advising aspects
+
+ In Spring AOP, it is not possible to have
+ aspects themselves be the target of advice from other aspects. The
+ @Aspect annotation on a class marks it as an
+ aspect, and hence excludes it from auto-proxying.
+
+
+
+
+ Declaring a pointcut
+
+ Recall that pointcuts determine join points of interest, and thus
+ enable us to control when advice executes. Spring AOP only
+ supports method execution join points for Spring beans, so
+ you can think of a pointcut as matching the execution of methods on
+ Spring beans. A pointcut declaration has two parts: a signature
+ comprising a name and any parameters, and a pointcut expression that
+ determines exactly which method executions we are
+ interested in. In the @AspectJ annotation-style of AOP, a pointcut
+ signature is provided by a regular method definition, and the pointcut
+ expression is indicated using the
+ @Pointcut annotation (the method serving
+ as the pointcut signature must have a
+ void return type).
+
+ An example will help make this distinction between a pointcut
+ signature and a pointcut expression clear. The following example defines
+ a pointcut named 'anyOldTransfer' that will match the
+ execution of any method named 'transfer':
+
+ @Pointcut("execution(* transfer(..))")// the pointcut expression
+private void anyOldTransfer() {}// the pointcut signature
+
+ The pointcut expression that forms the value of the
+ @Pointcut annotation is a regular AspectJ
+ 5 pointcut expression. For a full discussion of AspectJ's pointcut
+ language, see the AspectJ
+ Programming Guide (and for Java 5 based extensions, the AspectJ
+ 5 Developers Notebook) or one of the books on AspectJ such as
+ Eclipse AspectJ by Colyer et. al. or AspectJ in
+ Action by Ramnivas Laddad.
+
+
+ Supported Pointcut Designators
+
+ Spring AOP supports the following AspectJ pointcut designators
+ (PCD) for use in pointcut expressions:
+
+
+ Other pointcut types
+
+ The full AspectJ pointcut language supports additional
+ pointcut designators that are not supported in Spring. These are:
+ call, get, set, preinitialization, staticinitialization,
+ initialization, handler, adviceexecution, withincode, cflow,
+ cflowbelow, if, @this, and @withincode.
+ Use of these pointcut designators in pointcut expressions
+ interpreted by Spring AOP will result in an
+ IllegalArgumentException being thrown.
+
+ The set of pointcut designators supported by Spring AOP may be
+ extended in future releases both to support more of the AspectJ
+ pointcut designators.
+
+
+
+
+ execution - for matching method
+ execution join points, this is the primary pointcut designator you
+ will use when working with Spring AOP
+
+
+
+ within - limits matching to join points
+ within certain types (simply the execution of a method declared
+ within a matching type when using Spring AOP)
+
+
+
+ this - limits matching to join points
+ (the execution of methods when using Spring AOP) where the bean
+ reference (Spring AOP proxy) is an instance of the given
+ type
+
+
+
+ target - limits matching to join points
+ (the execution of methods when using Spring AOP) where the target
+ object (application object being proxied) is an instance of the
+ given type
+
+
+
+ args - limits matching to join points
+ (the execution of methods when using Spring AOP) where the
+ arguments are instances of the given types
+
+
+
+ @target
+ - limits matching to join points (the execution of methods when
+ using Spring AOP) where the class of the executing object has an
+ annotation of the given type
+
+
+
+ @args -
+ limits matching to join points (the execution of methods when
+ using Spring AOP) where the runtime type of the actual arguments
+ passed have annotations of the given type(s)
+
+
+
+ @within
+ - limits matching to join points within types that have the given
+ annotation (the execution of methods declared in types with the
+ given annotation when using Spring AOP)
+
+
+
+ @annotation - limits matching to join
+ points where the subject of the join point (method being executed
+ in Spring AOP) has the given annotation
+
+
+
+ Because Spring AOP limits matching to only method execution
+ join points, the discussion of the pointcut designators above gives a
+ narrower definition than you will find in the AspectJ programming
+ guide. In addition, AspectJ itself has type-based semantics and at an
+ execution join point both 'this' and
+ 'target' refer to the same object - the object
+ executing the method. Spring AOP is a proxy-based system and
+ differentiates between the proxy object itself (bound to
+ 'this') and the target object behind the proxy
+ (bound to 'target').
+
+
+ Due to the proxy-based nature of Spring's AOP framework,
+ protected methods are by definition not
+ intercepted, neither for JDK proxies (where this isn't applicable)
+ nor for CGLIB proxies (where this is technically possible but not
+ recommendable for AOP purposes). As a consequence, any given pointcut
+ will be matched against public methods only!
+
+ If your interception needs include protected/private methods
+ or even constructors, consider the use of Spring-driven
+ native AspectJ weaving instead
+ of Spring's proxy-based AOP framework. This constitutes a different
+ mode of AOP usage with different characteristics, so be sure to make
+ yourself familiar with weaving first before making a decision.
+
+
+ Spring AOP also supports an additional PCD named
+ 'bean'. This PCD allows you to limit the matching
+ of join points to a particular named Spring bean, or to a set of named
+ Spring beans (when using wildcards). The 'bean' PCD
+ has the following form:
+
+ bean(idOrNameOfBean)
+
+ The 'idOrNameOfBean' token can be the name of
+ any Spring bean: limited wildcard support using the
+ '*' character is provided, so if you establish
+ some naming conventions for your Spring beans you can quite easily
+ write a 'bean' PCD expression to pick them out. As
+ is the case with other pointcut designators, the
+ 'bean' PCD can be &&'ed, ||'ed, and !
+ (negated) too.
+
+
+ Please note that the 'bean' PCD is
+ only supported in Spring AOP - and
+ not in native AspectJ weaving. It is a
+ Spring-specific extension to the standard PCDs that AspectJ
+ defines.
+
+ The 'bean' PCD operates at the
+ instance level (building on the Spring
+ bean name concept) rather than at the type level only
+ (which is what weaving-based AOP is limited to).
+ Instance-based pointcut designators are a special capability
+ of Spring's proxy-based AOP framework and its close integration
+ with the Spring bean factory, where it is natural and
+ straightforward to identify specific beans by name.
+
+
+
+
+ Combining pointcut expressions
+
+ Pointcut expressions can be combined using '&&', '||'
+ and '!'. It is also possible to refer to pointcut expressions by name.
+ The following example shows three pointcut expressions:
+ anyPublicOperation (which matches if a method
+ execution join point represents the execution of any public method);
+ inTrading (which matches if a method execution is
+ in the trading module), and tradingOperation (which
+ matches if a method execution represents any public method in the
+ trading module).
+
+ @Pointcut("execution(public * *(..))")
+ private void anyPublicOperation() {}
+
+ @Pointcut("within(com.xyz.someapp.trading..*)")
+ private void inTrading() {}
+
+ @Pointcut("anyPublicOperation() && inTrading()")
+ private void tradingOperation() {}
+
+ It is a best practice to build more complex pointcut expressions
+ out of smaller named components as shown above. When referring to
+ pointcuts by name, normal Java visibility rules apply (you can see
+ private pointcuts in the same type, protected pointcuts in the
+ hierarchy, public pointcuts anywhere and so on). Visibility does not
+ affect pointcut matching.
+
+
+
+ Sharing common pointcut definitions
+
+ When working with enterprise applications, you often want to
+ refer to modules of the application and particular sets of operations
+ from within several aspects. We recommend defining a
+ "SystemArchitecture" aspect that captures common pointcut expressions
+ for this purpose. A typical such aspect would look as follows:
+
+ package com.xyz.someapp;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+
+@Aspect
+public class SystemArchitecture {
+
+ /**
+ * A join point is in the web layer if the method is defined
+ * in a type in the com.xyz.someapp.web package or any sub-package
+ * under that.
+ */
+ @Pointcut("within(com.xyz.someapp.web..*)")
+ public void inWebLayer() {}
+
+ /**
+ * A join point is in the service layer if the method is defined
+ * in a type in the com.xyz.someapp.service package or any sub-package
+ * under that.
+ */
+ @Pointcut("within(com.xyz.someapp.service..*)")
+ public void inServiceLayer() {}
+
+ /**
+ * A join point is in the data access layer if the method is defined
+ * in a type in the com.xyz.someapp.dao package or any sub-package
+ * under that.
+ */
+ @Pointcut("within(com.xyz.someapp.dao..*)")
+ public void inDataAccessLayer() {}
+
+ /**
+ * A business service is the execution of any method defined on a service
+ * interface. This definition assumes that interfaces are placed in the
+ * "service" package, and that implementation types are in sub-packages.
+ *
+ * If you group service interfaces by functional area (for example,
+ * in packages com.xyz.someapp.abc.service and com.xyz.def.service) then
+ * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
+ * could be used instead.
+ *
+ * Alternatively, you can write the expression using the 'bean'
+ * PCD, like so "bean(*Service)". (This assumes that you have
+ * named your Spring service beans in a consistent fashion.)
+ */
+ @Pointcut("execution(* com.xyz.someapp.service.*.*(..))")
+ public void businessService() {}
+
+ /**
+ * A data access operation is the execution of any method defined on a
+ * dao interface. This definition assumes that interfaces are placed in the
+ * "dao" package, and that implementation types are in sub-packages.
+ */
+ @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
+ public void dataAccessOperation() {}
+
+}
+
+ The pointcuts defined in such an aspect can be referred to
+ anywhere that you need a pointcut expression. For example, to make the
+ service layer transactional, you could write:
+
+ <aop:config>
+ <aop:advisor
+ pointcut="com.xyz.someapp.SystemArchitecture.businessService()"
+ advice-ref="tx-advice"/>
+</aop:config>
+
+<tx:advice id="tx-advice">
+ <tx:attributes>
+ <tx:method name="*" propagation="REQUIRED"/>
+ </tx:attributes>
+</tx:advice>
+
+ The <aop:config> and
+ <aop:advisor> elements are discussed in . The transaction elements are discussed in
+ .
+
+
+
+ Examples
+
+ Spring AOP users are likely to use the
+ execution pointcut designator the most often. The
+ format of an execution expression is:
+
+ execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
+ throws-pattern?)
+
+ All parts except the returning type pattern (ret-type-pattern in
+ the snippet above), name pattern, and parameters pattern are optional.
+ The returning type pattern determines what the return type of the
+ method must be in order for a join point to be matched. Most
+ frequently you will use * as the returning type
+ pattern, which matches any return type. A fully-qualified type name
+ will match only when the method returns the given type. The name
+ pattern matches the method name. You can use the *
+ wildcard as all or part of a name pattern. The parameters pattern is
+ slightly more complex: () matches a method that
+ takes no parameters, whereas (..) matches any
+ number of parameters (zero or more). The pattern
+ (*) matches a method taking one parameter of any
+ type, (*,String) matches a method taking two
+ parameters, the first can be of any type, the second must be a String.
+ Consult the
+ Language Semantics section of the AspectJ Programming Guide
+ for more information.
+
+ Some examples of common pointcut expressions are given
+ below.
+
+
+
+ the execution of any public method:
+
+ execution(public * *(..))
+
+
+
+ the execution of any method with a name beginning with
+ "set":
+
+ execution(* set*(..))
+
+
+
+ the execution of any method defined by the
+ AccountService interface:
+
+ execution(* com.xyz.service.AccountService.*(..))
+
+
+
+ the execution of any method defined in the service
+ package:
+
+ execution(* com.xyz.service.*.*(..))
+
+
+
+ the execution of any method defined in the service package
+ or a sub-package:
+
+ execution(* com.xyz.service..*.*(..))
+
+
+
+ any join point (method execution only in Spring AOP) within
+ the service package:
+
+ within(com.xyz.service.*)
+
+
+
+ any join point (method execution only in Spring AOP) within
+ the service package or a sub-package:
+
+ within(com.xyz.service..*)
+
+
+
+ any join point (method execution only in Spring AOP) where
+ the proxy implements the
+ AccountService interface:
+
+ this(com.xyz.service.AccountService)
+
+ 'this' is more commonly used in a binding form :-
+ see the following section on advice for how to make the proxy
+ object available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) where
+ the target object implements the
+ AccountService interface:
+
+ target(com.xyz.service.AccountService)
+
+ 'target' is more commonly used in a binding form :-
+ see the following section on advice for how to make the target
+ object available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) which
+ takes a single parameter, and where the argument passed at runtime
+ is Serializable:
+
+ args(java.io.Serializable)
+
+ 'args' is more commonly used in a binding form :- see the
+ following section on advice for how to make the method arguments
+ available in the advice body.
+
+ Note that the pointcut given in this example is different to
+ execution(* *(java.io.Serializable)): the args
+ version matches if the argument passed at runtime is Serializable,
+ the execution version matches if the method signature declares a
+ single parameter of type
+ Serializable.
+
+
+
+ any join point (method execution only in Spring AOP) where
+ the target object has an
+ @Transactional annotation:
+
+ @target(org.springframework.transaction.annotation.Transactional)
+
+ '@target' can also be used in a binding form :- see
+ the following section on advice for how to make the annotation
+ object available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) where
+ the declared type of the target object has an
+ @Transactional annotation:
+
+ @within(org.springframework.transaction.annotation.Transactional)
+
+ '@within' can also be used in a binding form :- see
+ the following section on advice for how to make the annotation
+ object available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) where
+ the executing method has an
+ @Transactional annotation:
+
+ @annotation(org.springframework.transaction.annotation.Transactional)
+
+ '@annotation' can also be used in a binding form :-
+ see the following section on advice for how to make the annotation
+ object available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) which
+ takes a single parameter, and where the runtime type of the
+ argument passed has the @Classified
+ annotation:
+
+ @args(com.xyz.security.Classified)
+
+ '@args' can also be used in a binding form :- see
+ the following section on advice for how to make the annotation
+ object(s) available in the advice body.
+
+
+
+ any join point (method execution only in Spring AOP) on a
+ Spring bean named 'tradeService':
+
+ bean(tradeService)
+
+
+
+ any join point (method execution only in Spring AOP) on
+ Spring beans having names that match the wildcard expression
+ '*Service':
+
+ bean(*Service)
+
+
+
+
+
+
+ Declaring advice
+
+ Advice is associated with a pointcut expression, and runs before,
+ after, or around method executions matched by the pointcut. The pointcut
+ expression may be either a simple reference to a named pointcut, or a
+ pointcut expression declared in place.
+
+
+ Before advice
+
+ Before advice is declared in an aspect using the
+ @Before annotation:
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+
+@Aspect
+public class BeforeExample {
+
+ @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
+ public void doAccessCheck() {
+ // ...
+ }
+
+}
+
+ If using an in-place pointcut expression we could rewrite the
+ above example as:
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+
+@Aspect
+public class BeforeExample {
+
+ @Before("execution(* com.xyz.myapp.dao.*.*(..))")
+ public void doAccessCheck() {
+ // ...
+ }
+
+}
+
+
+
+ After returning advice
+
+ After returning advice runs when a matched method execution
+ returns normally. It is declared using the
+ @AfterReturning annotation:
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.AfterReturning;
+
+@Aspect
+public class AfterReturningExample {
+
+ @AfterReturning("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
+ public void doAccessCheck() {
+ // ...
+ }
+
+}
+
+ Note: it is of course possible to have multiple advice
+ declarations, and other members as well, all inside the same aspect.
+ We're just showing a single advice declaration in these examples to
+ focus on the issue under discussion at the time.
+
+ Sometimes you need access in the advice body to the actual value
+ that was returned. You can use the form of
+ @AfterReturning that binds the return
+ value for this:
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.AfterReturning;
+
+@Aspect
+public class AfterReturningExample {
+
+ @AfterReturning(
+ pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
+ returning="retVal")
+ public void doAccessCheck(Object retVal) {
+ // ...
+ }
+
+}
+
+ The name used in the returning attribute must
+ correspond to the name of a parameter in the advice method. When a
+ method execution returns, the return value will be passed to the
+ advice method as the corresponding argument value. A
+ returning clause also restricts matching to only
+ those method executions that return a value of the specified type
+ (Object in this case, which will match any
+ return value).
+
+ Please note that it is not possible to
+ return a totally different reference when using after-returning
+ advice.
+
+
+
+ After throwing advice
+
+ After throwing advice runs when a matched method execution exits
+ by throwing an exception. It is declared using the
+ @AfterThrowing annotation:
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.AfterThrowing;
+
+@Aspect
+public class AfterThrowingExample {
+
+ @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
+ public void doRecoveryActions() {
+ // ...
+ }
+
+}
+
+ Often you want the advice to run only when exceptions of a given
+ type are thrown, and you also often need access to the thrown
+ exception in the advice body. Use the throwing
+ attribute to both restrict matching (if desired, use
+ Throwable as the exception type
+ otherwise) and bind the thrown exception to an advice
+ parameter.
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.AfterThrowing;
+
+@Aspect
+public class AfterThrowingExample {
+
+ @AfterThrowing(
+ pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
+ throwing="ex")
+ public void doRecoveryActions(DataAccessException ex) {
+ // ...
+ }
+
+}
+
+ The name used in the throwing attribute must
+ correspond to the name of a parameter in the advice method. When a
+ method execution exits by throwing an exception, the exception will be
+ passed to the advice method as the corresponding argument value. A
+ throwing clause also restricts matching to only
+ those method executions that throw an exception of the specified type
+ (DataAccessException in this case).
+
+
+
+ After (finally) advice
+
+ After (finally) advice runs however a matched method execution
+ exits. It is declared using the @After
+ annotation. After advice must be prepared to handle both normal and
+ exception return conditions. It is typically used for releasing
+ resources, etc.
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.After;
+
+@Aspect
+public class AfterFinallyExample {
+
+ @After("com.xyz.myapp.SystemArchitecture.dataAccessOperation()")
+ public void doReleaseLock() {
+ // ...
+ }
+
+}
+
+
+
+ Around advice
+
+ The final kind of advice is around advice. Around advice runs
+ "around" a matched method execution. It has the opportunity to do work
+ both before and after the method executes, and to determine when, how,
+ and even if, the method actually gets to execute at all. Around advice
+ is often used if you need to share state before and after a method
+ execution in a thread-safe manner (starting and stopping a timer for
+ example). Always use the least powerful form of advice that meets your
+ requirements (i.e. don't use around advice if simple before advice
+ would do).
+
+ Around advice is declared using the
+ @Around annotation. The first parameter
+ of the advice method must be of type
+ ProceedingJoinPoint. Within the body of
+ the advice, calling proceed() on the
+ ProceedingJoinPoint causes the
+ underlying method to execute. The proceed method
+ may also be called passing in an Object[] - the
+ values in the array will be used as the arguments to the method
+ execution when it proceeds.
+
+ The behavior of proceed when called with an
+ Object[] is a little different than the
+ behavior of proceed for around advice compiled by the AspectJ
+ compiler. For around advice written using the traditional AspectJ
+ language, the number of arguments passed to proceed must match the
+ number of arguments passed to the around advice (not the number of
+ arguments taken by the underlying join point), and the value passed to
+ proceed in a given argument position supplants the original value at
+ the join point for the entity the value was bound to (Don't worry if
+ this doesn't make sense right now!). The approach taken by Spring is
+ simpler and a better match to its proxy-based, execution only
+ semantics. You only need to be aware of this difference if you are
+ compiling @AspectJ aspects written for Spring and using proceed with
+ arguments with the AspectJ compiler and weaver. There is a way to
+ write such aspects that is 100% compatible across both Spring AOP and
+ AspectJ, and this is discussed in the following section on advice
+ parameters.
+
+ import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.ProceedingJoinPoint;
+
+@Aspect
+public class AroundExample {
+
+ @Around("com.xyz.myapp.SystemArchitecture.businessService()")
+ public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
+ // start stopwatch
+ Object retVal = pjp.proceed();
+ // stop stopwatch
+ return retVal;
+ }
+
+}
+
+ The value returned by the around advice will be the return value
+ seen by the caller of the method. A simple caching aspect for example
+ could return a value from a cache if it has one, and invoke proceed()
+ if it does not. Note that proceed may be invoked once, many times, or
+ not at all within the body of the around advice, all of these are
+ quite legal.
+
+
+
+ Advice parameters
+
+ Spring 2.0 offers fully typed advice - meaning that you declare
+ the parameters you need in the advice signature (as we saw for the
+ returning and throwing examples above) rather than work with
+ Object[] arrays all the time. We'll see how to
+ make argument and other contextual values available to the advice body
+ in a moment. First let's take a look at how to write generic advice
+ that can find out about the method the advice is currently
+ advising.
+
+
+ Access to the current
+ JoinPoint
+
+ Any advice method may declare as its first parameter, a
+ parameter of type
+ org.aspectj.lang.JoinPoint (please
+ note that around advice is required to declare
+ a first parameter of type
+ ProceedingJoinPoint, which is a
+ subclass of JoinPoint. The
+ JoinPoint interface provides a number
+ of useful methods such as getArgs() (returns the
+ method arguments), getThis() (returns the
+ proxy object), getTarget() (returns the
+ target object), getSignature() (returns a
+ description of the method that is being advised) and
+ toString() (prints a useful description of
+ the method being advised). Please do consult the Javadocs for full
+ details.
+
+
+
+ Passing parameters to advice
+
+ We've already seen how to bind the returned value or exception
+ value (using after returning and after throwing advice). To make
+ argument values available to the advice body, you can use the
+ binding form of args. If a parameter name is used
+ in place of a type name in an args expression, then the value of the
+ corresponding argument will be passed as the parameter value when
+ the advice is invoked. An example should make this clearer. Suppose
+ you want to advise the execution of dao operations that take an
+ Account object as the first parameter, and you need access to the
+ account in the advice body. You could write the following:
+
+ @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" +
+ "args(account,..)")
+public void validateAccount(Account account) {
+ // ...
+}
+
+ The args(account,..) part of the pointcut
+ expression serves two purposes: firstly, it restricts matching to
+ only those method executions where the method takes at least one
+ parameter, and the argument passed to that parameter is an instance
+ of Account; secondly, it makes the actual
+ Account object available to the advice via
+ the account parameter.
+
+ Another way of writing this is to declare a pointcut that
+ "provides" the Account object value when it
+ matches a join point, and then just refer to the named pointcut from
+ the advice. This would look as follows:
+
+ @Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() &&" +
+ "args(account,..)")
+private void accountDataAccessOperation(Account account) {}
+
+@Before("accountDataAccessOperation(account)")
+public void validateAccount(Account account) {
+ // ...
+}
+
+ The interested reader is once more referred to the AspectJ
+ programming guide for more details.
+
+ The proxy object (this), target object
+ (target), and annotations (@within,
+ @target, @annotation, @args) can all be bound in a similar
+ fashion. The following example shows how you could match the
+ execution of methods annotated with an
+ @Auditable annotation, and extract
+ the audit code.
+
+ First the definition of the
+ @Auditable annotation:
+
+ @Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Auditable {
+ AuditCode value();
+}
+
+ And then the advice that matches the execution of
+ @Auditable methods:
+
+ @Before("com.xyz.lib.Pointcuts.anyPublicMethod() && " +
+ "@annotation(auditable)")
+public void audit(Auditable auditable) {
+ AuditCode code = auditable.value();
+ // ...
+}
+
+
+
+ Determining argument names
+
+ The parameter binding in advice invocations relies on matching
+ names used in pointcut expressions to declared parameter names in
+ (advice and pointcut) method signatures. Parameter names are
+ not available through Java reflection, so
+ Spring AOP uses the following strategies to determine parameter
+ names:
+
+
+
+ If the parameter names have been specified by the user
+ explicitly, then the specified parameter names are used: both
+ the advice and the pointcut annotations have an optional
+ "argNames" attribute which can be used to specify the argument
+ names of the annotated method - these argument names
+ are available at runtime. For
+ example:
+
+ @Before(
+ value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
+ argNames="bean,auditable")
+public void audit(Object bean, Auditable auditable) {
+ AuditCode code = auditable.value();
+ // ... use code and bean
+}
+
+ If the first parameter is of the
+ JoinPoint,
+ ProceedingJoinPoint, or
+ JoinPoint.StaticPart type, you
+ may leave out the name of the parameter from the value of the
+ "argNames" attribute. For example, if you modify the preceding
+ advice to receive the join point object, the "argNames"
+ attribute need not include it:
+
+ @Before(
+ value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
+ argNames="bean,auditable")
+public void audit(JoinPoint jp, Object bean, Auditable auditable) {
+ AuditCode code = auditable.value();
+ // ... use code, bean, and jp
+}
+
+ The special treatment given to the first parameter of the
+ JoinPoint,
+ ProceedingJoinPoint, and
+ JoinPoint.StaticPart types is
+ particularly convenient for advice that do not collect any other
+ join point context. In such situations, you may simply omit the
+ "argNames" attribute. For example, the following advice need not
+ declare the "argNames" attribute:
+
+ @Before(
+ "com.xyz.lib.Pointcuts.anyPublicMethod()")
+public void audit(JoinPoint jp) {
+ // ... use jp
+}
+
+
+
+ Using the 'argNames' attribute is a
+ little clumsy, so if the 'argNames' attribute
+ has not been specified, then Spring AOP will look at the debug
+ information for the class and try to determine the parameter
+ names from the local variable table. This information will be
+ present as long as the classes have been compiled with debug
+ information ('-g:vars' at a minimum). The
+ consequences of compiling with this flag on are: (1) your code
+ will be slightly easier to understand (reverse engineer), (2)
+ the class file sizes will be very slightly bigger (typically
+ inconsequential), (3) the optimization to remove unused local
+ variables will not be applied by your compiler. In other words,
+ you should encounter no difficulties building with this flag
+ on.
+
+ If an @AspectJ aspect has been compiled by the AspectJ
+ compiler (ajc) even without the debug information then there is
+ no need to add the argNames attribute as the
+ compiler will retain the needed information.
+
+
+
+ If the code has been compiled without the necessary debug
+ information, then Spring AOP will attempt to deduce the pairing
+ of binding variables to parameters (for example, if only one
+ variable is bound in the pointcut expression, and the advice
+ method only takes one parameter, the pairing is obvious!). If
+ the binding of variables is ambiguous given the available
+ information, then an
+ AmbiguousBindingException will be
+ thrown.
+
+
+
+ If all of the above strategies fail then an
+ IllegalArgumentException will be
+ thrown.
+
+
+
+
+
+ Proceeding with arguments
+
+ We remarked earlier that we would describe how to write a
+ proceed call with arguments that works
+ consistently across Spring AOP and AspectJ. The solution is simply
+ to ensure that the advice signature binds each of the method
+ parameters in order. For example:
+
+ @Around("execution(List<Account> find*(..)) &&" +
+ "com.xyz.myapp.SystemArchitecture.inDataAccessLayer() && " +
+ "args(accountHolderNamePattern)")
+public Object preProcessQueryPattern(ProceedingJoinPoint pjp, String accountHolderNamePattern)
+throws Throwable {
+ String newPattern = preProcess(accountHolderNamePattern);
+ return pjp.proceed(new Object[] {newPattern});
+}
+
+
+ In many cases you will be doing this binding anyway (as in the
+ example above).
+
+
+
+
+ Advice ordering
+
+ What happens when multiple pieces of advice all want to run at
+ the same join point? Spring AOP follows the same precedence rules as
+ AspectJ to determine the order of advice execution. The highest
+ precedence advice runs first "on the way in" (so given two pieces of
+ before advice, the one with highest precedence runs first). "On the
+ way out" from a join point, the highest precedence advice runs last
+ (so given two pieces of after advice, the one with the highest
+ precedence will run second).
+
+ When two pieces of advice defined in
+ different aspects both need to run at the same
+ join point, unless you specify otherwise the order of execution is
+ undefined. You can control the order of execution by specifying
+ precedence. This is done in the normal Spring way by either
+ implementing the
+ org.springframework.core.Ordered
+ interface in the aspect class or annotating it with the
+ Order annotation. Given two aspects,
+ the aspect returning the lower value from
+ Ordered.getValue() (or the annotation value) has
+ the higher precedence.
+
+ When two pieces of advice defined in the
+ same aspect both need to run at the same join point, the
+ ordering is undefined (since there is no way to retrieve the
+ declaration order via reflection for javac-compiled classes). Consider
+ collapsing such advice methods into one advice method per join point
+ in each aspect class, or refactor the pieces of advice into separate
+ aspect classes - which can be ordered at the aspect level.
+
+
+
+
+ Introductions
+
+ Introductions (known as inter-type declarations in AspectJ) enable
+ an aspect to declare that advised objects implement a given interface,
+ and to provide an implementation of that interface on behalf of those
+ objects.
+
+ An introduction is made using the
+ @DeclareParents annotation. This
+ annotation is used to declare that matching types have a new parent
+ (hence the name). For example, given an interface
+ UsageTracked, and an implementation of
+ that interface DefaultUsageTracked, the following
+ aspect declares that all implementors of service interfaces also
+ implement the UsageTracked interface. (In
+ order to expose statistics via JMX for example.)
+
+ @Aspect
+public class UsageTracking {
+
+ @DeclareParents(value="com.xzy.myapp.service.*+",
+ defaultImpl=DefaultUsageTracked.class)
+ public static UsageTracked mixin;
+
+ @Before("com.xyz.myapp.SystemArchitecture.businessService() &&" +
+ "this(usageTracked)")
+ public void recordUsage(UsageTracked usageTracked) {
+ usageTracked.incrementUseCount();
+ }
+
+}
+
+ The interface to be implemented is determined by the type of the
+ annotated field. The value attribute of the
+ @DeclareParents annotation is an AspectJ
+ type pattern :- any bean of a matching type will implement the
+ UsageTracked interface. Note that in the before advice of the above
+ example, service beans can be directly used as implementations of the
+ UsageTracked interface. If accessing a
+ bean programmatically you would write the following:
+
+ UsageTracked usageTracked = (UsageTracked) context.getBean("myService");
+
+
+
+ Aspect instantiation models
+
+ (This is an advanced topic, so if you are just starting out with
+ AOP you can safely skip it until later.)
+
+ By default there will be a single instance of each aspect within
+ the application context. AspectJ calls this the singleton instantiation
+ model. It is possible to define aspects with alternate lifecycles :-
+ Spring supports AspectJ's perthis and
+ pertarget instantiation models (percflow,
+ percflowbelow, and pertypewithin are not
+ currently supported).
+
+ A "perthis" aspect is declared by specifying a
+ perthis clause in the
+ @Aspect annotation. Let's look at an
+ example, and then we'll explain how it works.
+
+ @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
+public class MyAspect {
+
+ private int someState;
+
+ @Before(com.xyz.myapp.SystemArchitecture.businessService())
+ public void recordServiceUsage() {
+ // ...
+ }
+
+}
+
+ The effect of the 'perthis' clause is that one
+ aspect instance will be created for each unique service object executing
+ a business service (each unique object bound to 'this' at join points
+ matched by the pointcut expression). The aspect instance is created the
+ first time that a method is invoked on the service object. The aspect
+ goes out of scope when the service object goes out of scope. Before the
+ aspect instance is created, none of the advice within it executes. As
+ soon as the aspect instance has been created, the advice declared within
+ it will execute at matched join points, but only when the service object
+ is the one this aspect is associated with. See the AspectJ programming
+ guide for more information on per-clauses.
+
+ The 'pertarget' instantiation model works in
+ exactly the same way as perthis, but creates one aspect instance for
+ each unique target object at matched join points.
+
+
+
+ Example
+
+ Now that you have seen how all the constituent parts work, let's
+ put them together to do something useful!
+
+ The execution of business services can sometimes fail due to
+ concurrency issues (for example, deadlock loser). If the operation is
+ retried, it is quite likely to succeed next time round. For business
+ services where it is appropriate to retry in such conditions (idempotent
+ operations that don't need to go back to the user for conflict
+ resolution), we'd like to transparently retry the operation to avoid the
+ client seeing a
+ PessimisticLockingFailureException. This is a
+ requirement that clearly cuts across multiple services in the service
+ layer, and hence is ideal for implementing via an aspect.
+
+ Because we want to retry the operation, we will need to use around
+ advice so that we can call proceed multiple times. Here's how the basic
+ aspect implementation looks:
+
+ @Aspect
+public class ConcurrentOperationExecutor implements Ordered {
+
+ private static final int DEFAULT_MAX_RETRIES = 2;
+
+ private int maxRetries = DEFAULT_MAX_RETRIES;
+ private int order = 1;
+
+ public void setMaxRetries(int maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public int getOrder() {
+ return this.order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ @Around("com.xyz.myapp.SystemArchitecture.businessService()")
+ public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
+ int numAttempts = 0;
+ PessimisticLockingFailureException lockFailureException;
+ do {
+ numAttempts++;
+ try {
+ return pjp.proceed();
+ }
+ catch(PessimisticLockingFailureException ex) {
+ lockFailureException = ex;
+ }
+ }
+ while(numAttempts <= this.maxRetries);
+ throw lockFailureException;
+ }
+
+}
+
+ Note that the aspect implements the
+ Ordered interface so we can set the
+ precedence of the aspect higher than the transaction advice (we want a
+ fresh transaction each time we retry). The maxRetries
+ and order properties will both be configured by
+ Spring. The main action happens in the
+ doConcurrentOperation around advice. Notice that for
+ the moment we're applying the retry logic to all
+ businessService()s. We try to proceed, and if we fail
+ with an PessimisticLockingFailureException we
+ simply try again unless we have exhausted all of our retry
+ attempts.
+
+ The corresponding Spring configuration is:
+
+ <aop:aspectj-autoproxy/>
+
+<bean id="concurrentOperationExecutor"
+ class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
+ <property name="maxRetries" value="3"/>
+ <property name="order" value="100"/>
+</bean>
+
+ To refine the aspect so that it only retries idempotent
+ operations, we might define an Idempotent
+ annotation:
+
+ @Retention(RetentionPolicy.RUNTIME)
+public @interface Idempotent {
+ // marker annotation
+}
+
+ and use the annotation to annotate the implementation of service
+ operations. The change to the aspect to only retry idempotent operations
+ simply involves refining the pointcut expression so that only
+ @Idempotent operations match:
+
+ @Around("com.xyz.myapp.SystemArchitecture.businessService() && " +
+ "@annotation(com.xyz.myapp.service.Idempotent)")
+public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
+ ...
+}
+
+
+
+
+ Schema-based AOP support
+
+ If you are unable to use Java 5, or simply prefer an XML-based
+ format, then Spring 2.0 also offers support for defining aspects using the
+ new "aop" namespace tags. The exact same pointcut expressions and advice
+ kinds are supported as when using the @AspectJ style, hence in this
+ section we will focus on the new syntax and refer the
+ reader to the discussion in the previous section () for an understanding of writing pointcut
+ expressions and the binding of advice parameters.
+
+ To use the aop namespace tags described in this section, you need to
+ import the spring-aop schema as described in . See for how to import the tags in the
+ aop namespace.
+
+ Within your Spring configurations, all aspect and advisor elements
+ must be placed within an <aop:config> element
+ (you can have more than one <aop:config> element
+ in an application context configuration). An
+ <aop:config> element can contain pointcut,
+ advisor, and aspect elements (note these must be declared in that
+ order).
+
+
+ The <aop:config> style of configuration
+ makes heavy use of Spring's auto-proxying mechanism. This can cause
+ issues (such as advice not being woven) if you are already using
+ explicit auto-proxying via the use of
+ BeanNameAutoProxyCreator or suchlike. The
+ recommended usage pattern is to use either just the
+ <aop:config> style, or just the
+ AutoProxyCreator style.
+
+
+
+ Declaring an aspect
+
+ Using the schema support, an aspect is simply a regular Java
+ object defined as a bean in your Spring application context. The state
+ and behavior is captured in the fields and methods of the object, and
+ the pointcut and advice information is captured in the XML.
+
+ An aspect is declared using the <aop:aspect> element, and
+ the backing bean is referenced using the ref
+ attribute:
+
+ <aop:config>
+ <aop:aspect id="myAspect" ref="aBean">
+ ...
+ </aop:aspect>
+</aop:config>
+
+<bean id="aBean" class="...">
+ ...
+</bean>
+
+ The bean backing the aspect ("aBean" in this
+ case) can of course be configured and dependency injected just like any
+ other Spring bean.
+
+
+
+ Declaring a pointcut
+
+ A named pointcut can be declared inside an <aop:config>
+ element, enabling the pointcut definition to be shared across several
+ aspects and advisors.
+
+ A pointcut representing the execution of any business service in
+ the service layer could be defined as follows:
+
+ <aop:config>
+
+ <aop:pointcut id="businessService"
+ expression="execution(* com.xyz.myapp.service.*.*(..))"/>
+
+</aop:config>
+
+ Note that the pointcut expression itself is using the same AspectJ
+ pointcut expression language as described in . If you are using the schema based
+ declaration style with Java 5, you can refer to named pointcuts defined
+ in types (@Aspects) within the pointcut expression, but this feature is
+ not available on JDK 1.4 and below (it relies on the Java 5 specific
+ AspectJ reflection APIs). On JDK 1.5 therefore, another way of defining
+ the above pointcut would be:
+
+ <aop:config>
+
+ <aop:pointcut id="businessService"
+ expression="com.xyz.myapp.SystemArchitecture.businessService()"/>
+
+</aop:config>
+
+ Assuming you have a SystemArchitecture aspect
+ as described in .
+
+ Declaring a pointcut inside an aspect is very similar to declaring
+ a top-level pointcut:
+
+ <aop:config>
+
+ <aop:aspect id="myAspect" ref="aBean">
+
+ <aop:pointcut id="businessService"
+ expression="execution(* com.xyz.myapp.service.*.*(..))"/>
+
+ ...
+
+ </aop:aspect>
+
+</aop:config>
+
+ Much the same way in an @AspectJ aspect, pointcuts declared using
+ the schema based definition style may collect join point context. For
+ example, the following pointcut collects the 'this' object as the join
+ point context and passes it to advice:
+
+ <aop:config>
+
+ <aop:aspect id="myAspect" ref="aBean">
+
+ <aop:pointcut id="businessService"
+ expression="execution(* com.xyz.myapp.service.*.*(..)) && this(service)"/>
+ <aop:before pointcut-ref="businessService" method="monitor"/>
+ ...
+
+ </aop:aspect>
+
+</aop:config>
+
+ The advice must be declared to receive the collected join point
+ context by including parameters of the matching names:
+
+ public void monitor(Object service) {
+ ...
+}
+
+ When combining pointcut sub-expressions, '&&' is awkward
+ within an XML document, and so the keywords 'and', 'or' and 'not' can be
+ used in place of '&&', '||' and '!' respectively. For example,
+ the previous pointcut may be better written as:
+
+ <aop:config>
+
+ <aop:aspect id="myAspect" ref="aBean">
+
+ <aop:pointcut id="businessService"
+ expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
+ <aop:before pointcut-ref="businessService" method="monitor"/>
+ ...
+
+ </aop:aspect>
+
+</aop:config>
+
+ Note that pointcuts defined in this way are referred to by their
+ XML id and cannot be used as named pointcuts to form composite
+ pointcuts. The named pointcut support in the schema based definition
+ style is thus more limited than that offered by the @AspectJ
+ style.
+
+
+
+ Declaring advice
+
+ The same five advice kinds are supported as for the @AspectJ
+ style, and they have exactly the same semantics.
+
+
+ Before advice
+
+ Before advice runs before a matched method execution. It is
+ declared inside an <aop:aspect> using the
+ <aop:before> element.
+
+ <aop:aspect id="beforeExample" ref="aBean">
+
+ <aop:before
+ pointcut-ref="dataAccessOperation"
+ method="doAccessCheck"/>
+
+ ...
+
+</aop:aspect>
+
+ Here dataAccessOperation is the id of a
+ pointcut defined at the top (<aop:config>)
+ level. To define the pointcut inline instead, replace the
+ pointcut-ref attribute with a
+ pointcut attribute:
+
+ <aop:aspect id="beforeExample" ref="aBean">
+
+ <aop:before
+ pointcut="execution(* com.xyz.myapp.dao.*.*(..))"
+ method="doAccessCheck"/>
+
+ ...
+
+</aop:aspect>
+
+ As we noted in the discussion of the @AspectJ style, using named
+ pointcuts can significantly improve the readability of your
+ code.
+
+ The method attribute identifies a method
+ (doAccessCheck) that provides the body of the
+ advice. This method must be defined for the bean referenced by the
+ aspect element containing the advice. Before a data access operation
+ is executed (a method execution join point matched by the pointcut
+ expression), the "doAccessCheck" method on the aspect bean will be
+ invoked.
+
+
+
+ After returning advice
+
+ After returning advice runs when a matched method execution
+ completes normally. It is declared inside an
+ <aop:aspect> in the same way as before
+ advice. For example:
+
+ <aop:aspect id="afterReturningExample" ref="aBean">
+
+ <aop:after-returning
+ pointcut-ref="dataAccessOperation"
+ method="doAccessCheck"/>
+
+ ...
+
+</aop:aspect>
+
+ Just as in the @AspectJ style, it is possible to get hold of the
+ return value within the advice body. Use the returning attribute to
+ specify the name of the parameter to which the return value should be
+ passed:
+
+ <aop:aspect id="afterReturningExample" ref="aBean">
+
+ <aop:after-returning
+ pointcut-ref="dataAccessOperation"
+ returning="retVal"
+ method="doAccessCheck"/>
+
+ ...
+
+</aop:aspect>
+
+ The doAccessCheck method must declare a parameter named
+ retVal. The type of this parameter constrains
+ matching in the same way as described for @AfterReturning. For
+ example, the method signature may be declared as:
+
+ public void doAccessCheck(Object retVal) {...
+
+
+
+ After throwing advice
+
+ After throwing advice executes when a matched method execution
+ exits by throwing an exception. It is declared inside an
+ <aop:aspect> using the after-throwing
+ element:
+
+ <aop:aspect id="afterThrowingExample" ref="aBean">
+
+ <aop:after-throwing
+ pointcut-ref="dataAccessOperation"
+ method="doRecoveryActions"/>
+
+ ...
+
+</aop:aspect>
+
+ Just as in the @AspectJ style, it is possible to get hold of the
+ thrown exception within the advice body. Use the throwing attribute to
+ specify the name of the parameter to which the exception should be
+ passed:
+
+ <aop:aspect id="afterThrowingExample" ref="aBean">
+
+ <aop:after-throwing
+ pointcut-ref="dataAccessOperation"
+ throwing="dataAccessEx"
+ method="doRecoveryActions"/>
+
+ ...
+
+</aop:aspect>
+
+ The doRecoveryActions method must declare a parameter named
+ dataAccessEx. The type of this parameter constrains
+ matching in the same way as described for @AfterThrowing. For example,
+ the method signature may be declared as:
+
+ public void doRecoveryActions(DataAccessException dataAccessEx) {...
+
+
+
+ After (finally) advice
+
+ After (finally) advice runs however a matched method execution
+ exits. It is declared using the after
+ element:
+
+ <aop:aspect id="afterFinallyExample" ref="aBean">
+
+ <aop:after
+ pointcut-ref="dataAccessOperation"
+ method="doReleaseLock"/>
+
+ ...
+
+</aop:aspect>
+
+
+
+ Around advice
+
+ The final kind of advice is around advice. Around advice runs
+ "around" a matched method execution. It has the opportunity to do work
+ both before and after the method executes, and to determine when, how,
+ and even if, the method actually gets to execute at all. Around advice
+ is often used if you need to share state before and after a method
+ execution in a thread-safe manner (starting and stopping a timer for
+ example). Always use the least powerful form of advice that meets your
+ requirements; don't use around advice if simple before advice would
+ do.
+
+ Around advice is declared using the
+ aop:around element. The first parameter of the
+ advice method must be of type
+ ProceedingJoinPoint. Within the body of
+ the advice, calling proceed() on the
+ ProceedingJoinPoint causes the
+ underlying method to execute. The proceed method
+ may also be calling passing in an Object[] -
+ the values in the array will be used as the arguments to the method
+ execution when it proceeds. See for notes on calling proceed
+ with an Object[].
+
+ <aop:aspect id="aroundExample" ref="aBean">
+
+ <aop:around
+ pointcut-ref="businessService"
+ method="doBasicProfiling"/>
+
+ ...
+
+</aop:aspect>
+
+ The implementation of the doBasicProfiling
+ advice would be exactly the same as in the @AspectJ example (minus the
+ annotation of course):
+
+ public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
+ // start stopwatch
+ Object retVal = pjp.proceed();
+ // stop stopwatch
+ return retVal;
+}
+
+
+
+ Advice parameters
+
+ The schema based declaration style supports fully typed advice
+ in the same way as described for the @AspectJ support - by matching
+ pointcut parameters by name against advice method parameters. See
+ for details. If you
+ wish to explicitly specify argument names for the advice methods (not
+ relying on the detection strategies previously described) then this is
+ done using the arg-names attribute of the advice
+ element, which is treated in the same manner to the "argNames"
+ attribute in an advice annotation as described in . For example:
+
+ <aop:before
+ pointcut="com.xyz.lib.Pointcuts.anyPublicMethod() and @annotation(auditable)"
+ method="audit"
+ arg-names="auditable"/>
+
+ The arg-names attribute accepts a
+ comma-delimited list of parameter names.
+
+ Find below a slightly more involved example of the XSD-based
+ approach that illustrates some around advice used in conjunction with
+ a number of strongly typed parameters.
+
+ package x.y.service;
+
+public interface FooService {
+
+ Foo getFoo(String fooName, int age);
+}
+
+public class DefaultFooService implements FooService {
+
+ public Foo getFoo(String name, int age) {
+ return new Foo(name, age);
+ }
+}
+
+ Next up is the aspect. Notice the fact that the
+ profile(..) method accepts a number of
+ strongly-typed parameters, the first of which happens to be the join
+ point used to proceed with the method call: the presence of this
+ parameter is an indication that the
+ profile(..) is to be used as
+ around advice:
+
+ package x.y;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.util.StopWatch;
+
+public class SimpleProfiler {
+
+ public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
+ StopWatch clock = new StopWatch(
+ "Profiling for '" + name + "' and '" + age + "'");
+ try {
+ clock.start(call.toShortString());
+ return call.proceed();
+ } finally {
+ clock.stop();
+ System.out.println(clock.prettyPrint());
+ }
+ }
+}
+
+ Finally, here is the XML configuration that is required to
+ effect the execution of the above advice for a particular join
+ point:
+
+ <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-2.5.xsd
+http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <!-- this is the object that will be proxied by Spring's AOP infrastructure -->
+ <bean id="fooService" class="x.y.service.DefaultFooService"/>
+
+ <!-- this is the actual advice itself -->
+ <bean id="profiler" class="x.y.SimpleProfiler"/>
+
+ <aop:config>
+ <aop:aspect ref="profiler">
+
+ <aop:pointcut id="theExecutionOfSomeFooServiceMethod"
+ expression="execution(* x.y.service.FooService.getFoo(String,int))
+ and args(name, age)"/>
+
+ <aop:around pointcut-ref="theExecutionOfSomeFooServiceMethod"
+ method="profile"/>
+
+ </aop:aspect>
+ </aop:config>
+
+</beans>
+
+ If we had the following driver script, we would get output
+ something like this on standard output:
+
+ import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import x.y.service.FooService;
+
+public final class Boot {
+
+ public static void main(final String[] args) throws Exception {
+ BeanFactory ctx = new ClassPathXmlApplicationContext("x/y/plain.xml");
+ FooService foo = (FooService) ctx.getBean("fooService");
+ foo.getFoo("Pengo", 12);
+ }
+}
+
+ StopWatch 'Profiling for 'Pengo' and '12'': running time (millis) = 0
+-----------------------------------------
+ms % Task name
+-----------------------------------------
+00000 ? execution(getFoo)
+
+
+
+ Advice ordering
+
+ When multiple advice needs to execute at the same join point
+ (executing method) the ordering rules are as described in . The precedence between
+ aspects is determined by either adding the
+ Order annotation to the bean backing
+ the aspect or by having the bean implement the
+ Ordered interface.
+
+
+
+
+ Introductions
+
+ Introductions (known as inter-type declarations in AspectJ) enable
+ an aspect to declare that advised objects implement a given interface,
+ and to provide an implementation of that interface on behalf of those
+ objects.
+
+ An introduction is made using the
+ aop:declare-parents element inside an
+ aop:aspect This element is used to declare that
+ matching types have a new parent (hence the name). For example, given an
+ interface UsageTracked, and an
+ implementation of that interface
+ DefaultUsageTracked, the following aspect
+ declares that all implementors of service interfaces also implement the
+ UsageTracked interface. (In order to
+ expose statistics via JMX for example.)
+
+ <aop:aspect id="usageTrackerAspect" ref="usageTracking">
+
+ <aop:declare-parents
+ types-matching="com.xzy.myapp.service.*+"
+ implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
+ default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
+
+ <aop:before
+ pointcut="com.xyz.myapp.SystemArchitecture.businessService()
+ and this(usageTracked)"
+ method="recordUsage"/>
+
+</aop:aspect>
+
+ The class backing the usageTracking bean would
+ contain the method:
+
+ public void recordUsage(UsageTracked usageTracked) {
+ usageTracked.incrementUseCount();
+}
+
+ The interface to be implemented is determined by
+ implement-interface attribute. The value of the
+ types-matching attribute is an AspectJ type pattern
+ :- any bean of a matching type will implement the
+ UsageTracked interface. Note that in the
+ before advice of the above example, service beans can be directly used
+ as implementations of the UsageTracked
+ interface. If accessing a bean programmatically you would write the
+ following:
+
+ UsageTracked usageTracked = (UsageTracked) context.getBean("myService");
+
+
+
+ Aspect instantiation models
+
+ The only supported instantiation model for schema-defined aspects
+ is the singleton model. Other instantiation models may be supported in
+ future releases.
+
+
+
+ Advisors
+
+ The concept of "advisors" is brought forward from the AOP support
+ defined in Spring 1.2 and does not have a direct equivalent in AspectJ.
+ An advisor is like a small self-contained aspect that has a single piece
+ of advice. The advice itself is represented by a bean, and must
+ implement one of the advice interfaces described in . Advisors can take advantage of
+ AspectJ pointcut expressions though.
+
+ Spring 2.0 supports the advisor concept with the
+ <aop:advisor> element. You will most commonly
+ see it used in conjunction with transactional advice, which also has its
+ own namespace support in Spring 2.0. Here's how it looks:
+
+ <aop:config>
+
+ <aop:pointcut id="businessService"
+ expression="execution(* com.xyz.myapp.service.*.*(..))"/>
+
+ <aop:advisor
+ pointcut-ref="businessService"
+ advice-ref="tx-advice"/>
+
+</aop:config>
+
+<tx:advice id="tx-advice">
+ <tx:attributes>
+ <tx:method name="*" propagation="REQUIRED"/>
+ </tx:attributes>
+</tx:advice>
+
+
+ As well as the pointcut-ref attribute used in the
+ above example, you can also use the pointcut attribute
+ to define a pointcut expression inline.
+
+ To define the precedence of an advisor so that the advice can
+ participate in ordering, use the order attribute to
+ define the Ordered value of the advisor.
+
+
+ Example
+
+ Let's see how the concurrent locking failure retry example from
+ looks when rewritten using the
+ schema support.
+
+ The execution of business services can sometimes fail due to
+ concurrency issues (for example, deadlock loser). If the operation is
+ retried, it is quite likely it will succeed next time round. For
+ business services where it is appropriate to retry in such conditions
+ (idempotent operations that don't need to go back to the user for
+ conflict resolution), we'd like to transparently retry the operation to
+ avoid the client seeing a
+ PessimisticLockingFailureException. This is a
+ requirement that clearly cuts across multiple services in the service
+ layer, and hence is ideal for implementing via an aspect.
+
+ Because we want to retry the operation, we'll need to use around
+ advice so that we can call proceed multiple times. Here's how the basic
+ aspect implementation looks (it's just a regular Java class using the
+ schema support):
+
+ public class ConcurrentOperationExecutor implements Ordered {
+
+ private static final int DEFAULT_MAX_RETRIES = 2;
+
+ private int maxRetries = DEFAULT_MAX_RETRIES;
+ private int order = 1;
+
+ public void setMaxRetries(int maxRetries) {
+ this.maxRetries = maxRetries;
+ }
+
+ public int getOrder() {
+ return this.order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
+ int numAttempts = 0;
+ PessimisticLockingFailureException lockFailureException;
+ do {
+ numAttempts++;
+ try {
+ return pjp.proceed();
+ }
+ catch(PessimisticLockingFailureException ex) {
+ lockFailureException = ex;
+ }
+ }
+ while(numAttempts <= this.maxRetries);
+ throw lockFailureException;
+ }
+
+}
+
+ Note that the aspect implements the
+ Ordered interface so we can set the
+ precedence of the aspect higher than the transaction advice (we want a
+ fresh transaction each time we retry). The maxRetries
+ and order properties will both be configured by
+ Spring. The main action happens in the
+ doConcurrentOperation around advice method. We try to
+ proceed, and if we fail with a
+ PessimisticLockingFailureException we simply try
+ again unless we have exhausted all of our retry attempts.
+
+ This class is identical to the one used in the @AspectJ example,
+ but with the annotations removed.
+
+ The corresponding Spring configuration is:
+
+ <aop:config>
+
+ <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
+
+ <aop:pointcut id="idempotentOperation"
+ expression="execution(* com.xyz.myapp.service.*.*(..))"/>
+
+ <aop:around
+ pointcut-ref="idempotentOperation"
+ method="doConcurrentOperation"/>
+
+ </aop:aspect>
+
+</aop:config>
+
+<bean id="concurrentOperationExecutor"
+ class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
+ <property name="maxRetries" value="3"/>
+ <property name="order" value="100"/>
+</bean>
+
+ Notice that for the time being we assume that all business
+ services are idempotent. If this is not the case we can refine the
+ aspect so that it only retries genuinely idempotent operations, by
+ introducing an Idempotent
+ annotation:
+
+ @Retention(RetentionPolicy.RUNTIME)
+public @interface Idempotent {
+ // marker annotation
+}
+
+ and using the annotation to annotate the implementation of service
+ operations. The change to the aspect to retry only idempotent operations
+ simply involves refining the pointcut expression so that only
+ @Idempotent operations match:
+
+ <aop:pointcut id="idempotentOperation"
+ expression="execution(* com.xyz.myapp.service.*.*(..)) and
+ @annotation(com.xyz.myapp.service.Idempotent)"/>
+
+
+
+
+ Choosing which AOP declaration style to use
+
+ Once you have decided that an aspect is the best approach for
+ implementing a given requirement, how do you decide between using Spring
+ AOP or AspectJ, and between the Aspect language (code) style, @AspectJ
+ annotation style, or the Spring XML style? These decisions are influenced
+ by a number of factors including application requirements, development
+ tools, and team familiarity with AOP.
+
+
+ Spring AOP or full AspectJ?
+
+ Use the simplest thing that can work. Spring AOP is simpler than
+ using full AspectJ as there is no requirement to introduce the AspectJ
+ compiler / weaver into your development and build processes. If you only
+ need to advise the execution of operations on Spring beans, then Spring
+ AOP is the right choice. If you need to advise objects not managed by
+ the Spring container (such as domain objects typically), then you will
+ need to use AspectJ. You will also need to use AspectJ if you wish to
+ advise join points other than simple method executions (for example,
+ field get or set join points, and so on).
+
+ When using AspectJ, you have the choice of the AspectJ language
+ syntax (also known as the "code style") or the @AspectJ annotation
+ style. Clearly, if you are not using Java 5+ then the choice has been
+ made for you... use the code style. If aspects play a large role in your
+ design, and you are able to use the AspectJ Development Tools
+ (AJDT) plugin for Eclipse, then the AspectJ language syntax is
+ the preferred option: it is cleaner and simpler because the language was
+ purposefully designed for writing aspects. If you are not using Eclipse,
+ or have only a few aspects that do not play a major role in your
+ application, then you may want to consider using the @AspectJ style and
+ sticking with a regular Java compilation in your IDE, and adding an
+ aspect weaving phase to your build script.
+
+
+
+ @AspectJ or XML for Spring AOP?
+
+ If you have chosen to use Spring AOP, then you have a choice of
+ @AspectJ or XML style. Clearly if you are not running on Java 5+, then
+ the XML style is the appropriate choice; for Java 5 projects there are
+ various tradeoffs to consider.
+
+ The XML style will be most familiar to existing Spring users. It
+ can be used with any JDK level (referring to named pointcuts from within
+ pointcut expressions does still require Java 5+ though) and is backed by
+ genuine POJOs. When using AOP as a tool to configure enterprise services
+ then XML can be a good choice (a good test is whether you consider the
+ pointcut expression to be a part of your configuration you might want to
+ change independently). With the XML style arguably it is clearer from
+ your configuration what aspects are present in the system.
+
+ The XML style has two disadvantages. Firstly it does not fully
+ encapsulate the implementation of the requirement it addresses in a
+ single place. The DRY principle says that there should be a single,
+ unambiguous, authoritative representation of any piece of knowledge
+ within a system. When using the XML style, the knowledge of
+ how a requirement is implemented is split across
+ the declaration of the backing bean class, and the XML in the
+ configuration file. When using the @AspectJ style there is a single
+ module - the aspect - in which this information is encapsulated.
+ Secondly, the XML style is slightly more limited in what it can express
+ than the @AspectJ style: only the "singleton" aspect instantiation model
+ is supported, and it is not possible to combine named pointcuts declared
+ in XML. For example, in the @AspectJ style you can write something
+ like:
+
+ @Pointcut(execution(* get*()))
+ public void propertyAccess() {}
+
+ @Pointcut(execution(org.xyz.Account+ *(..))
+ public void operationReturningAnAccount() {}
+
+ @Pointcut(propertyAccess() && operationReturningAnAccount())
+ public void accountPropertyAccess() {}
+
+ In the XML style I can declare the first two pointcuts:
+
+ <aop:pointcut id="propertyAccess"
+ expression="execution(* get*())"/>
+
+ <aop:pointcut id="operationReturningAnAccount"
+ expression="execution(org.xyz.Account+ *(..))"/>
+
+ The downside of the XML approach is that you cannot define the
+ 'accountPropertyAccess' pointcut by combining these
+ definitions.
+
+ The @AspectJ style supports additional instantiation models, and
+ richer pointcut composition. It has the advantage of keeping the aspect
+ as a modular unit. It also has the advantage the @AspectJ aspects can be
+ understood (and thus consumed) both by Spring AOP and by AspectJ - so if
+ you later decide you need the capabilities of AspectJ to implement
+ additional requirements then it is very easy to migrate to an
+ AspectJ-based approach. On balance the Spring team prefer the @AspectJ
+ style whenever you have aspects that do more than simple "configuration"
+ of enterprise services.
+
+
+
+
+ Mixing aspect types
+
+ It is perfectly possible to mix @AspectJ style aspects using the
+ autoproxying support, schema-defined <aop:aspect>
+ aspects, <aop:advisor> declared advisors and even
+ proxies and interceptors defined using the Spring 1.2 style in the same
+ configuration. All of these are implemented using the same underlying
+ support mechanism and will co-exist without any difficulty.
+
+
+
+ Proxying mechanisms
+
+ Spring AOP uses either JDK dynamic proxies or CGLIB to create the
+ proxy for a given target object. (JDK dynamic proxies are preferred
+ whenever you have a choice).
+
+ If the target object to be proxied implements at least one interface
+ then a JDK dynamic proxy will be used. All of the interfaces implemented
+ by the target type will be proxied. If the target object does not
+ implement any interfaces then a CGLIB proxy will be created.
+
+ If you want to force the use of CGLIB proxying (for example, to
+ proxy every method defined for the target object, not just those
+ implemented by its interfaces) you can do so. However, there are some
+ issues to consider:
+
+
+
+ final methods cannot be advised, as they
+ cannot be overriden.
+
+
+
+ You will need the CGLIB 2 binaries on your classpath, whereas
+ dynamic proxies are available with the JDK. Spring will automatically
+ warn you when it needs CGLIB and the CGLIB library classes are not
+ found on the classpath.
+
+
+
+ The constructor of your proxied object will be called twice.
+ This is a natural consequence of the CGLIB proxy model whereby a
+ subclass is generated for each proxied object. For each proxied
+ instance, two objects are created: the actual proxied object and an
+ instance of the subclass that implements the advice. This behavior is
+ not exhibited when using JDK proxies. Usually, calling the constructor
+ of the proxied type twice, is not an issue, as there are usually only
+ assignments taking place and no real logic is implemented in the
+ constructor.
+
+
+
+ To force the use of CGLIB proxies set
+ the value of the proxy-target-class attribute of the
+ <aop:config> element to true:
+
+ <aop:config proxy-target-class="true">
+ <!-- other beans defined here... -->
+</aop:config>
+
+ To force CGLIB proxying when using the @AspectJ autoproxy support,
+ set the 'proxy-target-class' attribute of the
+ <aop:aspectj-autoproxy> element to
+ true:
+
+ <aop:aspectj-autoproxy proxy-target-class="true"/>
+
+
+ Multiple <aop:config/> sections are
+ collapsed into a single unified auto-proxy creator at runtime, which
+ applies the strongest proxy settings that any of
+ the <aop:config/> sections (typically from
+ different XML bean definition files) specified. This also applies to the
+ <tx:annotation-driven/> and
+ <aop:aspectj-autoproxy/> elements.
+
+ To be clear: using 'proxy-target-class="true"'
+ on <tx:annotation-driven/>,
+ <aop:aspectj-autoproxy/> or
+ <aop:config/> elements will force the use of
+ CGLIB proxies for all three of them.
+
+
+
+ Understanding AOP proxies
+
+ Spring AOP is proxy-based. It is vitally
+ important that you grasp the semantics of what that last statement
+ actually means before you write your own aspects or use any of the
+ Spring AOP-based aspects supplied with the Spring Framework.
+
+ Consider first the scenario where you have a plain-vanilla,
+ un-proxied, nothing-special-about-it, straight object reference, as
+ illustrated by the following code snippet.
+
+ public class SimplePojo implements Pojo {
+
+ public void foo() {
+ // this next method invocation is a direct call on the 'this' reference
+ this.bar();
+ }
+
+ public void bar() {
+ // some logic...
+ }
+}
+
+ If you invoke a method on an object reference, the method is
+ invoked directly on that object reference, as can
+ be seen below.
+
+
+
+
+
+
+
+
+
+
+
+ public class Main {
+
+ public static void main(String[] args) {
+
+ Pojo pojo = new SimplePojo();
+
+ // this is a direct method call on the 'pojo' reference
+ pojo.foo();
+ }
+}
+
+ Things change slightly when the reference that client code has is
+ a proxy. Consider the following diagram and code snippet.
+
+
+
+
+
+
+
+
+
+
+
+ public class Main {
+
+ public static void main(String[] args) {
+
+ ProxyFactory factory = new ProxyFactory(new SimplePojo());
+ factory.addInterface(Pojo.class);
+ factory.addAdvice(new RetryAdvice());
+
+ Pojo pojo = (Pojo) factory.getProxy();
+
+ // this is a method call on the proxy!
+ pojo.foo();
+ }
+}
+
+ The key thing to understand here is that the client code inside
+ the main(..) of the Main
+ class has a reference to the proxy. This means that
+ method calls on that object reference will be calls on the proxy, and as
+ such the proxy will be able to delegate to all of the interceptors
+ (advice) that are relevant to that particular method call. However, once
+ the call has finally reached the target object, the
+ SimplePojo reference in this case, any method
+ calls that it may make on itself, such as
+ this.bar() or
+ this.foo(), are going to be invoked against the
+ this reference, and
+ not the proxy. This has important implications. It
+ means that self-invocation is not going to result
+ in the advice associated with a method invocation getting a chance to
+ execute.
+
+ Okay, so what is to be done about this? The best approach (the
+ term best is used loosely here) is to refactor your code such that the
+ self-invocation does not happen. For sure, this does entail some work on
+ your part, but it is the best, least-invasive approach. The next
+ approach is absolutely horrendous, and I am almost reticent to point it
+ out precisely because it is so horrendous. You can (choke!) totally tie
+ the logic within your class to Spring AOP by doing this:
+
+ public class SimplePojo implements Pojo {
+
+ public void foo() {
+ // this works, but... gah!
+ ((Pojo) AopContext.currentProxy()).bar();
+ }
+
+ public void bar() {
+ // some logic...
+ }
+}
+
+ This totally couples your code to Spring AOP,
+ and it makes the class itself aware of the fact
+ that it is being used in an AOP context, which flies in the face of AOP.
+ It also requires some additional configuration when the proxy is being
+ created:
+
+ public class Main {
+
+ public static void main(String[] args) {
+
+ ProxyFactory factory = new ProxyFactory(new SimplePojo());
+ factory.adddInterface(Pojo.class);
+ factory.addAdvice(new RetryAdvice());
+ factory.setExposeProxy(true);
+
+ Pojo pojo = (Pojo) factory.getProxy();
+
+ // this is a method call on the proxy!
+ pojo.foo();
+ }
+}
+
+ Finally, it must be noted that AspectJ does not have this
+ self-invocation issue because it is not a proxy-based AOP
+ framework.
+
+
+
+
+ Programmatic creation of @AspectJ Proxies
+
+ In addition to declaring aspects in your configuration using either
+ <aop:config> or
+ <aop:aspectj-autoproxy>, it is also possible
+ programmatically to create proxies that advise target objects. For the
+ full details of Spring's AOP API, see the next chapter. Here we want to
+ focus on the ability to automatically create proxies using @AspectJ
+ aspects.
+
+ The class
+ org.springframework.aop.aspectj.annotation.AspectJProxyFactory
+ can be used to create a proxy for a target object that is advised by one
+ or more @AspectJ aspects. Basic usage for this class is very simple, as
+ illustrated below. See the Javadocs for full information.
+
+ // create a factory that can generate a proxy for the given target object
+AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);
+
+// add an aspect, the class must be an @AspectJ aspect
+// you can call this as many times as you need with different aspects
+factory.addAspect(SecurityManager.class);
+
+// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect
+factory.addAspect(usageTracker);
+
+// now get the proxy object...
+MyInterfaceType proxy = factory.getProxy();
+
+
+
+ Using AspectJ with Spring applications
+
+ Everything we've covered so far in this chapter is pure Spring AOP.
+ In this section, we're going to look at how you can use the AspectJ
+ compiler/weaver instead of, or in addition to, Spring AOP if your needs go
+ beyond the facilities offered by Spring AOP alone.
+
+ Spring ships with a small AspectJ aspect library, which is available
+ standalone in your distribution as spring-aspects.jar; you'll need to add this
+ to your classpath in order to use the aspects in it. and
+ discuss the content of this library and how you can use it. discusses how to dependency inject AspectJ
+ aspects that are woven using the AspectJ compiler. Finally, provides an introduction to load-time weaving for
+ Spring applications using AspectJ.
+
+
+ Using AspectJ to dependency inject domain objects with
+ Spring
+
+ The Spring container instantiates and configures beans defined in
+ your application context. It is also possible to ask a bean factory to
+ configure a pre-existing object given the name of a
+ bean definition containing the configuration to be applied. The
+ spring-aspects.jar contains an
+ annotation-driven aspect that exploits this capability to allow
+ dependency injection of any object. The support is
+ intended to be used for objects created outside of the control
+ of any container. Domain objects often fall into this
+ category because they are often created programmatically using the
+ new operator, or by an ORM tool as a result of a
+ database query.
+
+ The @Configurable annotation marks
+ a class as eligible for Spring-driven configuration. In the simplest
+ case it can be used just as a marker annotation:
+
+ package com.xyz.myapp.domain;
+
+import org.springframework.beans.factory.annotation.Configurable;
+
+@Configurable
+public class Account {
+ // ...
+}
+
+ When used as a marker interface in this way, Spring will configure
+ new instances of the annotated type (Account in
+ this case) using a prototype-scoped bean definition with the same name
+ as the fully-qualified type name
+ (com.xyz.myapp.domain.Account). Since the default
+ name for a bean is the fully-qualified name of its type, a convenient
+ way to declare the prototype definition is simply to omit the
+ id attribute:
+
+ <bean class="com.xyz.myapp.domain.Account" scope="prototype">
+ <property name="fundsTransferService" ref="fundsTransferService"/>
+</bean>
+
+ If you want to explicitly specify the name of the prototype bean
+ definition to use, you can do so directly in the annotation:
+
+ package com.xyz.myapp.domain;
+
+import org.springframework.beans.factory.annotation.Configurable;
+
+@Configurable("account")
+public class Account {
+ // ...
+}
+
+ Spring will now look for a bean definition named
+ "account" and use that as the definition to configure
+ new Account instances.
+
+ You can also use autowiring to avoid having to specify a
+ prototype-scoped bean definition at all. To have Spring apply autowiring
+ use the 'autowire' property of the
+ @Configurable annotation: specify either
+ @Configurable(autowire=Autowire.BY_TYPE) or
+ @Configurable(autowire=Autowire.BY_NAME for
+ autowiring by type or by name respectively. As an alternative, as of
+ Spring 2.5 it is preferable to specify explicit, annotation-driven
+ dependency injection for your @Configurable
+ beans by using @Autowired and
+ @Resource at the field or method level (see
+ for further details).
+
+ Finally you can enable Spring dependency checking for the object
+ references in the newly created and configured object by using the
+ dependencyCheck attribute (for example:
+ @Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)).
+ If this attribute is set to true, then Spring will validate after
+ configuration that all properties (which are not primitives or
+ collections) have been set.
+
+ Using the annotation on its own does nothing of course. It is the
+ AnnotationBeanConfigurerAspect in spring-aspects.jar that acts on the
+ presence of the annotation. In essence the aspect says "after returning
+ from the initialization of a new object of a type annotated with
+ @Configurable, configure the newly
+ created object using Spring in accordance with the properties of the
+ annotation". In this context, initialization refers
+ to newly instantiated objects (e.g., objects instantiated with the
+ 'new' operator) as well as to
+ Serializable objects that are undergoing
+ deserialization (e.g., via readResolve()).
+
+
+ One of the key phrases in the above paragraph is 'in
+ essence'. For most cases, the exact semantics of
+ 'after returning from the initialization of a new
+ object' will be fine... in this context, 'after
+ initialization' means that the dependencies will be
+ injected after the object has been constructed -
+ this means that the dependencies will not be available for use in the
+ constructor bodies of the class. If you want the dependencies to be
+ injected before the constructor bodies execute,
+ and thus be available for use in the body of the constructors, then
+ you need to define this on the
+ @Configurable declaration like
+ so:
+
+ @Configurable(preConstruction=true)
+
+ You can find out more information about the language semantics
+ of the various pointcut types in AspectJ in
+ this appendix of the AspectJ
+ Programming Guide.
+
+
+ For this to work the annotated types must be woven with the
+ AspectJ weaver - you can either use a build-time Ant or Maven task to do
+ this (see for example the AspectJ
+ Development Environment Guide) or load-time weaving (see ). The
+ AnnotationBeanConfigurerAspect itself needs
+ configuring by Spring (in order to obtain a reference to the bean
+ factory that is to be used to configure new objects). The Spring context
+ namespace defines a convenient tag for doing this: just include
+ the following in your application context configuration:
+
+ <context:spring-configured/>
+
+ If you are using the DTD instead of schema, the equivalent
+ definition is:
+
+ <bean
+ class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"
+ factory-method="aspectOf"/>
+
+ Instances of @Configurable objects
+ created before the aspect has been configured will
+ result in a warning being issued to the log and no configuration of the
+ object taking place. An example might be a bean in the Spring
+ configuration that creates domain objects when it is initialized by
+ Spring. In this case you can use the "depends-on" bean attribute to
+ manually specify that the bean depends on the configuration
+ aspect.
+
+ <bean id="myService"
+ class="com.xzy.myapp.service.MyService"
+ depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
+
+ <!-- ... -->
+
+</bean>
+
+
+ Unit testing @Configurable
+ objects
+
+ One of the goals of the
+ @Configurable support is to enable
+ independent unit testing of domain objects without the difficulties
+ associated with hard-coded lookups. If
+ @Configurable types have not been woven
+ by AspectJ then the annotation has no affect during unit testing, and
+ you can simply set mock or stub property references in the object
+ under test and proceed as normal. If
+ @Configurable types
+ have been woven by AspectJ then you can still
+ unit test outside of the container as normal, but you will see a
+ warning message each time that you construct an
+ @Configurable object indicating that it
+ has not been configured by Spring.
+
+
+
+ Working with multiple application contexts
+
+ The AnnotationBeanConfigurerAspect used
+ to implement the @Configurable support
+ is an AspectJ singleton aspect. The scope of a singleton aspect is the
+ same as the scope of static members, that is to say
+ there is one aspect instance per classloader that defines the type.
+ This means that if you define multiple application contexts within the
+ same classloader hierarchy you need to consider where to define the
+ <context:spring-configured/> bean and where to
+ place spring-aspects.jar on
+ the classpath.
+
+ Consider a typical Spring web-app configuration with a shared
+ parent application context defining common business services and
+ everything needed to support them, and one child application context
+ per servlet containing definitions particular to that servlet. All of
+ these contexts will co-exist within the same classloader hierarchy,
+ and so the AnnotationBeanConfigurerAspect can only
+ hold a reference to one of them. In this case we recommend defining
+ the <context:spring-configured/> bean in the
+ shared (parent) application context: this defines the services that
+ you are likely to want to inject into domain objects. A consequence is
+ that you cannot configure domain objects with references to beans
+ defined in the child (servlet-specific) contexts using the
+ @Configurable mechanism (probably not something you want to do
+ anyway!).
+
+ When deploying multiple web-apps within the same container,
+ ensure that each web-application loads the types in spring-aspects.jar using its own
+ classloader (for example, by placing spring-aspects.jar in 'WEB-INF/lib'). If spring-aspects.jar is only added to the
+ container wide classpath (and hence loaded by the shared parent
+ classloader), all web applications will share the same aspect instance
+ which is probably not what you want.
+
+
+
+
+ Other Spring aspects for AspectJ
+
+ In addition to the @Configurable
+ aspect, spring-aspects.jar
+ contains an AspectJ aspect that can be used to drive Spring's
+ transaction management for types and methods annotated with the
+ @Transactional annotation. This is
+ primarily intended for users who want to use the Spring Framework's
+ transaction support outside of the Spring container.
+
+ The aspect that interprets
+ @Transactional annotations is the
+ AnnotationTransactionAspect. When using this
+ aspect, you must annotate the implementation class
+ (and/or methods within that class), not the
+ interface (if any) that the class implements. AspectJ follows Java's
+ rule that annotations on interfaces are not
+ inherited.
+
+ A @Transactional annotation on a
+ class specifies the default transaction semantics for the execution of
+ any public operation in the class.
+
+ A @Transactional annotation on a
+ method within the class overrides the default transaction semantics
+ given by the class annotation (if present). Methods with
+ public, protected, and default
+ visibility may all be annotated. Annotating protected
+ and default visibility methods directly is the only way to get
+ transaction demarcation for the execution of such methods.
+
+ For AspectJ programmers that want to use the Spring configuration
+ and transaction management support but don't want to (or cannot) use
+ annotations, spring-aspects.jar
+ also contains abstract aspects you can extend to
+ provide your own pointcut definitions. See the sources for the
+ AbstractBeanConfigurerAspect and
+ AbstractTransactionAspect aspects for more
+ information. As an example, the following excerpt shows how you could
+ write an aspect to configure all instances of objects defined in the
+ domain model using prototype bean definitions that match the
+ fully-qualified class names:
+
+ public aspect DomainObjectConfiguration extends AbstractBeanConfigurerAspect {
+
+ public DomainObjectConfiguration() {
+ setBeanWiringInfoResolver(new ClassNameBeanWiringInfoResolver());
+ }
+
+ // the creation of a new bean (any object in the domain model)
+ protected pointcut beanCreation(Object beanInstance) :
+ initialization(new(..)) &&
+ SystemArchitecture.inDomainModel() &&
+ this(beanInstance);
+
+}
+
+
+
+ Configuring AspectJ aspects using Spring IoC
+
+ When using AspectJ aspects with Spring applications, it is natural
+ to both want and expect to be able to configure such aspects using
+ Spring. The AspectJ runtime itself is responsible for aspect creation,
+ and the means of configuring the AspectJ created aspects via Spring
+ depends on the AspectJ instantiation model (the
+ 'per-xxx' clause) used by the aspect.
+
+ The majority of AspectJ aspects are singleton
+ aspects. Configuration of these aspects is very easy: simply create a
+ bean definition referencing the aspect type as normal, and include the
+ bean attribute 'factory-method="aspectOf"'. This
+ ensures that Spring obtains the aspect instance by asking AspectJ for it
+ rather than trying to create an instance itself. For example:
+
+ <bean id="profiler" class="com.xyz.profiler.Profiler"
+ factory-method="aspectOf">
+ <property name="profilingStrategy" ref="jamonProfilingStrategy"/>
+</bean>
+
+ Non-singleton aspects are harder to configure: however it is
+ possible to do so by creating prototype bean definitions and using the
+ @Configurable support from spring-aspects.jar to configure the
+ aspect instances once they have bean created by the AspectJ
+ runtime.
+
+ If you have some @AspectJ aspects that you want to weave with
+ AspectJ (for example, using load-time weaving for domain model types)
+ and other @AspectJ aspects that you want to use with Spring AOP, and
+ these aspects are all configured using Spring, then you will need to
+ tell the Spring AOP @AspectJ autoproxying support which exact subset of
+ the @AspectJ aspects defined in the configuration should be used for
+ autoproxying. You can do this by using one or more
+ <include/> elements inside the
+ <aop:aspectj-autoproxy/> declaration. Each
+ <include/> element specifies a name pattern,
+ and only beans with names matched by at least one of the patterns will
+ be used for Spring AOP autoproxy configuration:
+
+ <aop:aspectj-autoproxy>
+ <aop:include name="thisBean"/>
+ <aop:include name="thatBean"/>
+</aop:aspectj-autoproxy>
+
+
+ Do not be misled by the name of the
+ <aop:aspectj-autoproxy/> element: using it
+ will result in the creation of Spring AOP
+ proxies. The @AspectJ style of aspect declaration is just
+ being used here, but the AspectJ runtime is not
+ involved.
+
+
+
+
+ Load-time weaving with AspectJ in the Spring Framework
+
+ Load-time weaving (LTW) refers to the process of weaving AspectJ
+ aspects into an application's class files as they are being loaded into
+ the Java virtual machine (JVM). The focus of this section is on
+ configuring and using LTW in the specific context of the Spring
+ Framework: this section is not an introduction to LTW though. For full
+ details on the specifics of LTW and configuring LTW with just AspectJ
+ (with Spring not being involved at all), see the LTW
+ section of the AspectJ Development Environment Guide.
+
+ The value-add that the Spring Framework brings to AspectJ LTW is
+ in enabling much finer-grained control over the weaving process.
+ 'Vanilla' AspectJ LTW is effected using a Java (5+) agent, which is
+ switched on by specifying a VM argument when starting up a JVM. It is
+ thus a JVM-wide setting, which may be fine in some situations, but often
+ is a little too coarse. Spring-enabled LTW enables you to switch on LTW
+ on a per-ClassLoader basis,
+ which obviously is more fine-grained and which can make more sense in a
+ 'single-JVM-multiple-application' environment (such as is found in a
+ typical application server environment).
+
+ Further, in certain
+ environments, this support enables load-time weaving
+ without making any modifications to the application server's
+ launch script that will be needed to add
+ -javaagent:path/to/aspectjweaver.jar or (as we describe later in this
+ section) -javaagent:path/to/spring-agent.jar. Developers simply modify
+ one or more files that form the application context to enable load-time
+ weaving instead of relying on administrators who typically are in charge
+ of the deployment configuration such as the launch script.
+
+ Now that the sales pitch is over, let us first walk through a
+ quick example of AspectJ LTW using Spring, followed by detailed
+ specifics about elements introduced in the following example. For a
+ complete example, please see the Petclinic sample application.
+
+
+ A first example
+
+ Let us assume that you are an application developer who has been
+ tasked with diagnosing the cause of some performance problems in a
+ system. Rather than break out a profiling tool, what we are going to
+ do is switch on a simple profiling aspect that will enable us to very
+ quickly get some performance metrics, so that we can then apply a
+ finer-grained profiling tool to that specific area immediately
+ afterwards.
+
+ Here is the profiling aspect. Nothing too fancy, just a
+ quick-and-dirty time-based profiler, using the @AspectJ-style of
+ aspect declaration.
+
+ package foo;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.util.StopWatch;
+import org.springframework.core.annotation.Order;
+
+@Aspect
+public class ProfilingAspect {
+
+ @Around("methodsToBeProfiled()")
+ public Object profile(ProceedingJoinPoint pjp) throws Throwable {
+ StopWatch sw = new StopWatch(getClass().getSimpleName());
+ try {
+ sw.start(pjp.getSignature().getName());
+ return pjp.proceed();
+ } finally {
+ sw.stop();
+ System.out.println(sw.prettyPrint());
+ }
+ }
+
+ @Pointcut("execution(public * foo..*.*(..))")
+ public void methodsToBeProfiled(){}
+}
+
+
+ We will also need to create an
+ 'META-INF/aop.xml' file, to inform the AspectJ
+ weaver that we want to weave our
+ ProfilingAspect into our classes. This file
+ convention, namely the presence of a file (or files) on the Java
+ classpath called ' META-INF/aop.xml' is standard
+ AspectJ.
+
+ <!DOCTYPE aspectj PUBLIC
+ "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
+<aspectj>
+
+ <weaver>
+
+ <!-- only weave classes in our application-specific packages -->
+ <include within="foo.*"/>
+
+ </weaver>
+
+ <aspects>
+
+ <!-- weave in just this aspect -->
+ <aspect name="foo.ProfilingAspect"/>
+
+ </aspects>
+
+ </aspectj>
+
+ Now to the Spring-specific portion of the configuration. We need
+ to configure a LoadTimeWeaver (all
+ explained later, just take it on trust for now). This load-time weaver
+ is the essential component responsible for weaving the aspect
+ configuration in one or more 'META-INF/aop.xml'
+ files into the classes in your application. The good thing is that it
+ does not require a lot of configuration, as can be seen below (there
+ are some more options that you can specify, but these are detailed
+ later).
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <!-- a service object; we will be profiling its methods -->
+ <bean id="entitlementCalculationService"
+ class="foo.StubEntitlementCalculationService"/>
+
+ <!-- this switches on the load-time weaving -->
+ <context:load-time-weaver/>
+
+</beans>
+
+ Now that all the required artifacts are in place - the aspect,
+ the 'META-INF/aop.xml' file, and the Spring
+ configuration -, let us create a simple driver class with a
+ main(..) method to demonstrate the LTW in
+ action.
+
+ package foo;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public final class Main {
+
+ public static void main(String[] args) {
+
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class);
+
+ EntitlementCalculationService entitlementCalculationService
+ = (EntitlementCalculationService) ctx.getBean("entitlementCalculationService");
+
+ // the profiling aspect is 'woven' around this method execution
+ entitlementCalculationService.calculateEntitlement();
+ }
+}
+
+ There is one last thing to do. The introduction to this section
+ did say that one could switch on LTW selectively on a
+ per-ClassLoader basis with Spring, and this is
+ true. However, just for this example, we are going to use a Java agent
+ (supplied with Spring) to switch on the LTW. This is the command line
+ we will use to run the above Main class:
+
+ java -javaagent:C:/projects/foo/lib/global/spring-agent.jar foo.Main
+
+ The '-javaagent' is a Java 5+ flag for
+ specifying and enabling agents
+ to instrument programs running on the JVM. The Spring
+ Framework ships with such an agent, the
+ InstrumentationSavingAgent, which is packaged
+ in the spring-agent.jar that
+ was supplied as the value of the -javaagent
+ argument in the above example.
+
+ The output from the execution of the Main
+ program will look something like that below. (I have introduced a
+ Thread.sleep(..) statement into the
+ calculateEntitlement() implementation so that
+ the profiler actually captures something other than 0 milliseconds -
+ the 01234 milliseconds is not
+ an overhead introduced by the AOP :) )
+
+ Calculating entitlement
+
+StopWatch 'ProfilingAspect': running time (millis) = 1234
+------ ----- ----------------------------
+ms % Task name
+------ ----- ----------------------------
+01234 100% calculateEntitlement
+
+ Since this LTW is effected using full-blown AspectJ, we are not
+ just limited to advising Spring beans; the following slight variation
+ on the Main program will yield the same
+ result.
+
+ package foo;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public final class Main {
+
+ public static void main(String[] args) {
+
+ new ClassPathXmlApplicationContext("beans.xml", Main.class);
+
+ EntitlementCalculationService entitlementCalculationService =
+ new StubEntitlementCalculationService();
+
+ // the profiling aspect will be 'woven' around this method execution
+ entitlementCalculationService.calculateEntitlement();
+ }
+}
+
+ Notice how in the above program we are simply bootstrapping the
+ Spring container, and then creating a new instance of the
+ StubEntitlementCalculationService totally
+ outside the context of Spring... the profiling advice still gets woven
+ in.
+
+ The example admittedly is simplistic... however the basics of
+ the LTW support in Spring have all been introduced in the above
+ example, and the rest of this section will explain the 'why' behind
+ each bit of configuration and usage in detail.
+
+
+ The ProfilingAspect used in this
+ example may be basic, but it is quite useful. It is a nice example
+ of a development-time aspect that developers can use during
+ development (of course), and then quite easily exclude from builds
+ of the application being deployed into UAT or production.
+
+
+
+
+ Aspects
+
+ The aspects that you use in LTW have to be AspectJ aspects. They
+ can be written in either the AspectJ language itself or you can write
+ your aspects in the @AspectJ-style. The latter option is of course
+ only an option if you are using Java 5+, but it does mean that your
+ aspects are then both valid AspectJ and Spring
+ AOP aspects. Furthermore, the compiled aspect classes need to be
+ available on the classpath.
+
+
+
+ 'META-INF/aop.xml'
+
+ The AspectJ LTW infrastructure is configured using one or more
+ 'META-INF/aop.xml' files, that are on the Java
+ classpath (either directly, or more typically in jar files).
+
+ The structure and contents of this file is detailed in the main
+ AspectJ reference documentation, and the interested reader is referred
+ to that resource. (I appreciate that this section is brief,
+ but the 'aop.xml' file is 100% AspectJ - there is
+ no Spring-specific information or semantics that apply to it, and so
+ there is no extra value that I can contribute either as a result), so
+ rather than rehash the quite satisfactory section that the AspectJ
+ developers wrote, I am just directing you there.)
+
+
+
+ Required libraries (JARS)
+
+ At a minimum you will need the following libraries to use the
+ Spring Framework's support for AspectJ LTW:
+
+
+
+ spring.jar (version
+ 2.5 or later)
+
+
+
+ aspectjrt.jar
+ (version 1.5 or later)
+
+
+
+ aspectjweaver.jar
+ (version 1.5 or later)
+
+
+
+ If you are using the Spring-provided agent to
+ enable instrumentation, you will also need:
+
+
+
+ spring-agent.jar
+
+
+
+
+
+ Spring configuration
+
+ The key component in Spring's LTW support is the
+ LoadTimeWeaver interface (in the
+ org.springframework.instrument.classloading
+ package), and the numerous implementations of it that ship with the
+ Spring distribution. A LoadTimeWeaver
+ is responsible for adding one or more
+ java.lang.instrument.ClassFileTransformers to a
+ ClassLoader at runtime, which opens the door to
+ all manner of interesting applications, one of which happens to be the
+ LTW of aspects.
+
+
+ If you are unfamiliar with the idea of runtime class file
+ transformation, you are encouraged to read the Javadoc API
+ documentation for the java.lang.instrument
+ package before continuing. This is not a huge chore because there is
+ - rather annoyingly - precious little documentation there... the key
+ interfaces and classes will at least be laid out in front of you for
+ reference as you read through this section.
+
+
+ Configuring a LoadTimeWeaver
+ using XML for a particular
+ ApplicationContext can be as easy as
+ adding one line. (Please note that you almost certainly will need to
+ be using an ApplicationContext as your
+ Spring container - typically a
+ BeanFactory will not be enough because
+ the LTW support makes use of
+ BeanFactoryPostProcessors.)
+
+ To enable the Spring Framework's LTW support, you need to
+ configure a LoadTimeWeaver, which
+ typically is done using the
+ <context:load-time-weaver/> element. Find
+ below a valid <context:load-time-weaver/>
+ definition that uses default settings.
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:load-time-weaver/>
+
+</beans>
+
+ The above <context:load-time-weaver/>
+ bean definition will define and register a number of LTW-specific
+ infrastructure beans for you automatically, such as a
+ LoadTimeWeaver and an
+ AspectJWeavingEnabler. Notice how the
+ <context:load-time-weaver/> is defined in the
+ 'context' namespace; note also that the referenced
+ XML Schema file is only available in versions of Spring 2.5 and
+ later.
+
+ What the above configuration does is define and register a
+ default LoadTimeWeaver bean for you.
+ The default LoadTimeWeaver is the
+ DefaultContextLoadTimeWeaver class, which
+ attempts to decorate an automatically detected
+ LoadTimeWeaver: the exact type of
+ LoadTimeWeaver that will be
+ 'automatically detected' is dependent upon your runtime environment
+ (summarised in the following table).
+
+
+ DefaultContextLoadTimeWeaver
+ LoadTimeWeavers
+
+
+
+
+
+
+ Runtime Environment
+ LoadTimeWeaver implementation
+
+
+
+
+
+ Running in BEA's
+ Weblogic 10
+ WebLogicLoadTimeWeaver
+
+
+
+ Running in Oracle's
+ OC4J
+ OC4JLoadTimeWeaver
+
+
+
+ Running in GlassFish
+ GlassFishLoadTimeWeaver
+
+
+
+ JVM started with Spring
+ InstrumentationSavingAgent
+ (java
+ -javaagent:path/to/spring-agent.jar)
+ InstrumentationLoadTimeWeaver
+
+
+
+ Fallback, expecting the underlying ClassLoader to follow common conventions
+ (e.g. applicable to TomcatInstrumentableClassLoader and to Resin)
+ ReflectiveLoadTimeWeaver
+
+
+
+
+
+ Note that these are just the
+ LoadTimeWeavers that are autodetected
+ when using the DefaultContextLoadTimeWeaver: it
+ is of course possible to specify exactly which
+ LoadTimeWeaver implementation that you
+ wish to use by specifying the fully-qualified classname as the value
+ of the 'weaver-class' attribute of the
+ <context:load-time-weaver/> element. Find
+ below an example of doing just that:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:load-time-weaver
+ weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
+
+</beans>
+
+ The LoadTimeWeaver that is
+ defined and registered by the
+ <context:load-time-weaver/> element can be
+ later retrieved from the Spring container using the well-known name
+ 'loadTimeWeaver'. Remember that the
+ LoadTimeWeaver exists just as a
+ mechanism for Spring's LTW infrastructure to add one or more
+ ClassFileTransformers. The actual
+ ClassFileTransformer that does the LTW is the
+ ClassPreProcessorAgentAdapter (from the
+ org.aspectj.weaver.loadtime package) class. See the
+ class-level Javadoc for the
+ ClassPreProcessorAgentAdapter class for further
+ details, because the specifics of how the weaving is actually effected
+ is beyond the scope of this section.
+
+ There is one final attribute of the
+ <context:load-time-weaver/> left to discuss:
+ the 'aspectj-weaving' attribute. This is a simple
+ attribute that controls whether LTW is enabled or not, it is as simple
+ as that. It accepts one of three possible values, summarised below,
+ with the default value if the attribute is not present being '
+ autodetect'
+
+
+ 'aspectj-weaving' attribute values
+
+
+
+
+
+
+ Attribute Value
+ Explanation
+
+
+
+
+
+ on
+ AspectJ weaving is on, and aspects will be woven
+ at load-time as appropriate.
+
+
+
+ off
+ LTW is off... no aspect will be woven at
+ load-time.
+
+
+
+ autodetect
+ If the Spring LTW infrastructure can find at
+ least one 'META-INF/aop.xml' file, then
+ AspectJ weaving is on, else it is off. This is the default
+ value.
+
+
+
+
+
+
+
+ Environment-specific configuration
+
+ This last section contains any additional settings and
+ configuration that you will need when using Spring's LTW support in
+ environments such as application servers and web containers.
+
+
+ Generic Java applications
+
+ You may enable Spring's support for LTW in any Java application
+ (standalone as well as application server based) through the use of
+ the Spring-provided instrumentation agent. To do so, start
+ the VM by by specifying the
+ -javaagent:path/to/spring-agent.jar option.
+ Note that this requires modification of the VM launch script
+ which may prevent you from using this in application server
+ environments (depending on your operation policies).
+
+
+
+ Tomcat
+
+ For web applications deployed onto Apache Tomcat 5.0 and above,
+ Spring provides a TomcatInstrumentableClassLoader
+ to be registered as the web app class loader. The required Tomcat setup
+ looks as follows, to be included either in Tomcat's central
+ server.xml file or in an application-specific
+ META-INF/context.xml file within the WAR root.
+ Spring's spring-tomcat-weaver.jar needs to be
+ included in Tomcat's common lib directory in order to make this
+ setup work.
+
+ <Context path="/myWebApp" docBase="/my/webApp/location">
+ <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
+ useSystemClassLoaderAsParent="false"/>
+</Context>
+
+
+ Note: We generally recommend Tomcat 5.5.20 or above
+ when enabling load-time weaving. Prior versions have known
+ issues with custom ClassLoader setup.
+
+ Alternatively, consider the use of the Spring-provided generic
+ VM agent, to be specified in Tomcat's launch script (see above).
+ This will make instrumentation available to all deployed web
+ applications, no matter which ClassLoader they happen to run on.
+
+ For a more detailed discussion of Tomcat-based weaving setup,
+ check out the section
+ which discusses specifics of various Tomcat versions. While the primary
+ focus of that section is on JPA persistence provider setup, the Tomcat
+ setup characteristics apply to general load-time weaving as well.
+
+
+
+ WebLogic, OC4J, Resin, GlassFish
+
+ Recent versions of BEA WebLogic (version 10 and above), Oracle
+ Containers for Java EE (OC4J 10.1.3.1 and above) and Resin (3.1 and above)
+ provide a ClassLoader that is capable of local instrumentation.
+ Spring's native LTW leverages such ClassLoaders to enable AspectJ weaving.
+ You can enable LTW by simply activating context:load-time-weaver
+ as described earlier. Specifically, you do not
+ need to modify the launch script to add
+ -javaagent:path/to/spring-agent.jar.
+
+ GlassFish provides an instrumentation-capable ClassLoader as well,
+ but only in its EAR environment. For GlassFish web applications,
+ follow the Tomcat setup instructions as outlined above.
+
+
+
+
+
+
+ Further Resources
+
+ More information on AspectJ can be found on the AspectJ website.
+
+ The book Eclipse AspectJ by Adrian Colyer et.
+ al. (Addison-Wesley, 2005) provides a comprehensive introduction and
+ reference for the AspectJ language.
+
+ The book AspectJ in Action by Ramnivas Laddad
+ (Manning, 2003) comes highly recommended; the focus of the book is on
+ AspectJ, but a lot of general AOP themes are explored (in some depth).
+
+
+
diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml
new file mode 100644
index 00000000000..954812e54e6
--- /dev/null
+++ b/spring-framework-reference/src/beans.xml
@@ -0,0 +1,6405 @@
+
+
+ The IoC container
+
+
+ Introduction
+
+ This chapter covers the Spring Framework's implementation of the
+ Inversion of Control (IoC)
+ See the section entitled
+ principle.
+
+
+ BeanFactory or
+ ApplicationContext?
+
+ Users are sometimes unsure whether a
+ BeanFactory or an
+ ApplicationContext is best suited for use
+ in a particular situation. A BeanFactory
+ pretty much just instantiates and configures beans. An
+ ApplicationContext also does that,
+ and it provides the supporting infrastructure to
+ enable lots of enterprise-specific features such as
+ transactions and AOP.
+
+ In short, favor the use of an
+ ApplicationContext.
+
+ (For the specific details behind this recommendation, see this
+ section.)
+
+
+ The org.springframework.beans and
+ org.springframework.context packages provide the basis
+ for the Spring Framework's IoC container. The BeanFactory
+ interface provides an advanced configuration mechanism capable of managing
+ objects of any nature. The ApplicationContext
+ interface builds on top of the BeanFactory
+ (it is a sub-interface) and adds other functionality such as easier
+ integration with Spring's AOP features, message resource handling (for use
+ in internationalization), event propagation, and application-layer
+ specific contexts such as the
+ WebApplicationContext for use in web
+ applications.
+
+ In short, the BeanFactory provides
+ the configuration framework and basic functionality, while the
+ ApplicationContext adds more
+ enterprise-centric functionality to it. The
+ ApplicationContext is a complete superset
+ of the BeanFactory, and any description of
+ BeanFactory capabilities and behavior is to
+ be considered to apply to the
+ ApplicationContext as well.
+
+ This chapter is divided into two parts, with the first part covering the basic principles
+ that apply to both the BeanFactory and
+ ApplicationContext, and with the second part covering those features
+ that apply only to the ApplicationContext
+ interface.
+
+
+
+ Basics - containers and beans
+
+ In Spring, those objects that form the backbone of your application
+ and that are managed by the Spring IoC container
+ are referred to as beans. A bean is simply an
+ object that is instantiated, assembled and otherwise managed by a Spring
+ IoC container; other than that, there is nothing special about a bean (it
+ is in all other respects one of probably many objects in your
+ application). These beans, and the dependencies
+ between them, are reflected in the configuration
+ metadata used by a container.
+
+
+ Why... bean?
+
+ The motivation for using the name 'bean', as
+ opposed to 'component' or
+ 'object' is rooted in the origins of the Spring
+ Framework itself (it arose partly as a response to the complexity of
+ Enterprise JavaBeans).
+
+
+
+ The container
+
+ The
+ org.springframework.beans.factory.BeanFactory
+ is the actual representation of the Spring IoC
+ container that is responsible for containing and
+ otherwise managing the aforementioned beans.
+
+ The BeanFactory interface is the
+ central IoC container interface in Spring. Its responsibilities include
+ instantiating or sourcing application objects, configuring such objects,
+ and assembling the dependencies between these objects.
+
+ There are a number of implementations of the
+ BeanFactory interface that come supplied
+ straight out-of-the-box with Spring. The most commonly used
+ BeanFactory implementation is the
+ XmlBeanFactory class. This implementation allows
+ you to express the objects that compose your application, and the
+ doubtless rich interdependencies between such objects, in terms of XML.
+ The XmlBeanFactory takes this XML
+ configuration metadata and uses it to create a
+ fully configured system or application.
+
+
+
+
+
+
+
+
+
+
+
+
+ The Spring IoC container
+
+
+
+
+
+ Configuration metadata
+
+ As can be seen in the above image, the Spring IoC container
+ consumes some form of configuration metadata;
+ this configuration metadata is nothing more than how you (as an
+ application developer) inform the Spring container as to how to
+ instantiate, configure, and assemble [the objects in
+ your application]. This configuration metadata is
+ typically supplied in a simple and intuitive XML format. When using
+ XML-based configuration metadata, you write bean
+ definitions for those beans that you want the Spring IoC
+ container to manage, and then let the container do its stuff.
+
+
+ XML-based metadata is by far the most commonly used form of
+ configuration metadata. It is not however the
+ only form of configuration metadata that is allowed. The Spring IoC
+ container itself is totally decoupled from the
+ format in which this configuration metadata is actually written. The
+ XML-based configuration metadata format really is simple though, and
+ so the majority of this chapter will use the XML format to convey
+ key concepts and features of the Spring IoC container.
+
+ You can find details of another form of metadata that the
+ Spring container can consume in the section entitled
+
+
+
+
+ Resources
+
+ The location path or paths supplied to an
+ ApplicationContext constructor are
+ actually resource strings that allow the container to load
+ configuration metadata from a variety of external resources such as
+ the local file system, from the Java CLASSPATH,
+ etc.
+
+ Once you have learned about Spring's IoC container, you may wish
+ to learn a little more about Spring's
+ Resource abstraction, as described in
+ the chapter entitled .
+
+
+ In the vast majority of application scenarios, explicit user code
+ is not required to instantiate one or more instances of a Spring IoC
+ container. For example, in a web application scenario, a simple eight
+ (or so) lines of boilerplate J2EE web descriptor XML in the
+ web.xml file of the application will typically
+ suffice (see ).
+
+
+ Spring configuration consists of at least one bean definition that
+ the container must manage, but typically there will be more than one bean
+ definition. When using XML-based configuration metadata, these beans are
+ configured as <bean/> elements inside a top-level
+ <beans/> element.
+
+ These bean definitions correspond to the actual objects that make up
+ your application. Typically you will have bean definitions for your
+ service layer objects, your data access objects (DAOs), presentation
+ objects such as Struts Action instances,
+ infrastructure objects such as Hibernate
+ SessionFactories, JMS
+ Queues, and so forth. Typically one does
+ not configure fine-grained domain objects in the container, because it is
+ usually the responsibility of DAOs and business logic to create/load
+ domain objects.
+
+ Find below an example of the basic structure of XML-based
+ configuration metadata.
+
+ <?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-2.5.xsd">
+
+ <bean id="..." class="...">
+ <!-- collaborators and configuration for this bean go here -->
+ </bean>
+
+ <bean id="..." class="...">
+ <!-- collaborators and configuration for this bean go here -->
+ </bean>
+
+ <!-- more bean definitions go here -->
+
+</beans>
+
+
+ Instantiating a container
+
+ Instantiating a Spring IoC container is straightforward.
+
+ ApplicationContext context = new ClassPathXmlApplicationContext(
+ new String[] {"services.xml", "daos.xml"});
+
+// an ApplicationContext is also a BeanFactory (via inheritance)
+BeanFactory factory = context;
+
+
+ Composing XML-based configuration metadata
+
+ It can often be useful to split up container definitions into
+ multiple XML files. One way to then load an application context which
+ is configured from all these XML fragments is to use the application
+ context constructor which takes multiple
+ Resource locations. With a bean
+ factory, a bean definition reader can be used multiple times to read
+ definitions from each file in turn.
+
+ Generally, the Spring team prefers the above approach, since it
+ keeps container configuration files unaware of the fact that they are
+ being combined with others. An alternate approach is to use one or
+ more occurrences of the <import/> element to
+ load bean definitions from another file (or files). Let's look at a
+ sample:
+
+ <beans>
+
+ <import resource="services.xml"/>
+ <import resource="resources/messageSource.xml"/>
+ <import resource="/resources/themeSource.xml"/>
+
+ <bean id="bean1" class="..."/>
+ <bean id="bean2" class="..."/>
+
+</beans>
+
+ In this example, external bean definitions are being loaded from
+ 3 files, services.xml,
+ messageSource.xml, and
+ themeSource.xml. All location paths are considered
+ relative to the definition file doing the importing, so
+ services.xml in this case must be in the same
+ directory or classpath location as the file doing the importing, while
+ messageSource.xml and
+ themeSource.xml must be in a
+ resources location below the location of the
+ importing file. As you can see, a leading slash is actually ignored,
+ but given that these are considered relative paths, it is probably
+ better form not to use the slash at all. The contents of the files
+ being imported must be valid XML bean definition files according to
+ the Spring Schema or DTD, including the top level
+ <beans/> element.
+
+
+
+ It is possible to reference files in parent directories using a relative "../"
+ path. However, this is not recommended because it creates a dependency on a file
+ that is outside the current application. This is in particular not recommended
+ for "classpath:" URLs (e.g. "classpath:../services.xml") where the runtime
+ resolution process will pick the "nearest" classpath root and then look into
+ its parent directory. This is fragile since classpath configuration changes
+ may lead to a different directory being picked.
+
+ Note that you can always use fully qualified resource locations
+ instead of relative paths: e.g. "file:C:/config/services.xml" or
+ "classpath:/config/services.xml". However, be aware that you are coupling
+ your application's configuration to specific absolute locations then.
+ It is generally preferable to keep an indirection for such absolute
+ locations, e.g. through "${...}" placeholders that are resolved
+ against JVM system properties at runtime.
+
+
+
+
+
+ The beans
+
+ A Spring IoC container manages one or more
+ beans. These beans are created using the
+ configuration metadata that has been supplied to the container
+ (typically in the form of XML <bean/>
+ definitions).
+
+ Within the container itself, these bean definitions are
+ represented as BeanDefinition objects,
+ which contain (among other information) the following metadata:
+
+
+
+ a package-qualified class name: typically
+ this is the actual implementation class of the bean being
+ defined.
+
+
+
+ bean behavioral configuration elements, which state how the
+ bean should behave in the container (scope, lifecycle callbacks, and
+ so forth).
+
+
+
+ references to other beans which are needed for the bean to do
+ its work; these references are also called
+ collaborators or
+ dependencies.
+
+
+
+ other configuration settings to set in the newly created
+ object. An example would be the number of connections to use in a
+ bean that manages a connection pool, or the size limit of the
+ pool.
+
+
+
+ The concepts listed above directly translate to a set of
+ properties that each bean definition consists of. Some of these
+ properties are listed below, along with a link to further documentation
+ about each of them.
+
+
+
+ Besides bean definitions which contain information on how to
+ create a specific bean, certain
+ BeanFactory implementations also permit
+ the registration of existing objects that have been created outside the
+ factory (by user code). The
+ DefaultListableBeanFactory class supports this
+ through the registerSingleton(..) method.
+ (Typical applications solely work with beans defined through metadata
+ bean definitions though.)
+
+
+ Naming beans
+
+
+ Bean naming conventions
+
+ The convention (at least amongst the Spring development team)
+ is to use the standard Java convention for instance field names when
+ naming beans. That is, bean names start with a lowercase letter, and
+ are camel-cased from then on. Examples of such names would be
+ (without quotes) 'accountManager',
+ 'accountService', 'userDao',
+ 'loginController', and so forth.
+
+ Adopting a consistent way of naming your beans will go a long
+ way towards making your configuration easier to read and understand;
+ adopting such naming standards is not hard to do, and if you are
+ using Spring AOP it can pay off handsomely when it comes to applying
+ advice to a set of beans related by name.
+
+
+ Every bean has one or more ids (also called
+ identifiers, or names; these terms refer to the same thing). These
+ ids must be unique within the container the bean is
+ hosted in. A bean will almost always have only one id, but if a bean
+ has more than one id, the extra ones can essentially be considered
+ aliases.
+
+ When using XML-based configuration metadata, you use the
+ 'id' or 'name' attributes to
+ specify the bean identifier(s). The 'id' attribute
+ allows you to specify exactly one id, and as it is a real XML element
+ ID attribute, the XML parser is able to do some extra validation when
+ other elements reference the id; as such, it is the preferred way to
+ specify a bean id. However, the XML specification does limit the
+ characters which are legal in XML IDs. This is usually not a
+ constraint, but if you have a need to use one of these special XML
+ characters, or want to introduce other aliases to the bean, you may
+ also or instead specify one or more bean ids,
+ separated by a comma (,), semicolon
+ (;), or whitespace in the 'name'
+ attribute.
+
+ Please note that you are not required to supply a name for a
+ bean. If no name is supplied explicitly, the container will generate a
+ unique name for that bean. The motivations for not supplying a name
+ for a bean will be discussed later (one use case is inner beans).
+
+
+ Aliasing beans
+
+ In a bean definition itself, you may supply more than one name
+ for the bean, by using a combination of up to one name specified via
+ the id attribute, and any number of other names
+ via the name attribute. All these names can be
+ considered equivalent aliases to the same bean, and are useful for
+ some situations, such as allowing each component used in an
+ application to refer to a common dependency using a bean name that
+ is specific to that component itself.
+
+ Having to specify all aliases when the bean is actually
+ defined is not always adequate however. It is sometimes desirable to
+ introduce an alias for a bean which is defined elsewhere. In
+ XML-based configuration metadata this may be accomplished via the
+ use of the <alias/> element.
+
+ <alias name="fromName" alias="toName"/>
+
+ In this case, a bean in the same container which is named
+ 'fromName', may also after the use of this alias
+ definition, be referred to as 'toName'.
+
+ As a concrete example, consider the case where component A
+ defines a DataSource bean called componentA-dataSource, in its XML
+ fragment. Component B would however like to refer to the DataSource
+ as componentB-dataSource in its XML fragment. And the main
+ application, MyApp, defines its own XML fragment and assembles the
+ final application context from all three fragments, and would like
+ to refer to the DataSource as myApp-dataSource. This scenario can be
+ easily handled by adding to the MyApp XML fragment the following
+ standalone aliases:
+
+ <alias name="componentA-dataSource" alias="componentB-dataSource"/>
+<alias name="componentA-dataSource" alias="myApp-dataSource" />
+
+ Now each component and the main application can refer to the
+ dataSource via a name that is unique and guaranteed not to clash
+ with any other definition (effectively there is a namespace), yet
+ they refer to the same bean.
+
+
+
+
+ Instantiating beans
+
+
+ Inner class names
+
+ If for whatever reason you want to configure a bean definition
+ for a static inner class, you have to use the
+ binary name of the inner class.
+
+ For example, if you have a class called
+ Foo in the com.example
+ package, and this Foo class has a
+ static inner class called
+ Bar, the value of the
+ 'class' attribute on a bean definition would
+ be...
+
+
+ com.example.Foo$Bar
+
+
+ Notice the use of the $ character in the
+ name to separate the inner class name from the outer class
+ name.
+
+
+ A bean definition essentially is a recipe for creating one or
+ more objects. The container looks at the recipe for a named bean when
+ asked, and uses the configuration metadata encapsulated by that bean
+ definition to create (or acquire) an actual object.
+
+ If you are using XML-based configuration metadata, you can
+ specify the type (or class) of object that is to be instantiated using
+ the 'class' attribute of the
+ <bean/> element. This
+ 'class' attribute (which internally eventually
+ boils down to being a Class property on a
+ BeanDefinition instance) is normally
+ mandatory (see and for the two exceptions) and
+ is used for one of two purposes. The class property specifies the
+ class of the bean to be constructed in the common case where the
+ container itself directly creates the bean by calling its constructor
+ reflectively (somewhat equivalent to Java code using the
+ 'new' operator). In the less common case where
+ the container invokes a static,
+ factory method on a class to create the bean, the
+ class property specifies the actual class containing the
+ static factory method that is to be invoked to
+ create the object (the type of the object returned from the invocation
+ of the static factory method may be the same class
+ or another class entirely, it doesn't matter).
+
+
+ Instantiation using a constructor
+
+ When creating a bean using the constructor approach, all
+ normal classes are usable by and compatible with Spring. That is,
+ the class being created does not need to implement any specific
+ interfaces or be coded in a specific fashion. Just specifying the
+ bean class should be enough. However, depending on what type of IoC
+ you are going to use for that specific bean, you may need a default
+ (empty) constructor.
+
+ Additionally, the Spring IoC container isn't limited to just
+ managing true JavaBeans, it is also able to manage virtually
+ any class you want it to manage. Most people
+ using Spring prefer to have actual JavaBeans (having just a default
+ (no-argument) constructor and appropriate setters and getters
+ modeled after the properties) in the container, but it is also
+ possible to have more exotic non-bean-style classes in your
+ container. If, for example, you need to use a legacy connection pool
+ that absolutely does not adhere to the JavaBean specification,
+ Spring can manage it as well.
+
+ When using XML-based configuration metadata you can specify
+ your bean class like so:
+
+ <bean id="exampleBean" class="examples.ExampleBean"/>
+
+<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
+
+ The mechanism for supplying arguments to the constructor (if
+ required), or setting properties of the object instance after it has
+ been constructed, is
+ described shortly.
+
+
+
+ Instantiation using a static factory method
+
+ When defining a bean which is to be created using a static
+ factory method, along with the class attribute
+ which specifies the class containing the static
+ factory method, another attribute named
+ factory-method is needed to specify the name of
+ the factory method itself. Spring expects to be able to call this
+ method (with an optional list of arguments as described later) and
+ get back a live object, which from that point on is treated as if it
+ had been created normally via a constructor. One use for such a bean
+ definition is to call static factories in legacy
+ code.
+
+ The following example shows a bean definition which specifies
+ that the bean is to be created by calling a factory-method. Note
+ that the definition does not specify the type (class) of the
+ returned object, only the class containing the factory method. In
+ this example, the createInstance() method
+ must be a static method.
+
+ <bean id="exampleBean"
+ class="examples.ExampleBean2"
+ factory-method="createInstance"/>
+
+ The mechanism for supplying (optional) arguments to the
+ factory method, or setting properties of the object instance after
+ it has been returned from the factory, will be described
+ shortly.
+
+
+
+ Instantiation using an instance factory method
+
+ In a fashion similar to instantiation via a static factory
+ method, instantiation using an instance factory method is
+ where a non-static method of an existing bean from the container is
+ invoked to create a new bean. To use this mechanism, the
+ 'class' attribute must be left empty, and the
+ 'factory-bean' attribute must specify the name of
+ a bean in the current (or parent/ancestor) container that contains
+ the instance method that is to be invoked to create the object. The
+ name of the factory method itself must be set using the
+ 'factory-method' attribute.
+
+ <!-- the factory bean, which contains a method called createInstance() -->
+<bean id="serviceLocator" class="com.foo.DefaultServiceLocator">
+ <!-- inject any dependencies required by this locator bean -->
+</bean>
+
+<!-- the bean to be created via the factory bean -->
+<bean id="exampleBean"
+ factory-bean="serviceLocator"
+ factory-method="createInstance"/>
+
+ Although the mechanisms for setting bean
+ properties are still to be discussed, one implication of this
+ approach is that the factory bean itself can be managed and
+ configured via DI.
+
+
+
+ When the Spring documentation makes mention of a 'factory
+ bean', this will be a reference to a bean that is configured in the
+ Spring container that will create objects via an instance
+ or static
+ factory method. When the documentation mentions a
+ FactoryBean (notice the
+ capitalization) this is a reference to a Spring-specific
+ FactoryBean
+ .
+
+
+
+
+
+ Using the container
+
+ A BeanFactory is essentially
+ nothing more than the interface for an advanced factory capable of
+ maintaining a registry of different beans and their dependencies. The
+ BeanFactory enables you to read bean
+ definitions and access them using the bean factory. When using just the
+ BeanFactory you would create one and read
+ in some bean definitions in the XML format as follows:
+
+ Resource res = new FileSystemResource("beans.xml");
+BeanFactory factory = new XmlBeanFactory(res);
+
+ Basically that is all there is to it. Using
+ getBean(String) you can retrieve instances of
+ your beans; the client-side view of the
+ BeanFactory is simple. The
+ BeanFactory interface has just a few
+ other methods, but ideally your application code should never use
+ them... indeed, your application code should have no calls to the
+ getBean(String) method at all, and thus no
+ dependency on Spring APIs at all.
+
+
+
+
+ Dependencies
+
+ Your typical enterprise application is not made up of a single
+ object (or bean in the Spring parlance). Even the simplest of applications
+ will no doubt have at least a handful of objects that work together to
+ present what the end-user sees as a coherent application. This next
+ section explains how you go from defining a number of bean definitions
+ that stand-alone, each to themselves, to a fully realized application
+ where objects work (or collaborate) together to achieve some goal (usually
+ an application that does what the end-user wants).
+
+
+ Injecting dependencies
+
+ The basic principle behind Dependency
+ Injection (DI) is that objects define their dependencies
+ (that is to say the other objects they work with) only through
+ constructor arguments, arguments to a factory method, or properties
+ which are set on the object instance after it has been constructed or
+ returned from a factory method. Then, it is the job of the container to
+ actually inject those dependencies when it creates
+ the bean. This is fundamentally the inverse, hence the name
+ Inversion of Control (IoC), of the bean itself
+ being in control of instantiating or locating its dependencies on its
+ own using direct construction of classes, or something like the
+ Service Locator pattern.
+
+ It becomes evident upon usage that code gets much cleaner when the
+ DI principle is applied, and reaching a higher grade of decoupling is
+ much easier when objects do not look up their dependencies, but are
+ provided with them (and additionally do not even know where the
+ dependencies are located and of what concrete class they are). DI exists
+ in two major variants, namely Constructor Injection and
+ Setter Injection.
+
+
+ Constructor Injection
+
+ Constructor-based DI is effected by
+ invoking a constructor with a number of arguments, each representing a
+ dependency. Additionally, calling a static factory
+ method with specific arguments to construct the bean, can be
+ considered almost equivalent, and the rest of this text will consider
+ arguments to a constructor and arguments to a
+ static factory method similarly. Find below an
+ example of a class that could only be dependency injected using
+ constructor injection. Notice that there is nothing
+ special about this class.
+
+ public class SimpleMovieLister {
+
+ // the SimpleMovieLister has a dependency on a MovieFinder
+ private MovieFinder movieFinder;
+
+ // a constructor so that the Spring container can 'inject' a MovieFinder
+ public SimpleMovieLister(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // business logic that actually 'uses' the injected MovieFinder is omitted...
+}
+
+
+ Constructor Argument Resolution
+
+ Constructor argument resolution matching occurs using the
+ argument's type. If there is no potential for ambiguity in the
+ constructor arguments of a bean definition, then the order in which
+ the constructor arguments are defined in a bean definition is the
+ order in which those arguments will be supplied to the appropriate
+ constructor when it is being instantiated. Consider the following
+ class:
+
+ package x.y;
+
+public class Foo {
+
+ public Foo(Bar bar, Baz baz) {
+ // ...
+ }
+}
+
+ There is no potential for ambiguity here (assuming of course
+ that Bar and Baz
+ classes are not related in an inheritance hierarchy). Thus the
+ following configuration will work just fine, and you do not need to
+ specify the constructor argument indexes and / or types
+ explicitly.
+
+ <beans>
+ <bean name="foo" class="x.y.Foo">
+ <constructor-arg>
+ <bean class="x.y.Bar"/>
+ </constructor-arg>
+ <constructor-arg>
+ <bean class="x.y.Baz"/>
+ </constructor-arg>
+ </bean>
+</beans>
+
+ When another bean is referenced, the type is known, and
+ matching can occur (as was the case with the preceding example).
+ When a simple type is used, such as
+ <value>true<value>, Spring cannot
+ determine the type of the value, and so cannot match by type without
+ help. Consider the following class:
+
+ package examples;
+
+public class ExampleBean {
+
+ // No. of years to the calculate the Ultimate Answer
+ private int years;
+
+ // The Answer to Life, the Universe, and Everything
+ private String ultimateAnswer;
+
+ public ExampleBean(int years, String ultimateAnswer) {
+ this.years = years;
+ this.ultimateAnswer = ultimateAnswer;
+ }
+}
+
+
+ Constructor Argument Type Matching
+
+ The above scenario can use type
+ matching with simple types by explicitly specifying the type of
+ the constructor argument using the 'type'
+ attribute. For example:
+
+ <bean id="exampleBean" class="examples.ExampleBean">
+ <constructor-arg type="int" value="7500000"/>
+ <constructor-arg type="java.lang.String" value="42"/>
+</bean>
+
+
+
+ Constructor Argument Index
+
+ Constructor arguments can have their index specified
+ explicitly by use of the index attribute. For
+ example:
+
+ <bean id="exampleBean" class="examples.ExampleBean">
+ <constructor-arg index="0" value="7500000"/>
+ <constructor-arg index="1" value="42"/>
+</bean>
+
+ As well as solving the ambiguity problem of multiple simple
+ values, specifying an index also solves the problem of ambiguity
+ where a constructor may have two arguments of the same type. Note
+ that the index is 0 based.
+
+
+
+
+
+ Setter Injection
+
+ Setter-based DI is realized by calling
+ setter methods on your beans after invoking a no-argument constructor
+ or no-argument static factory method to instantiate
+ your bean.
+
+ Find below an example of a class that can only be dependency
+ injected using pure setter injection. Note that there is nothing
+ special about this class... it is plain old
+ Java.
+
+ public class SimpleMovieLister {
+
+ // the SimpleMovieLister has a dependency on the MovieFinder
+ private MovieFinder movieFinder;
+
+ // a setter method so that the Spring container can 'inject' a MovieFinder
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // business logic that actually 'uses' the injected MovieFinder is omitted...
+}
+
+
+
+ Constructor- or Setter-based DI?
+
+ The Spring team generally advocates the usage of setter
+ injection, since a large number of constructor arguments can get
+ unwieldy, especially when some properties are optional. The presence
+ of setter methods also makes objects of that class amenable to being
+ re-configured (or re-injected) at some later time (for management via
+ JMX MBeans is a particularly compelling use
+ case).
+
+ Constructor-injection is favored by some purists though (and
+ with good reason). Supplying all of an object's dependencies means
+ that that object is never returned to client (calling) code in a less
+ than totally initialized state. The flip side is that the object
+ becomes less amenable to re-configuration (or re-injection).
+
+ There is no hard and fast rule here. Use whatever type of DI
+ makes the most sense for a particular class; sometimes, when dealing
+ with third party classes to which you do not have the source, the
+ choice will already have been made for you - a legacy class may not
+ expose any setter methods, and so constructor injection will be the
+ only type of DI available to you.
+
+
+ The BeanFactory supports both of
+ these variants for injecting dependencies into beans it manages. (It in
+ fact also supports injecting setter-based dependencies after some
+ dependencies have already been supplied via the constructor approach.)
+ The configuration for the dependencies comes in the form of a
+ BeanDefinition, which is used together
+ with PropertyEditor instances to know how
+ to convert properties from one format to another. However, most users of
+ Spring will not be dealing with these classes directly (that is
+ programmatically), but rather with an XML definition file which will be
+ converted internally into instances of these classes, and used to load
+ an entire Spring IoC container instance.
+
+ Bean dependency resolution generally happens as follows:
+
+
+
+ The BeanFactory is created and
+ initialized with a configuration which describes all the beans.
+ (Most Spring users use a BeanFactory
+ or ApplicationContext implementation
+ that supports XML format configuration files.)
+
+
+
+ Each bean has dependencies expressed in the form of
+ properties, constructor arguments, or arguments to the
+ static-factory method when that is used instead of a normal
+ constructor. These dependencies will be provided to the bean,
+ when the bean is actually created.
+
+
+
+ Each property or constructor argument is either an actual
+ definition of the value to set, or a reference to another bean in
+ the container.
+
+
+
+
+ Each property or constructor argument which is a value must be able
+ to be converted from whatever format it was specified in, to the
+ actual type of that property or constructor argument. By default
+ Spring can convert a value supplied in string format to all built-in
+ types, such as int, long,
+ String, boolean, etc.
+
+
+
+ The Spring container validates the configuration of each bean as
+ the container is created, including the validation that properties which
+ are bean references are actually referring to valid beans. However, the
+ bean properties themselves are not set until the bean is
+ actually created. For those beans that are singleton-scoped
+ and set to be pre-instantiated (such as singleton beans in an
+ ApplicationContext), creation happens at
+ the time that the container is created, but otherwise this is only when
+ the bean is requested. When a bean actually has to be created, this will
+ potentially cause a graph of other beans to be created, as its
+ dependencies and its dependencies' dependencies (and so on) are created
+ and assigned.
+
+
+ Circular dependencies
+
+ If you are using predominantly constructor injection it is
+ possible to write and configure your classes and beans such that an
+ unresolvable circular dependency scenario is created.
+
+ Consider the scenario where you have class A, which requires an
+ instance of class B to be provided via constructor injection, and
+ class B, which requires an instance of class A to be provided via
+ constructor injection. If you configure beans for classes A and B to
+ be injected into each other, the Spring IoC container will detect this
+ circular reference at runtime, and throw a
+ BeanCurrentlyInCreationException.
+
+ One possible solution to this issue is to edit the source code
+ of some of your classes to be configured via setters instead of via
+ constructors. Another solution is not to use constructor injection and
+ stick to setter injection only. In other words, while it should
+ generally be avoided in all but the rarest of circumstances, it is
+ possible to configure circular dependencies with setter
+ injection.
+
+ Unlike the typical case (with no circular
+ dependencies), a circular dependency between bean A and bean B will
+ force one of the beans to be injected into the other prior to being
+ fully initialized itself (a classic chicken/egg scenario).
+
+
+ You can generally trust Spring to do the right thing. It will
+ detect misconfiguration issues, such as references to non-existent beans
+ and circular dependencies, at container load-time. It will actually set
+ properties and resolve dependencies as late as possible, which is when
+ the bean is actually created. This means that a Spring container which
+ has loaded correctly can later generate an exception when you request a
+ bean if there is a problem creating that bean or one of its
+ dependencies. This could happen if the bean throws an exception as a
+ result of a missing or invalid property, for example. This potentially
+ delayed visibility of some configuration issues is why
+ ApplicationContext implementations by
+ default pre-instantiate singleton beans. At the cost of some upfront
+ time and memory to create these beans before they are actually needed,
+ you find out about configuration issues when the
+ ApplicationContext is created, not later.
+ If you wish, you can still override this default behavior and set any of
+ these singleton beans to lazy-initialize (that is not be
+ pre-instantiated).
+
+ If no circular dependencies are involved (see sidebar for a
+ discussion of circular dependencies), when one or more collaborating
+ beans are being injected into a dependent bean, each collaborating bean
+ is totally configured prior to being passed (via
+ one of the DI flavors) to the dependent bean. This means that if bean A
+ has a dependency on bean B, the Spring IoC container will
+ totally configure bean B prior to invoking the
+ setter method on bean A; you can read 'totally
+ configure' to mean that the bean will be instantiated (if not
+ a pre-instantiated singleton), all of its dependencies will be set, and
+ the relevant lifecycle methods (such as a configured init
+ method or the IntializingBean
+ callback method) will all be invoked.
+
+
+ Some examples
+
+ First, an example of using XML-based configuration metadata for
+ setter-based DI. Find below a small part of a Spring XML configuration
+ file specifying some bean definitions.
+
+ <bean id="exampleBean" class="examples.ExampleBean">
+
+ <!-- setter injection using the nested <ref/> element -->
+ <property name="beanOne"><ref bean="anotherExampleBean"/></property>
+
+ <!-- setter injection using the neater 'ref' attribute -->
+ <property name="beanTwo" ref="yetAnotherBean"/>
+ <property name="integerProperty" value="1"/>
+</bean>
+
+<bean id="anotherExampleBean" class="examples.AnotherBean"/>
+<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
+
+ public class ExampleBean {
+
+ private AnotherBean beanOne;
+ private YetAnotherBean beanTwo;
+ private int i;
+
+ public void setBeanOne(AnotherBean beanOne) {
+ this.beanOne = beanOne;
+ }
+
+ public void setBeanTwo(YetAnotherBean beanTwo) {
+ this.beanTwo = beanTwo;
+ }
+
+ public void setIntegerProperty(int i) {
+ this.i = i;
+ }
+}
+
+ As you can see, setters have been declared to match against the
+ properties specified in the XML file. Find below an example of using
+ constructor-based DI.
+
+ <bean id="exampleBean" class="examples.ExampleBean">
+
+ <!-- constructor injection using the nested <ref/> element -->
+ <constructor-arg>
+ <ref bean="anotherExampleBean"/>
+ </constructor-arg>
+
+ <!-- constructor injection using the neater 'ref' attribute -->
+ <constructor-arg ref="yetAnotherBean"/>
+
+ <constructor-arg type="int" value="1"/>
+</bean>
+
+<bean id="anotherExampleBean" class="examples.AnotherBean"/>
+<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
+
+ public class ExampleBean {
+
+ private AnotherBean beanOne;
+ private YetAnotherBean beanTwo;
+ private int i;
+
+ public ExampleBean(
+ AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
+ this.beanOne = anotherBean;
+ this.beanTwo = yetAnotherBean;
+ this.i = i;
+ }
+}
+
+ As you can see, the constructor arguments specified in the bean
+ definition will be used to pass in as arguments to the constructor of
+ the ExampleBean.
+
+ Now consider a variant of this where instead of using a
+ constructor, Spring is told to call a static
+ factory method to return an instance of the object:
+
+ <bean id="exampleBean" class="examples.ExampleBean"
+ factory-method="createInstance">
+ <constructor-arg ref="anotherExampleBean"/>
+ <constructor-arg ref="yetAnotherBean"/>
+ <constructor-arg value="1"/>
+</bean>
+
+<bean id="anotherExampleBean" class="examples.AnotherBean"/>
+<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
+
+ public class ExampleBean {
+
+ // a private constructor
+ private ExampleBean(...) {
+ ...
+ }
+
+ // a static factory method; the arguments to this method can be
+ // considered the dependencies of the bean that is returned,
+ // regardless of how those arguments are actually used.
+ public static ExampleBean createInstance (
+ AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
+
+ ExampleBean eb = new ExampleBean (...);
+ // some other operations...
+ return eb;
+ }
+}
+
+ Note that arguments to the static factory
+ method are supplied via <constructor-arg/>
+ elements, exactly the same as if a constructor had actually been used.
+ Also, it is important to realize that the type of the class being
+ returned by the factory method does not have to be of the same type as
+ the class which contains the static factory method,
+ although in this example it is. An instance (non-static) factory
+ method would be used in an essentially identical fashion (aside from
+ the use of the factory-bean attribute instead of
+ the class attribute), so details will not be
+ discussed here.
+
+
+
+
+ Dependencies and configuration in detail
+
+ As mentioned in the previous section, bean properties and
+ constructor arguments can be defined as either references to other
+ managed beans (collaborators), or values defined inline. Spring's
+ XML-based configuration metadata supports a number of sub-element types
+ within its <property/> and
+ <constructor-arg/> elements for just this
+ purpose.
+
+
+ Straight values (primitives, Strings,
+ etc.)
+
+ The <value/> element specifies a
+ property or constructor argument as a human-readable string
+ representation. As mentioned
+ previously, JavaBeans PropertyEditors are
+ used to convert these string values from a
+ String to the actual type of the property or
+ argument.
+
+ <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
+
+ <!-- results in a setDriverClassName(String) call -->
+ <property name="driverClassName">
+ <value>com.mysql.jdbc.Driver</value>
+ </property>
+ <property name="url">
+ <value>jdbc:mysql://localhost:3306/mydb</value>
+ </property>
+ <property name="username">
+ <value>root</value>
+ </property>
+ <property name="password">
+ <value>masterkaoli</value>
+ </property>
+</bean>
+
+ The <property/> and
+ <constructor-arg/> elements also support the
+ use of the 'value' attribute, which can lead to
+ much more succinct configuration. When using the
+ 'value' attribute, the above bean definition reads
+ like so:
+
+ <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
+
+ <!-- results in a setDriverClassName(String) call -->
+ <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
+ <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
+ <property name="username" value="root"/>
+ <property name="password" value="masterkaoli"/>
+</bean>
+
+ The Spring team generally prefer the attribute style over the
+ use of nested <value/> elements. If you are
+ reading this reference manual straight through from top to bottom
+ (wow!) then we are getting slightly ahead of ourselves here, but you
+ can also configure a java.util.Properties
+ instance like so:
+
+ <bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+
+ <!-- typed as a java.util.Properties -->
+ <property name="properties">
+ <value>
+ jdbc.driver.className=com.mysql.jdbc.Driver
+ jdbc.url=jdbc:mysql://localhost:3306/mydb
+ </value>
+ </property>
+</bean>
+
+ Can you see what is happening? The Spring container is
+ converting the text inside the <value/>
+ element into a java.util.Properties instance
+ using the JavaBeans PropertyEditor
+ mechanism. This is a nice shortcut, and is one of a few places where
+ the Spring team do favor the use of the nested
+ <value/> element over the
+ 'value' attribute style.
+
+
+ The idref element
+
+ The idref element is simply an error-proof
+ way to pass the id of another bean in the
+ container (to a <constructor-arg/> or
+ <property/> element).
+
+ <bean id="theTargetBean" class="..."/>
+
+<bean id="theClientBean" class="...">
+ <property name="targetName">
+ <idref bean="theTargetBean" />
+ </property>
+</bean>
+
+ The above bean definition snippet is
+ exactly equivalent (at runtime) to the
+ following snippet:
+
+ <bean id="theTargetBean" class="..." />
+
+<bean id="client" class="...">
+ <property name="targetName" value="theTargetBean" />
+</bean>
+
+ The main reason the first form is preferable to the second is
+ that using the idref tag allows the container to
+ validate at deployment time that the
+ referenced, named bean actually exists. In the second variation, no
+ validation is performed on the value that is passed to the
+ 'targetName' property of the
+ 'client' bean. Any typo will only be discovered
+ (with most likely fatal results) when the
+ 'client' bean is actually instantiated. If the
+ 'client' bean is a prototype bean, this typo (and
+ the resulting exception) may only be discovered long after the
+ container is actually deployed.
+
+ Additionally, if the bean being referred to is in the same XML
+ unit, and the bean name is the bean id, the
+ 'local' attribute may be used, which allows the
+ XML parser itself to validate the bean id even earlier, at XML
+ document parse time.
+
+ <property name="targetName">
+ <!-- a bean with an id of 'theTargetBean' must exist; otherwise an XML exception will be thrown -->
+ <idref local="theTargetBean"/>
+</property>
+
+ By way of an example, one common place (at least in pre-Spring
+ 2.0 configuration) where the <idref/> element brings value is
+ in the configuration of AOP
+ interceptors in a ProxyFactoryBean
+ bean definition. If you use <idref/> elements when specifying
+ the interceptor names, there is no chance of inadvertently
+ misspelling an interceptor id.
+
+
+
+
+ References to other beans (collaborators)
+
+ The ref element is the final element allowed
+ inside a <constructor-arg/> or
+ <property/> definition element. It is used to
+ set the value of the specified property to be a reference to another
+ bean managed by the container (a collaborator). As mentioned in a
+ previous section, the referred-to bean is considered to be a
+ dependency of the bean who's property is being set, and will be
+ initialized on demand as needed (if it is a singleton bean it may have
+ already been initialized by the container) before the property is set.
+ All references are ultimately just a reference to another object, but
+ there are 3 variations on how the id/name of the other object may be
+ specified, which determines how scoping and validation is
+ handled.
+
+ Specifying the target bean by using the bean
+ attribute of the <ref/> tag is the most
+ general form, and will allow creating a reference to any bean in the
+ same container (whether or not in the same XML file), or parent
+ container. The value of the 'bean' attribute may be
+ the same as either the 'id' attribute of the target
+ bean, or one of the values in the 'name' attribute
+ of the target bean.
+
+ <ref bean="someBean"/>
+
+ Specifying the target bean by using the local
+ attribute leverages the ability of the XML parser to validate XML id
+ references within the same file. The value of the
+ local attribute must be the same as the
+ id attribute of the target bean. The XML parser
+ will issue an error if no matching element is found in the same file.
+ As such, using the local variant is the best choice (in order to know
+ about errors as early as possible) if the target bean is in the same
+ XML file.
+
+ <ref local="someBean"/>
+
+ Specifying the target bean by using the
+ 'parent' attribute allows a reference to be created
+ to a bean which is in a parent container of the current container. The
+ value of the 'parent' attribute may be the same as
+ either the 'id' attribute of the target bean, or
+ one of the values in the 'name' attribute of the
+ target bean, and the target bean must be in a parent container to the
+ current one. The main use of this bean reference variant is when you
+ have a hierarchy of containers and you want to wrap an existing bean
+ in a parent container with some sort of proxy which will have the same
+ name as the parent bean.
+
+ <!-- in the parent context -->
+<bean id="accountService" class="com.foo.SimpleAccountService">
+ <!-- insert dependencies as required as here -->
+</bean>
+
+ <!-- in the child (descendant) context -->
+<bean id="accountService" <-- notice that the name of this bean is the same as the name of the 'parent' bean
+ class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="target">
+ <ref parent="accountService"/> <-- notice how we refer to the parent bean
+ </property>
+ <!-- insert other configuration and dependencies as required as here -->
+</bean>
+
+
+
+ Inner beans
+
+ A <bean/> element inside the
+ <property/> or
+ <constructor-arg/> elements is used to define
+ a so-called inner bean. An inner bean
+ definition does not need to have any id or name defined, and it is
+ best not to even specify any id or name value because the id or name
+ value simply will be ignored by the container.
+
+ <bean id="outer" class="...">
+ <!-- instead of using a reference to a target bean, simply define the target bean inline -->
+ <property name="target">
+ <bean class="com.example.Person"> <!-- this is the inner bean -->
+ <property name="name" value="Fiona Apple"/>
+ <property name="age" value="25"/>
+ </bean>
+ </property>
+</bean>
+
+ Note that in the specific case of inner beans, the
+ 'scope' flag and any 'id' or
+ 'name' attribute are effectively ignored. Inner
+ beans are always anonymous and they are
+ always scoped as prototypes. Please
+ also note that it is not possible to inject inner
+ beans into collaborating beans other than the enclosing bean.
+
+
+
+ Collections
+
+ The <list/>,
+ <set/>, <map/>, and
+ <props/> elements allow properties and
+ arguments of the Java Collection type
+ List,
+ Set,
+ Map, and
+ Properties, respectively, to be defined
+ and set.
+
+ <bean id="moreComplexObject" class="example.ComplexObject">
+ <!-- results in a setAdminEmails(java.util.Properties) call -->
+ <property name="adminEmails">
+ <props>
+ <prop key="administrator">administrator@example.org</prop>
+ <prop key="support">support@example.org</prop>
+ <prop key="development">development@example.org</prop>
+ </props>
+ </property>
+ <!-- results in a setSomeList(java.util.List) call -->
+ <property name="someList">
+ <list>
+ <value>a list element followed by a reference</value>
+ <ref bean="myDataSource" />
+ </list>
+ </property>
+ <!-- results in a setSomeMap(java.util.Map) call -->
+ <property name="someMap">
+ <map>
+ <entry>
+ <key>
+ <value>an entry</value>
+ </key>
+ <value>just some string</value>
+ </entry>
+ <entry>
+ <key>
+ <value>a ref</value>
+ </key>
+ <ref bean="myDataSource" />
+ </entry>
+ </map>
+ </property>
+ <!-- results in a setSomeSet(java.util.Set) call -->
+ <property name="someSet">
+ <set>
+ <value>just some string</value>
+ <ref bean="myDataSource" />
+ </set>
+ </property>
+</bean>
+
+ The nested element style used this initial
+ example tends to become quite verbose. Fortunately, there are
+ attribute shortcuts for most elements, which you can read about in
+ .
+
+ Note that the value of a map key or value, or a set
+ value, can also again be any of the following
+ elements:
+
+ bean | ref | idref | list | set | map | props | value | null
+
+
+ Collection merging
+
+ As of Spring 2.0, the container also supports the
+ merging of collections. This allows an
+ application developer to define a parent-style
+ <list/>, <map/>,
+ <set/> or <props/>
+ element, and have child-style <list/>,
+ <map/>, <set/> or
+ <props/> elements inherit and override
+ values from the parent collection; that is to say the child
+ collection's values will be the result obtained from the merging of
+ the elements of the parent and child collections, with the child's
+ collection elements overriding values specified in the parent
+ collection.
+
+ Please note that this section on merging makes use
+ of the parent-child bean mechanism. This concept has not yet been
+ introduced, so readers unfamiliar with the concept of parent and
+ child bean definitions may wish to read the relevant section
+ before continuing.
+
+ Find below an example of the collection merging
+ feature:
+
+ <beans>
+<bean id="parent" abstract="true" class="example.ComplexObject">
+ <property name="adminEmails">
+ <props>
+ <prop key="administrator">administrator@example.com</prop>
+ <prop key="support">support@example.com</prop>
+ </props>
+ </property>
+</bean>
+<bean id="child" parent="parent">
+ <property name="adminEmails">
+ <!-- the merge is specified on the *child* collection definition -->
+ <props merge="true">
+ <prop key="sales">sales@example.com</prop>
+ <prop key="support">support@example.co.uk</prop>
+ </props>
+ </property>
+</bean>
+<beans>
+
+ Notice the use of the merge=true attribute
+ on the <props/> element of the
+ adminEmails property of the
+ child bean definition. When the
+ child bean is actually resolved and instantiated
+ by the container, the resulting instance will have an
+ adminEmailsProperties
+ collection that contains the result of the merging of the child's
+ adminEmails collection with the parent's
+ adminEmails collection.
+
+ administrator=administrator@example.com
+sales=sales@example.com
+support=support@example.co.uk
+
+ Notice how the child Properties
+ collection's value set will have inherited all the property elements
+ from the parent <props/>. Notice also how
+ the child's value for the support value overrides
+ the value in the parent collection.
+
+ This merging behavior applies similarly to the
+ <list/>, <map/>,
+ and <set/> collection types. In the
+ specific case of the <list/> element, the
+ semantics associated with the List collection
+ type, that is the notion of an ordered collection
+ of values, is maintained; the parent's values will precede all of
+ the child list's values. In the case of the
+ Map,
+ Set, and
+ Properties collection types, there is
+ no notion of ordering and hence no ordering semantics are in effect
+ for the collection types that underlie the associated
+ Map,
+ Set and
+ Properties implementation types used
+ internally by the container.
+
+ Finally, some minor notes about the merging support are in
+ order; you cannot merge different collection types (e.g. a
+ Map and a
+ List), and if you do attempt to do so
+ an appropriate Exception will be thrown; and
+ in case it is not immediately obvious, the
+ 'merge' attribute must be specified on the lower
+ level, inherited, child definition; specifying the
+ 'merge' attribute on a parent collection
+ definition is redundant and will not result in the desired merging;
+ and (lastly), please note that this merging feature is only
+ available in Spring 2.0 (and later versions).
+
+
+
+ Strongly-typed collection (Java 5+ only)
+
+ If you are using Java 5 or Java 6, you will be aware that it
+ is possible to have strongly typed collections (using generic
+ types). That is, it is possible to declare a
+ Collection type such that it can only
+ contain String elements (for example). If you
+ are using Spring to dependency inject a strongly-typed
+ Collection into a bean, you can take
+ advantage of Spring's type-conversion support such that the elements
+ of your strongly-typed Collection
+ instances will be converted to the appropriate type prior to being
+ added to the Collection.
+
+ public class Foo {
+
+ private Map<String, Float> accounts;
+
+ public void setAccounts(Map<String, Float> accounts) {
+ this.accounts = accounts;
+ }
+}
+
+ <beans>
+ <bean id="foo" class="x.y.Foo">
+ <property name="accounts">
+ <map>
+ <entry key="one" value="9.99"/>
+ <entry key="two" value="2.75"/>
+ <entry key="six" value="3.99"/>
+ </map>
+ </property>
+ </bean>
+</beans>
+
+ When the 'accounts' property of the
+ 'foo' bean is being prepared for injection, the
+ generics information about the element type of the strongly-typed
+ Map<String, Float> is actually
+ available via reflection, and so Spring's type conversion
+ infrastructure will actually recognize the various value elements as
+ being of type Float and so the string values
+ '9.99', '2.75', and '3.99'
+ will be converted into an actual Float
+ type.
+
+
+
+
+ Nulls
+
+ The <null/> element is used to handle
+ null values. Spring treats empty arguments for
+ properties and the like as empty Strings. The
+ following XML-based configuration metadata snippet results in the
+ email property being set to the empty String
+ value ("")
+
+ <bean class="ExampleBean">
+ <property name="email"><value/></property>
+</bean>
+
+ This is equivalent to the following Java code:
+ exampleBean.setEmail(""). The special
+ <null> element may be used to indicate a
+ null value. For example:
+
+ <bean class="ExampleBean">
+ <property name="email"><null/></property>
+</bean>
+
+ The above configuration is equivalent to the following Java
+ code: exampleBean.setEmail(null).
+
+
+
+ Shortcuts and other convenience options for XML-based
+ configuration metadata
+
+ The configuration metadata shown so far is a tad verbose. That
+ is why there are several options available for you to limit the amount
+ of XML you have to write to configure your components. The first is a
+ shortcut to define values and references to other beans as part of a
+ <property/> definition. The second is
+ slightly different format of specifying properties altogether.
+
+
+ XML-based configuration metadata shortcuts
+
+ The <property/>,
+ <constructor-arg/>, and
+ <entry/> elements all support a
+ 'value' attribute which may be used instead of
+ embedding a full <value/> element.
+ Therefore, the following:
+
+ <property name="myProperty">
+ <value>hello</value>
+</property>
+
+ <constructor-arg>
+ <value>hello</value>
+</constructor-arg>
+
+ <entry key="myKey">
+ <value>hello</value>
+</entry>
+
+ are equivalent to:
+
+ <property name="myProperty" value="hello"/>
+
+ <constructor-arg value="hello"/>
+
+ <entry key="myKey" value="hello"/>
+
+ The <property/> and
+ <constructor-arg/> elements support a
+ similar shortcut 'ref' attribute which may be
+ used instead of a full nested <ref/>
+ element. Therefore, the following:
+
+ <property name="myProperty">
+ <ref bean="myBean">
+</property>
+
+ <constructor-arg>
+ <ref bean="myBean">
+</constructor-arg>
+
+ ... are equivalent to:
+
+ <property name="myProperty" ref="myBean"/>
+
+ <constructor-arg ref="myBean"/>
+
+ Note however that the shortcut form is equivalent to a
+ <ref bean="xxx"> element; there is no
+ shortcut for <ref local="xxx">. To enforce
+ a strict local reference, you must use the long form.
+
+ Finally, the entry element allows a shortcut form to specify
+ the key and/or value of the map, in the form of the
+ 'key' / 'key-ref' and
+ 'value' / 'value-ref'
+ attributes. Therefore, the following:
+
+ <entry>
+ <key>
+ <ref bean="myKeyBean" />
+ </key>
+ <ref bean="myValueBean" />
+</entry>
+
+ is equivalent to:
+
+ <entry key-ref="myKeyBean" value-ref="myValueBean"/>
+
+ Again, the shortcut form is equivalent to a <ref
+ bean="xxx"> element; there is no shortcut for
+ <ref local="xxx">.
+
+
+
+ The p-namespace and how to use it to configure
+ properties
+
+ The second option you have to limit the amount of XML you have
+ to write to configure your components is to use the special
+ "p-namespace". Spring 2.0 and later features support for extensible
+ configuration formats using
+ namespaces. Those namespaces are all based on an XML Schema
+ definition. In fact, the beans configuration
+ format that you've been reading about is defined in an XML Schema
+ document.
+
+ One special namespace is not defined in an XSD file, and only
+ exists in the core of Spring itself. The so-called p-namespace
+ doesn't need a schema definition and is an alternative way of
+ configuring your properties differently than the way you have seen
+ so far. Instead of using nested <property/>
+ elements, using the p-namespace you can use attributes as part of
+ the bean element that describe your property
+ values. The values of the attributes will be taken as the values for
+ your properties.
+
+ The following two XML snippets boil down to the same thing in
+ the end: the first is using the standard XML format whereas the
+ second example is using the p-namespace.
+
+ <beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean name="classic" class="com.example.ExampleBean">
+ <property name="email" value="foo@bar.com/>
+ </bean>
+
+ <bean name="p-namespace" class="com.example.ExampleBean"
+ p:email="foo@bar.com"/>
+</beans>
+
+ As you can see, we are including an attribute in the
+ p-namespace called email in the bean definition - this is telling
+ Spring that it should include a property declaration. As previously
+ mentioned, the p-namespace doesn't have a schema definition, so the
+ name of the attribute can be set to whatever name your property
+ has.
+
+ This next example includes two more bean definitions that both
+ have a reference to another bean:
+
+ <beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean name="john-classic" class="com.example.Person">
+ <property name="name" value="John Doe"/>
+ <property name="spouse" ref="jane"/>
+ </bean>
+
+ <bean name="john-modern"
+ class="com.example.Person"
+ p:name="John Doe"
+ p:spouse-ref="jane"/>
+
+ <bean name="jane" class="com.example.Person">
+ <property name="name" value="Jane Doe"/>
+ </bean>
+</beans>
+
+ As you can see, this example doesn't only include a property
+ value using the p-namespace, but also uses a special format to
+ declare property references. Whereas the first bean definition uses
+ <property name="spouse" ref="jane"/> to
+ create a reference from bean john to bean
+ jane, the second bean definition uses
+ p:spouse-ref="jane" as an attribute to do the
+ exact same thing. In this case 'spouse' is the
+ property name whereas the '-ref' part indicates
+ that this is not a straight value but rather a reference to another
+ bean.
+
+
+ Please note that the p-namespace is not quite as flexible as
+ the standard XML format - for example particular, the 'special'
+ format used to declare property references will clash with
+ properties that end in 'Ref', whereas the
+ standard XML format would have no problem there. We recommend that
+ you choose carefully which approach you are going to use in your
+ projects. You should also communicate this to your team members so
+ you won't end up with XML documents using all three approaches at
+ the same time. This will prevent people from not understanding the
+ application because of different ways of configuring it, and will
+ add to the overall consistency of your codebase.
+
+
+
+
+
+ Compound property names
+
+ Compound or nested property names are perfectly legal when
+ setting bean properties, as long as all components of the path except
+ the final property name are not null. Consider the
+ following bean definition...
+
+ <bean id="foo" class="foo.Bar">
+ <property name="fred.bob.sammy" value="123" />
+</bean>
+
+ The foo bean has a fred
+ property which has a bob property, which has a
+ sammy property, and that final
+ sammy property is being set to the value
+ 123. In order for this to work, the
+ fred property of foo, and the
+ bob property of fred must not be
+ null be non-null after the bean is constructed, or
+ a NullPointerException will be
+ thrown.
+
+
+
+
+ Using depends-on
+
+ For most situations, the fact that a bean is a dependency of
+ another is expressed by the fact that one bean is set as a property of
+ another. This is typically accomplished with the <ref/>
+ element in XML-based configuration metadata. For the relatively
+ infrequent situations where dependencies between beans are less direct
+ (for example, when a static initializer in a class needs to be
+ triggered, such as database driver registration), the
+ 'depends-on' attribute may be used to explicitly
+ force one or more beans to be initialized before the bean using this
+ element is initialized. Find below an example of using the
+ 'depends-on' attribute to express a dependency on a
+ single bean.
+
+ <bean id="beanOne" class="ExampleBean" depends-on="manager"/>
+
+<bean id="manager" class="ManagerBean" />
+
+ If you need to express a dependency on multiple beans, you can
+ supply a list of bean names as the value of the
+ 'depends-on' attribute, with commas, whitespace and
+ semicolons all valid delimiters, like so:
+
+ <bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
+ <property name="manager" ref="manager" />
+</bean>
+
+<bean id="manager" class="ManagerBean" />
+<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
+
+
+ The 'depends-on' attribute at the bean definition
+ level is used not only to specify an initialization time dependency, but
+ also to specify the corresponding destroy time dependency (in the case of
+ singleton beans
+ only). Dependent beans that define a 'depends-on'
+ relationship with a given bean will be destroyed first - prior to the given
+ bean itself being destroyed. As a consequence, 'depends-on'
+ may be used to control shutdown order too.
+
+
+
+
+ Lazily-instantiated beans
+
+ The default behavior for
+ ApplicationContext implementations is to
+ eagerly pre-instantiate all singleton beans at
+ startup. Pre-instantiation means that an
+ ApplicationContext will eagerly create
+ and configure all of its singleton beans as part
+ of its initialization process. Generally this is a good
+ thing, because it means that any errors in the configuration
+ or in the surrounding environment will be discovered immediately (as
+ opposed to possibly hours or even days down the line).
+
+ However, there are times when this behavior is
+ not what is wanted. If you do not want a singleton
+ bean to be pre-instantiated when using an
+ ApplicationContext, you can selectively
+ control this by marking a bean definition as lazy-initialized. A
+ lazily-initialized bean indicates to the IoC container whether or not a
+ bean instance should be created at startup or when it is first
+ requested.
+
+ When configuring beans via XML, this lazy loading is controlled by
+ the 'lazy-init' attribute on the
+ <bean/> element; for example:
+
+ <bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
+
+<bean name="not.lazy" class="com.foo.AnotherBean"/>
+
+ When the above configuration is consumed by an
+ ApplicationContext, the bean named
+ 'lazy' will not be eagerly
+ pre-instantiated when the
+ ApplicationContext is starting up,
+ whereas the 'not.lazy' bean will be eagerly
+ pre-instantiated.
+
+ One thing to understand about lazy-initialization is that even
+ though a bean definition may be marked up as being lazy-initialized, if
+ the lazy-initialized bean is the dependency of a singleton bean that is
+ not lazy-initialized, when the
+ ApplicationContext is eagerly
+ pre-instantiating the singleton, it will have to satisfy all of the
+ singletons dependencies, one of which will be the lazy-initialized bean!
+ So don't be confused if the IoC container creates one of the beans that
+ you have explicitly configured as lazy-initialized at startup; all that
+ means is that the lazy-initialized bean is being injected into a
+ non-lazy-initialized singleton bean elsewhere.
+
+ It is also possible to control lazy-initialization at the
+ container level by using the 'default-lazy-init'
+ attribute on the <beans/> element; for
+ example:
+
+ <beans default-lazy-init="true">
+ <!-- no beans will be pre-instantiated... -->
+</beans>
+
+
+
+ Autowiring collaborators
+
+ The Spring container is able to autowire
+ relationships between collaborating beans. This means that it is
+ possible to automatically let Spring resolve collaborators (other beans)
+ for your bean by inspecting the contents of the
+ BeanFactory. The autowiring functionality
+ has five modes. Autowiring is specified per bean
+ and can thus be enabled for some beans, while other beans will not be
+ autowired. Using autowiring, it is possible to reduce or eliminate the
+ need to specify properties or constructor arguments, thus saving a
+ significant amount of typing.
+ See the section entitled
+ When using XML-based configuration metadata, the autowire
+ mode for a bean definition is specified by using the
+ autowire attribute of the
+ <bean/> element. The following values are
+ allowed:
+
+
+ Autowiring modes
+
+
+
+
+
+
+
+ Mode
+ Explanation
+
+
+
+
+
+ no
+
+ No autowiring at all. Bean references must be
+ defined via a ref element. This is the
+ default, and changing this is discouraged for larger
+ deployments, since explicitly specifying collaborators gives
+ greater control and clarity. To some extent, it is a form of
+ documentation about the structure of a system.
+
+
+
+ byName
+
+ Autowiring by property name. This option will
+ inspect the container and look for a bean named exactly the same
+ as the property which needs to be autowired. For example, if you
+ have a bean definition which is set to autowire by name, and it
+ contains a master property (that is, it has
+ a setMaster(..) method), Spring will look
+ for a bean definition named master, and use
+ it to set the property.
+
+
+
+ byType
+
+ Allows a property to be autowired if there is
+ exactly one bean of the property type in the container. If there
+ is more than one, a fatal exception is thrown, and this
+ indicates that you may not use byType
+ autowiring for that bean. If there are no matching beans,
+ nothing happens; the property is not set. If this is not
+ desirable, setting the
+ dependency-check="objects" attribute value
+ specifies that an error should be thrown in this
+ case.
+
+
+
+ constructor
+
+ This is analogous to byType,
+ but applies to constructor arguments. If there isn't exactly one
+ bean of the constructor argument type in the container, a fatal
+ error is raised.
+
+
+
+ autodetect
+
+ Chooses constructor or
+ byType through introspection of the bean
+ class. If a default constructor is found, the
+ byType mode will be applied.
+
+
+
+
+
+ Note that explicit dependencies in property and
+ constructor-arg settings
+ always override autowiring. Please also
+ note that it is not currently possible to autowire so-called
+ simple properties such as primitives,
+ Strings, and Classes (and
+ arrays of such simple properties). (This is by-design and should be
+ considered a feature.) When using either the
+ byType or constructor
+ autowiring mode, it is possible to wire arrays and typed-collections. In
+ such cases all autowire candidates within the
+ container that match the expected type will be provided to satisfy the
+ dependency. Strongly-typed Maps can even be autowired if the expected
+ key type is String. An autowired Map's values
+ will consist of all bean instances that match the expected type, and the
+ Map's keys will contain the corresponding bean names.
+
+ Autowire behavior can be combined with dependency checking, which
+ will be performed after all autowiring has been completed.
+
+ It is important to understand the various advantages and
+ disadvantages of autowiring. Some advantages of autowiring
+ include:
+
+
+
+ Autowiring can significantly reduce the volume of
+ configuration required. However, mechanisms such as the use of a
+ bean template (discussed elsewhere in this
+ chapter) are also valuable in this regard.
+
+
+
+ Autowiring can cause configuration to keep itself up to date
+ as your objects evolve. For example, if you need to add an
+ additional dependency to a class, that dependency can be satisfied
+ automatically without the need to modify configuration. Thus there
+ may be a strong case for autowiring during development, without
+ ruling out the option of switching to explicit wiring when the code
+ base becomes more stable.
+
+
+
+ Some disadvantages of autowiring:
+
+
+
+ Autowiring is more magical than explicit wiring. Although, as
+ noted in the above table, Spring is careful to avoid guessing in
+ case of ambiguity which might have unexpected results, the
+ relationships between your Spring-managed objects are no longer
+ documented explicitly.
+
+
+
+ Wiring information may not be available to tools that may
+ generate documentation from a Spring container.
+
+
+
+ Another issue to consider when autowiring by type is that multiple
+ bean definitions within the container may match the type specified by
+ the setter method or constructor argument to be autowired. For arrays,
+ collections, or Maps, this is not necessarily a problem. However for
+ dependencies that expect a single value, this ambiguity will not be
+ arbitrarily resolved. Instead, if no unique bean definition is
+ available, an Exception will be thrown. You do have several options when
+ confronted with this scenario. First, you may abandon autowiring in
+ favor of explicit wiring. Second, you may designate that certain bean
+ definitions are never to be considered as candidates by setting their
+ 'autowire-candidate' attributes to
+ 'false' as described in the next section. Third, you
+ may designate a single bean definition as the
+ primary candidate by setting the
+ 'primary' attribute of its
+ <bean/> element to 'true'.
+ Finally, if you are using at least Java 5, you may be interested in
+ exploring the more fine-grained control available with annotation-based
+ configuration as described in the section entitled .
+
+ When deciding whether to use autowiring, there is no wrong or
+ right answer in all cases. A degree of consistency across a project is
+ best though; for example, if autowiring is not used in general, it might
+ be confusing to developers to use it just to wire one or two bean
+ definitions.
+
+
+ Excluding a bean from being available for autowiring
+
+ You can also (on a per-bean basis) totally exclude a bean from
+ being an autowire candidate. When configuring beans using Spring's XML
+ format, the 'autowire-candidate' attribute of the
+ <bean/> element can be set to
+ 'false'; this has the effect of making the
+ container totally exclude that specific bean definition from being
+ available to the autowiring infrastructure.
+
+ Another option is to limit autowire candidates based on
+ pattern-matching against bean names. The top-level
+ <beans/> element accepts one or more patterns
+ within its 'default-autowire-candidates' attribute.
+ For example, to limit autowire candidate status to any bean whose name
+ ends with 'Repository', provide a value of
+ '*Repository'. To provide multiple patterns, define them in a
+ comma-separated list. Note that an explicit value of
+ 'true' or 'false' for a bean
+ definition's 'autowire-candidate' attribute always
+ takes precedence, and for such beans, the pattern matching rules will
+ not apply.
+
+ These techniques can be useful when you have one or more beans
+ that you absolutely never ever want to have injected into other beans
+ via autowiring. It does not mean that an excluded bean cannot itself
+ be configured using autowiring... it can, it is rather that it itself
+ will not be considered as a candidate for autowiring other
+ beans.
+
+
+
+
+ Checking for dependencies
+
+ The Spring IoC container also has the ability to check for the
+ existence of unresolved dependencies of a bean deployed into the
+ container. These are JavaBeans properties of the bean, which do not have
+ actual values set for them in the bean definition, or alternately
+ provided automatically by the autowiring feature.
+
+ This feature is sometimes useful when you want to ensure that all
+ properties (or all properties of a certain type) are set on a bean. Of
+ course, in many cases a bean class will have default values for many
+ properties, or some properties do not apply to all usage scenarios, so
+ this feature is of limited use. Dependency checking can also be enabled
+ and disabled per bean, just as with the autowiring functionality. The
+ default is to not check dependencies. Dependency
+ checking can be handled in several different modes. When using XML-based
+ configuration metadata, this is specified via the
+ 'dependency-check' attribute in a bean definition,
+ which may have the following values.
+
+
+ Dependency checking modes
+
+
+
+
+
+
+
+ Mode
+
+ Explanation
+
+
+
+
+
+ none
+
+ No dependency checking. Properties of the bean
+ which have no value specified for them are simply not
+ set.
+
+
+
+ simple
+
+ Dependency checking is performed for primitive
+ types and collections (everything except
+ collaborators).
+
+
+
+ object
+
+ Dependency checking is performed for collaborators
+ only.
+
+
+
+ all
+
+ Dependency checking is done for collaborators,
+ primitive types and collections.
+
+
+
+
+
+ If you are using Java 5 and thus have access to source-level
+ annotations, you may find the section entitled to be of interest.
+
+
+
+ Method Injection
+
+ For most application scenarios, the majority of the beans in the
+ container will be singletons. When a
+ singleton bean needs to collaborate with another singleton bean, or a
+ non-singleton bean needs to collaborate with another non-singleton bean,
+ the typical and common approach of handling this dependency by defining
+ one bean to be a property of the other is quite adequate. There is a
+ problem when the bean lifecycles are different. Consider a singleton
+ bean A which needs to use a non-singleton (prototype) bean B, perhaps on
+ each method invocation on A. The container will only create the
+ singleton bean A once, and thus only get the opportunity to set the
+ properties once. There is no opportunity for the container to provide
+ bean A with a new instance of bean B every time one is needed.
+
+ One solution to this issue is to forego some inversion of control.
+ Bean A can be made
+ aware of the container by implementing the
+ BeanFactoryAware interface, and use programmatic means to ask the
+ container via a getBean("B") call for (a
+ typically new) bean B instance every time it needs it. Find below an
+ admittedly somewhat contrived example of this approach:
+
+ // a class that uses a stateful Command-style class to perform some processing
+package fiona.apple;
+
+// lots of Spring-API imports
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+
+public class CommandManager implements BeanFactoryAware {
+
+ private BeanFactory beanFactory;
+
+ public Object process(Map commandState) {
+ // grab a new instance of the appropriate Command
+ Command command = createCommand();
+ // set the state on the (hopefully brand new) Command instance
+ command.setState(commandState);
+ return command.execute();
+ }
+
+ // the Command returned here could be an implementation that executes asynchronously, or whatever
+ protected Command createCommand() {
+ return (Command) this.beanFactory.getBean("command"); // notice the Spring API dependency
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+}
+
+ The above example is generally not a desirable solution since the
+ business code is then aware of and coupled to the Spring Framework.
+ Method Injection, a somewhat advanced feature of the Spring IoC
+ container, allows this use case to be handled in a clean fashion.
+
+
+ Lookup method injection
+
+
+ Isn't this Method Injection...
+
+ ... somewhat like Tapestry 4.0's pages, where folks wrote
+ abstract properties that Tapestry would override
+ at runtime with implementations that did stuff? It sure is (well,
+ somewhat).
+
+ You can read more about the motivation for Method Injection in
+ this blog
+ entry.
+
+
+ Lookup method injection refers to the ability of the container
+ to override methods on container managed beans,
+ to return the result of looking up another named bean in the
+ container. The lookup will typically be of a prototype bean as in the
+ scenario described above. The Spring Framework implements this method
+ injection by dynamically generating a subclass overriding the method,
+ using bytecode generation via the CGLIB library.
+
+ So if you look at the code from previous code snippet (the
+ CommandManager class), the Spring container is
+ going to dynamically override the implementation of the
+ createCommand() method. Your
+ CommandManager class is not going to have any
+ Spring dependencies, as can be seen in this reworked example
+ below:
+
+ package fiona.apple;
+
+// no more Spring imports!
+
+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();
+}
+
+ In the client class containing the method to be injected (the
+ CommandManager in this case), the method that
+ is to be 'injected' must have a signature of the following
+ form:
+
+ <public|protected> [abstract] <return-type> theMethodName(no-arguments);
+
+ If the method is abstract, the
+ dynamically-generated subclass will implement the method. Otherwise,
+ the dynamically-generated subclass will override the concrete method
+ defined in the original class. Let's look at an example:
+
+ <!-- a stateful bean deployed as a prototype (non-singleton) -->
+<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
+ <!-- inject dependencies here as required -->
+</bean>
+
+<!-- commandProcessor uses statefulCommandHelper -->
+<bean id="commandManager" class="fiona.apple.CommandManager">
+ <lookup-method name="createCommand" bean="command"/>
+</bean>
+
+ The bean identified as commandManager will
+ call its own method createCommand() whenever
+ it needs a new instance of the command bean. It
+ is important to note that the person deploying the beans must be
+ careful to deploy the command bean as a prototype
+ (if that is actually what is needed). If it is deployed as a singleton, the same
+ instance of the command bean will be returned each
+ time!
+
+ Please be aware that in order for this dynamic subclassing to
+ work, you will need to have the CGLIB jar(s) on your classpath.
+ Additionally, the class that the Spring container is going to subclass
+ cannot be final, and the method that is being
+ overridden cannot be final either. Also, testing a
+ class that has an abstract method can be somewhat
+ odd in that you will have to subclass the class yourself and supply a
+ stub implementation of the abstract method.
+ Finally, objects that have been the target of method injection cannot
+ be serialized.
+
+
+ The interested reader may also find the
+ ServiceLocatorFactoryBean (in the
+ org.springframework.beans.factory.config package)
+ to be of use; the approach is similar to that of the
+ ObjectFactoryCreatingFactoryBean, but it
+ allows you to specify your own lookup interface as opposed to having
+ to use a Spring-specific lookup interface such as the
+ ObjectFactory. Consult the (copious)
+ Javadoc for the ServiceLocatorFactoryBean for
+ a full treatment of this alternative approach (that
+ does reduce the coupling to Spring).
+
+
+
+
+ Arbitrary method replacement
+
+ A less commonly useful form of method injection than Lookup
+ Method Injection is the ability to replace arbitrary methods in a
+ managed bean with another method implementation. Users may safely skip
+ the rest of this section (which describes this somewhat advanced
+ feature), until this functionality is actually needed.
+
+ When using XML-based configuration metadata, the
+ replaced-method element may be used to replace an
+ existing method implementation with another, for a deployed bean.
+ Consider the following class, with a method computeValue, which we
+ want to override:
+
+ public class MyValueCalculator {
+
+ public String computeValue(String input) {
+ // some real code...
+ }
+
+ // some other methods...
+
+}
+
+ A class implementing the
+ org.springframework.beans.factory.support.MethodReplacer
+ interface provides the new method definition.
+
+ /** meant to be used to override the existing computeValue(String)
+ implementation in MyValueCalculator
+ */
+public class ReplacementComputeValue implements MethodReplacer {
+
+ public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
+ // get the input value, work with it, and return a computed result
+ String input = (String) args[0];
+ ...
+ return ...;
+ }
+}
+
+ The bean definition to deploy the original class and specify the
+ method override would look like this:
+
+ <bean id="myValueCalculator class="x.y.z.MyValueCalculator">
+ <!-- arbitrary method replacement -->
+ <replaced-method name="computeValue" replacer="replacementComputeValue">
+ <arg-type>String</arg-type>
+ </replaced-method>
+</bean>
+
+<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>
+
+ One or more contained <arg-type/>
+ elements within the <replaced-method/>
+ element may be used to indicate the method signature of the method
+ being overridden. Note that the signature for the arguments is
+ actually only needed in the case that the method is actually
+ overloaded and there are multiple variants within the class. For
+ convenience, the type string for an argument may be a substring of the
+ fully qualified type name. For example, all the following would match
+ java.lang.String.
+
+ java.lang.String
+ String
+ Str
+
+ Since the number of arguments is often enough to distinguish
+ between each possible choice, this shortcut can save a lot of typing,
+ by allowing you to type just the shortest string that will match an
+ argument type.
+
+
+
+
+
+ Bean scopes
+
+ When you create a bean definition what you are actually creating is
+ a recipe for creating actual instances of the class
+ defined by that bean definition. The idea that a bean definition is a
+ recipe is important, because it means that, just like a class, you can
+ potentially have many object instances created from a single
+ recipe.
+
+ 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 scope of
+ the objects created from a particular bean definition. This approach is
+ very powerful and gives you the flexibility to choose
+ the scope of the objects you create through configuration instead of
+ having to 'bake in' the scope of an object at the Java class level. Beans
+ can be defined to be deployed in one of a number of scopes: out of the
+ box, the Spring Framework supports exactly five scopes (of which three are
+ available only if you are using a web-aware
+ ApplicationContext).
+
+ The scopes supported out of the box are listed below:
+
+
+ Bean scopes
+
+
+
+
+ Scope
+
+ Description
+
+
+
+
+
+
+
+ singleton
+
+
+
+
+ Scopes a single bean definition to a single object
+ instance per Spring IoC container.
+
+
+
+
+
+
+ prototype
+
+
+
+
+ Scopes a single bean definition to any number of object
+ instances.
+
+
+
+
+
+
+ request
+
+
+
+
+ Scopes a single bean definition to the lifecycle of a
+ single HTTP request; that is each and every HTTP request will
+ have its own instance of a bean created off the back of a single
+ bean definition. Only valid in the context of a web-aware Spring
+ ApplicationContext.
+
+
+
+
+
+
+ session
+
+
+
+
+ Scopes a single bean definition to the lifecycle of a HTTP
+ Session. Only valid in the
+ context of a web-aware Spring
+ ApplicationContext.
+
+
+
+
+
+
+ global
+ session
+
+
+
+
+ Scopes a single bean definition to the lifecycle of a
+ global HTTP Session. Typically
+ only valid when used in a portlet context. Only valid in the
+ context of a web-aware Spring
+ ApplicationContext.
+
+
+
+
+
+
+
+ The singleton scope
+
+ When a bean is a singleton, only one shared
+ instance of the bean will be managed, and all requests for beans with an
+ id or ids matching that bean definition will result
+ in that one specific bean instance being returned by the Spring
+ container.
+
+ To put it another way, when you define a bean definition and it is
+ scoped as a singleton, then the Spring IoC container will create
+ exactly one instance of the object defined by that
+ bean definition. This single instance will be stored in a cache of such
+ singleton beans, and all subsequent requests and
+ references for that named bean will result in the cached
+ object being returned.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please be aware that Spring's concept of a singleton bean is quite
+ different from the Singleton pattern as defined in the seminal Gang of
+ Four (GoF) patterns book. The GoF Singleton hard codes the scope of an
+ object such that one and only one instance of a
+ particular class will ever be created per
+ ClassLoader. The scope of the Spring
+ singleton is best described as per container and per
+ bean. This means that if you define one bean for a particular
+ class in a single Spring container, then the Spring container will
+ create one and only one instance of the class
+ defined by that bean definition. The singleton scope is the
+ default scope in Spring. To define a bean as a singleton in
+ XML, you would write configuration like so:
+
+ <bean id="accountService" class="com.foo.DefaultAccountService"/>
+
+<!-- the following is equivalent, though redundant (singleton scope is the default); using spring-beans-2.0.dtd -->
+<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>
+
+<!-- the following is equivalent and preserved for backward compatibility in spring-beans.dtd -->
+<bean id="accountService" class="com.foo.DefaultAccountService" singleton="true"/>
+
+
+
+ The prototype scope
+
+ The non-singleton, prototype scope of bean deployment results in
+ the creation of a new bean instance every time a
+ request for that specific bean is made (that is, it is injected into
+ another bean or it is requested via a programmatic
+ getBean() method call on the container). As a rule of
+ thumb, you should use the prototype scope for all beans that are
+ stateful, while the singleton scope should be used for stateless
+ beans.
+
+ The following diagram illustrates the Spring prototype scope.
+ Please note that a DAO would not typically be configured as a
+ prototype, since a typical DAO would not hold any conversational state;
+ it was just easier for this author to reuse the core of the singleton
+ diagram.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To define a bean as a prototype in XML, you would write
+ configuration like so:
+
+ <!-- using spring-beans-2.0.dtd -->
+<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
+
+<!-- the following is equivalent and preserved for backward compatibility in spring-beans.dtd -->
+<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>
+
+ There is one quite important thing to be aware of when deploying a
+ bean in the prototype scope, in that the lifecycle of the bean changes
+ slightly. Spring does not manage the complete lifecycle of a prototype
+ bean: the container instantiates, configures, decorates and otherwise
+ assembles a prototype object, hands it to the client and then has no
+ further knowledge of that prototype instance. This means that while
+ initialization lifecycle callback methods will be
+ called on all objects regardless of scope, in the case of prototypes,
+ any configured destruction lifecycle callbacks will
+ not be called. It is the responsibility of the
+ client code to clean up prototype scoped objects and release any
+ expensive resources that the prototype bean(s) are holding onto. (One
+ possible way to get the Spring container to release resources used by
+ prototype-scoped beans is through the use of a custom bean post-processor which
+ would hold a reference to the beans that need to be cleaned up.)
+
+ In some respects, you can think of the Spring containers role when
+ talking about a prototype-scoped bean as somewhat of a replacement for
+ the Java 'new' operator. All lifecycle aspects past
+ that point have to be handled by the client. (The lifecycle of a bean in
+ the Spring container is further described in the section entitled .)
+
+
+
+ Singleton beans with prototype-bean dependencies
+
+ When using singleton-scoped beans that have dependencies on beans
+ that are scoped as prototypes, please be aware that
+ dependencies are resolved at instantiation time.
+ This means that if you dependency inject a prototype-scoped bean into a
+ singleton-scoped bean, a brand new prototype bean will be instantiated
+ and then dependency injected into the singleton bean... but
+ that is all. That exact same prototype instance will be the
+ sole instance that is ever supplied to the singleton-scoped bean, which
+ is fine if that is what you want.
+
+ However, sometimes what you actually want is for the
+ singleton-scoped bean to be able to acquire a brand new instance of the
+ prototype-scoped bean again and again and again at runtime. In that case
+ it is no use just dependency injecting a prototype-scoped bean into your
+ singleton bean, because as explained above, that only happens
+ once when the Spring container is instantiating the
+ singleton bean and resolving and injecting its dependencies. If you are
+ in the scenario where you need to get a brand new instance of a
+ (prototype) bean again and again and again at runtime, you are referred
+ to the section entitled
+
+
+
+ Backwards compatibility note: specifying the lifecycle scope in
+ XML
+
+ If you are referencing the 'spring-beans.dtd'
+ DTD in a bean definition file(s), and you are being explicit about the
+ lifecycle scope of your beans you must use the
+ "singleton" attribute to express the lifecycle scope
+ (remembering that the singleton lifecycle
+ scope is the default). If you are referencing the
+ 'spring-beans-2.0.dtd' DTD or the Spring 2.0 XSD
+ schema, then you will need to use the "scope"
+ attribute (because the "singleton" attribute was
+ removed from the definition of the new DTD and XSD files in favor of the
+ "scope" attribute).
+
+ To be totally clear about this, this means that if you use the
+ "singleton" attribute in an XML bean definition then
+ you must be referencing the
+ 'spring-beans.dtd' DTD in that
+ file. If you are using the "scope"
+ attribute then you must be referencing either the
+ 'spring-beans-2.0.dtd' DTD or the
+ 'spring-beans-2.5.xsd' XSD in that
+ file.
+
+
+
+ The other scopes
+
+ The other scopes, namely request,
+ session, and global session are
+ for use only in web-based applications (and can be used irrespective of
+ which particular web application framework you are using, if indeed
+ any). In the interest of keeping related concepts together in one place
+ in the reference documentation, these scopes are described here.
+
+
+ The scopes that are described in the following paragraphs are
+ only available if you are using a web-aware
+ Spring ApplicationContext
+ implementation (such as
+ XmlWebApplicationContext). If you try using
+ these next scopes with regular Spring IoC containers such as the
+ XmlBeanFactory or
+ ClassPathXmlApplicationContext, you
+ will get an
+ IllegalStateException complaining about an
+ unknown bean scope.
+
+
+
+ Initial web configuration
+
+ In order to support the scoping of beans at the
+ request, session, and
+ global session levels (web-scoped beans), some
+ minor initial configuration is required before you can set about
+ defining your bean definitions. Please note that this extra setup is
+ not required if you just want to use the
+ 'standard' scopes (namely singleton and prototype).
+
+ Now as things stand, there are a couple of ways to effect this
+ initial setup depending on your particular Servlet
+ environment...
+
+ If you are accessing scoped beans within Spring Web MVC, i.e.
+ within a request that is processed by the Spring
+ DispatcherServlet, or
+ DispatcherPortlet, then no special setup is
+ necessary: DispatcherServlet and
+ DispatcherPortlet already expose all relevant
+ state.
+
+ When using a Servlet 2.4+ web container, with requests processed
+ outside of Spring's DispatcherServlet (e.g. when using JSF or Struts),
+ you need to add the following
+ javax.servlet.ServletRequestListener to
+ the declarations in your web application's
+ 'web.xml' file.
+
+ <web-app>
+ ...
+ <listener>
+ <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
+ </listener>
+ ...
+</web-app>
+
+ If you are using an older web container (Servlet 2.3), you will
+ need to use the provided
+ javax.servlet.Filter implementation.
+ Find below a snippet of XML configuration that has to be included in
+ the 'web.xml' file of your web application if you
+ want to have access to web-scoped beans in requests outside of
+ Spring's DispatcherServlet on a Servlet 2.3 container. (The filter
+ mapping depends on the surrounding web application configuration and
+ so you will have to change it as appropriate.)
+
+ <web-app>
+ ..
+ <filter>
+ <filter-name>requestContextFilter</filter-name>
+ <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>requestContextFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ ...
+</web-app>
+
+ That's it. DispatcherServlet,
+ RequestContextListener and
+ RequestContextFilter all do exactly the same
+ thing, namely bind the HTTP request object to the
+ Thread that is servicing that request. This
+ makes beans that are request- and session-scoped available further
+ down the call chain.
+
+
+
+ The request scope
+
+ Consider the following bean definition:
+
+ <bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
+
+ With the above bean definition in place, the Spring container
+ will create a brand new instance of the
+ LoginAction bean using the
+ 'loginAction' bean definition for each and every
+ HTTP request. That is, the 'loginAction' bean will
+ be effectively scoped at the HTTP request level. You can change or
+ dirty the internal state of the instance that is created as much as
+ you want, safe in the knowledge that other requests that are also
+ using instances created off the back of the same
+ 'loginAction' bean definition will not be seeing
+ these changes in state since they are particular to an individual
+ request. When the request is finished processing, the bean that is
+ scoped to the request will be discarded.
+
+
+
+ The session scope
+
+ Consider the following bean definition:
+
+ <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
+
+ With the above bean definition in place, the Spring container
+ will create a brand new instance of the
+ UserPreferences bean using the
+ 'userPreferences' bean definition for the lifetime
+ of a single HTTP Session. In other
+ words, the 'userPreferences' bean will be
+ effectively scoped at the HTTP Session
+ level. Just like request-scoped beans, you can
+ change the internal state of the instance that is created as much as
+ you want, safe in the knowledge that other HTTP
+ Session instances that are also using
+ instances created off the back of the same
+ 'userPreferences' bean definition will not be
+ seeing these changes in state since they are particular to an
+ individual HTTP Session. When the HTTP
+ Session is eventually discarded, the
+ bean that is scoped to that particular HTTP
+ Session will also be discarded.
+
+
+
+ The global session scope
+
+ Consider the following bean definition:
+
+ <bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
+
+ The global session scope is similar to the
+ standard HTTP Session scope (described immediately
+ above), and really only makes sense in the context of
+ portlet-based web applications. The portlet specification defines the
+ notion of a global Session that is
+ shared amongst all of the various portlets that make up a single
+ portlet web application. Beans defined at the global
+ session scope are scoped (or bound) to the lifetime of the
+ global portlet Session.
+
+ Please note that if you are writing a standard Servlet-based web
+ application and you define one or more beans as having global
+ session scope, the standard HTTP
+ Session scope will be used, and no
+ error will be raised.
+
+
+
+ Scoped beans as dependencies
+
+ Being able to define a bean scoped to a HTTP request or
+ Session (or indeed a custom scope of your
+ own devising) is all very well, but one of the main value-adds of the
+ Spring IoC container is that it manages not only the instantiation of
+ your objects (beans), but also the wiring up of collaborators (or
+ dependencies). If you want to inject a (for example) HTTP request
+ scoped bean into another bean, you will need to inject an AOP proxy in
+ place of the scoped bean. That is, you need to inject a proxy object
+ that exposes the same public interface as the scoped object, but that
+ is smart enough to be able to retrieve the real, target object from
+ the relevant scope (for example a HTTP request) and delegate method
+ calls onto the real object.
+
+
+ You do not need to use the
+ <aop:scoped-proxy/> in conjunction with
+ beans that are scoped as singletons or
+ prototypes. It is an error to try to create a
+ scoped proxy for a singleton bean (and the resulting
+ BeanCreationException will certainly
+ set you straight in this regard).
+
+
+ Let's look at the configuration that is required to effect this;
+ the configuration is not hugely complex (it takes just one line), but
+ it is important to understand the why as well as the
+ how behind it.
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <!-- a HTTP Session-scoped bean exposed as a proxy -->
+ <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
+
+ <!-- this next element effects the proxying of the surrounding bean -->
+ <aop:scoped-proxy/>
+ </bean>
+
+ <!-- a singleton-scoped bean injected with a proxy to the above bean -->
+ <bean id="userService" class="com.foo.SimpleUserService">
+
+ <!-- a reference to the proxied'userPreferences' bean -->
+ <property name="userPreferences" ref="userPreferences"/>
+
+ </bean>
+</beans>
+
+
+ To create such a proxy, you need only to insert a child
+ <aop:scoped-proxy/> element into a scoped
+ bean definition (you may also need the CGLIB library on your classpath
+ so that the container can effect class-based proxying; you will also
+ need to be using ). So, just why do you
+ need this <aop:scoped-proxy/> element in the
+ definition of beans scoped at the request,
+ session, globalSession and
+ 'insert your custom scope here' level? The reason
+ is best explained by picking apart the following bean definition
+ (please note that the following 'userPreferences'
+ bean definition as it stands is
+ incomplete):
+
+ <bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
+
+<bean id="userManager" class="com.foo.UserManager">
+ <property name="userPreferences" ref="userPreferences"/>
+</bean>
+
+ From the above configuration it is evident that the singleton
+ bean 'userManager' is being injected with a
+ reference to the HTTP Session-scoped
+ bean 'userPreferences'. The salient point here is
+ that the 'userManager' bean is a singleton... it
+ will be instantiated exactly once per container,
+ and its dependencies (in this case only one, the
+ 'userPreferences' bean) will also only be injected
+ (once!). This means that the 'userManager' will
+ (conceptually) only ever operate on the exact same
+ 'userPreferences' object, that is the one that it
+ was originally injected with. This is not what
+ you want when you inject a HTTP
+ Session-scoped bean as a dependency
+ into a collaborating object (typically). Rather, what we
+ do want is a single
+ 'userManager' object, and then, for the lifetime of
+ a HTTP Session, we want to see and use
+ a 'userPreferences' object that is specific to said
+ HTTP Session.
+
+ Rather what you need then is to inject some sort of object that
+ exposes the exact same public interface as the
+ UserPreferences class (ideally an object that
+ is aUserPreferences
+ instance) and that is smart enough to be able to go off and fetch the
+ real
+ UserPreferences object from whatever underlying
+ scoping mechanism we have chosen (HTTP request,
+ Session, etc.). We can then safely
+ inject this proxy object into the 'userManager'
+ bean, which will be blissfully unaware that the
+ UserPreferences reference that it is holding
+ onto is a proxy. In the case of this example, when a
+ UserManager instance invokes a method
+ on the dependency-injected UserPreferences
+ object, it is really invoking a method on the proxy... the proxy will
+ then go off and fetch the real UserPreferences
+ object from (in this case) the HTTP
+ Session, and delegate the method
+ invocation onto the retrieved real
+ UserPreferences object.
+
+ That is why you need the following, correct and complete,
+ configuration when injecting request-,
+ session-, and
+ globalSession-scoped beans into collaborating
+ objects:
+
+ <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
+ <aop:scoped-proxy/>
+</bean>
+
+<bean id="userManager" class="com.foo.UserManager">
+ <property name="userPreferences" ref="userPreferences"/>
+</bean>
+
+
+ Choosing the type of proxy created
+
+ By default, when the Spring container is creating a proxy for
+ a bean that is marked up with the <aop:scoped-proxy/>
+ element, a CGLIB-based class proxy will be created.
+ This means that you need to have the CGLIB library on the classpath
+ of your application.
+
+ Note: CGLIB proxies will only intercept public method
+ calls! Do not call non-public methods on such a proxy;
+ they will not be delegated to the scoped target object.
+
+ You can choose to have the Spring container create 'standard'
+ JDK interface-based proxies for such scoped beans by specifying
+ 'false' for the value of the
+ 'proxy-target-class' attribute of the
+ <aop:scoped-proxy/> element. Using JDK
+ interface-based proxies does mean that you don't need any additional
+ libraries on your application's classpath to effect such proxying,
+ but it does mean that the class of the scoped bean must implement at
+ least one interface, and all of the
+ collaborators into which the scoped bean is injected must be
+ referencing the bean via one of its interfaces.
+
+ <!-- DefaultUserPreferences implements the UserPreferences interface -->
+<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session">
+ <aop:scoped-proxy proxy-target-class="false"/>
+</bean>
+
+<bean id="userManager" class="com.foo.UserManager">
+ <property name="userPreferences" ref="userPreferences"/>
+</bean>
+
+ The section entitled may also
+ be of some interest with regard to understanding the nuances of
+ choosing whether class-based or interface-based proxying is right
+ for you.
+
+
+
+
+
+ Custom scopes
+
+ As of Spring 2.0, the bean scoping mechanism in Spring is
+ extensible. This means that you are not limited to just the bean scopes
+ that Spring provides out of the box; you can define your own scopes, or
+ even redefine the existing scopes (although that last one would probably
+ be considered bad practice - please note that you
+ cannot override the built-in
+ singleton and prototype
+ scopes).
+
+
+ Creating your own custom scope
+
+ Scopes are defined by the
+ org.springframework.beans.factory.config.Scope
+ interface. This is the interface that you will need to implement in
+ order to integrate your own custom scope(s) into the Spring container,
+ and is described in detail below. You may wish to look at the
+ Scope implementations that are supplied
+ with the Spring Framework itself for an idea of how to go about
+ implementing your own. The Scope
+ Javadoc explains the main class to implement when you need
+ your own scope in more detail too.
+
+ The Scope interface has four methods dealing
+ with getting objects from the scope, removing them from the scope and
+ allowing them to be 'destroyed' if needed.
+
+ The first method should return the object from the underlying
+ scope. The session scope implementation for example will return the
+ session-scoped bean (and if it does not exist, return a new instance
+ of the bean, after having bound it to the session for future
+ reference).
+
+ Object get(String name, ObjectFactory objectFactory)
+
+ The second method should remove the object from the underlying
+ scope. The session scope implementation for example, removes the
+ session-scoped bean from the underlying session. The object should be
+ returned (you are allowed to return null if the object with the
+ specified name wasn't found)
+
+ Object remove(String name)
+
+ The third method is used to register callbacks the scope should
+ execute when it is destroyed or when the specified object in the scope
+ is destroyed. Please refer to the Javadoc or a Spring scope
+ implementation for more information on destruction callbacks.
+
+ void registerDestructionCallback(String name, Runnable destructionCallback)
+
+ The last method deals with obtaining the conversation identifier
+ for the underlying scope. This identifier is different for each scope.
+ For a session for example, this can be the session identifier.
+
+ String getConversationId()
+
+
+
+ Using a custom scope
+
+ After you have written and tested one or more custom
+ Scope implementations, you then need to
+ make the Spring container aware of your new scope(s). The central
+ method to register a new Scope with the
+ Spring container is declared on the
+ ConfigurableBeanFactory interface
+ (implemented by most of the concrete
+ BeanFactory implementations that ship
+ with Spring); this central method is displayed below:
+
+ void registerScope(String scopeName, Scope scope);
+
+ The first argument to the
+ registerScope(..) method is the unique name
+ associated with a scope; examples of such names in the Spring
+ container itself are 'singleton' and
+ 'prototype'. The second argument to the
+ registerScope(..) method is an actual
+ instance of the custom Scope
+ implementation that you wish to register and use.
+
+ Let's assume that you have written your own custom
+ Scope implementation, and you have
+ registered it like so:
+
+ // note: the ThreadScope class does not ship with the Spring Framework
+Scope customScope = new ThreadScope();
+beanFactory.registerScope("thread", customScope);
+
+ You can then create bean definitions that adhere to the scoping
+ rules of your custom Scope like
+ so:
+
+ <bean id="..." class="..." scope="thread"/>
+
+ If you have your own custom Scope
+ implementation(s), you are not just limited to only programmatic
+ registration of the custom scope(s). You can also do the
+ Scope registration declaratively, using
+ the CustomScopeConfigurer class.
+
+ The declarative registration of custom
+ Scope implementations using the
+ CustomScopeConfigurer class is shown
+ below:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+ <property name="scopes">
+ <map>
+ <entry key="thread">
+ <bean class="com.foo.ThreadScope"/>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <bean id="bar" class="x.y.Bar" scope="thread">
+ <property name="name" value="Rick"/>
+ <aop:scoped-proxy/>
+ </bean>
+
+ <bean id="foo" class="x.y.Foo">
+ <property name="bar" ref="bar"/>
+ </bean>
+
+</beans>
+
+
+
+
+
+ Note that, when placing a <aop:scoped-proxy/> in a FactoryBean
+ implementation, it is the factory bean itself that is scoped, not the object returned from
+ getObject().
+
+
+
+ Customizing the nature of a bean
+
+
+ Lifecycle callbacks
+
+ The Spring Framework provides several callback interfaces to change
+ the behavior of your bean in the container; they include
+ InitializingBean and
+ DisposableBean. Implementing these
+ interfaces will result in the container calling
+ afterPropertiesSet() for the former and
+ destroy() for the latter to allow the bean to
+ perform certain actions upon initialization and destruction.
+
+ Internally, the Spring Framework uses
+ BeanPostProcessor implementations to
+ process any callback interfaces it can find and call the appropriate
+ methods. If you need custom features or other lifecycle behavior Spring
+ doesn't offer out-of-the-box, you can implement a
+ BeanPostProcessor yourself. More
+ information about this can be found in the section entitled .
+
+ All the different lifecycle callback interfaces are described below.
+ In one of the appendices, you can find diagrams that show how Spring
+ manages beans, how those lifecycle features change the nature of your
+ beans, and how they are managed.
+
+
+ Initialization callbacks
+
+ Implementing the
+ org.springframework.beans.factory.InitializingBean
+ interface allows a bean to perform initialization work after all
+ necessary properties on the bean have been set by the container. The
+ InitializingBean interface specifies
+ exactly one method:
+
+ void afterPropertiesSet() throws Exception;
+
+ Generally, the use of the
+ InitializingBean interface can be
+ avoided and is actually discouraged since it unnecessarily couples the
+ code to Spring. As an alternative, bean definitions provide support
+ for a generic initialization method to be specified. In the case of
+ XML-based configuration metadata, this is done using the
+ 'init-method' attribute. For example, the following
+ definition:
+
+ <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
+
+ public class ExampleBean {
+
+ public void init() {
+ // do some initialization work
+ }
+}
+
+ ...is exactly the same as...
+
+ <bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
+
+ public class AnotherExampleBean implements InitializingBean {
+
+ public void afterPropertiesSet() {
+ // do some initialization work
+ }
+}
+
+ ... but does not couple the code to Spring.
+
+
+
+ Destruction callbacks
+
+ Implementing the
+ org.springframework.beans.factory.DisposableBean
+ interface allows a bean to get a callback when the container
+ containing it is destroyed. The
+ DisposableBean interface specifies a
+ single method:
+
+ void destroy() throws Exception;
+
+ Generally, the use of the
+ DisposableBean callback interface can be
+ avoided and is actually discouraged since it unnecessarily couples the
+ code to Spring. As an alternative, bean definitions provide support
+ for a generic destroy method to be specified. When using XML-based
+ configuration metadata this is done via the
+ 'destroy-method' attribute on the
+ <bean/>. For example, the following
+ definition:
+
+ <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
+
+ public class ExampleBean {
+
+ public void cleanup() {
+ // do some destruction work (like releasing pooled connections)
+ }
+}
+
+ ...is exactly the same as...
+
+ <bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
+
+ public class AnotherExampleBean implements DisposableBean {
+
+ public void destroy() {
+ // do some destruction work (like releasing pooled connections)
+ }
+}
+
+ ... but does not couple the code to Spring.
+
+
+
+ Default initialization & destroy methods
+
+ When writing initialization and destroy method callbacks that do
+ not use the Spring-specific
+ InitializingBean and
+ DisposableBean callback interfaces, one
+ typically finds oneself writing methods with names such as
+ init(), initialize(),
+ dispose(), etc. The names of such lifecycle
+ callback methods are (hopefully!) standardized across a project so
+ that all developers on a team use the same method names and thus
+ ensure some level of consistency.
+
+ The Spring container can be configured to
+ 'look' for named initialization and destroy
+ callback method names on every bean. This means
+ that you, as an application developer, can simply write your
+ application classes, use a convention of having an initialization
+ callback called init(), and then (without having to
+ configure each and every bean with, in the case of XML-based
+ configuration, an 'init-method="init"' attribute)
+ be safe in the knowledge that the Spring IoC container
+ will call that method when the bean is being
+ created (and in accordance with the standard lifecycle callback
+ contract described previously).
+
+ Let's look at an example to make the use of this feature
+ completely clear. For the sake of the example, let us say that one of
+ the coding conventions on a project is that all initialization
+ callback methods are to be named init() and that
+ destroy callback methods are to be called
+ destroy(). This leads to classes like so...
+
+ public class DefaultBlogService implements BlogService {
+
+ private BlogDao blogDao;
+
+ public void setBlogDao(BlogDao blogDao) {
+ this.blogDao = blogDao;
+ }
+
+ // this is (unsurprisingly) the initialization callback method
+ public void init() {
+ if (this.blogDao == null) {
+ throw new IllegalStateException("The [blogDao] property must be set.");
+ }
+ }
+}
+
+ <beans default-init-method="init">
+
+ <bean id="blogService" class="com.foo.DefaultBlogService">
+ <property name="blogDao" ref="blogDao" />
+ </bean>
+
+</beans>
+
+ Notice the use of the 'default-init-method'
+ attribute on the top-level <beans/> element.
+ The presence of this attribute means that the Spring IoC container
+ will recognize a method called 'init' on beans as
+ being the initialization method callback, and when a bean is being
+ created and assembled, if the bean's class has such a method, it will
+ be invoked at the appropriate time.
+
+ Destroy method callbacks are configured similarly (in XML that
+ is) using the 'default-destroy-method' attribute on
+ the top-level <beans/> element.
+
+ The use of this feature can save you the (small) housekeeping
+ chore of specifying an initialization and destroy method callback on
+ each and every bean, and it is great for enforcing a consistent naming
+ convention for initialization and destroy method callbacks, as
+ consistency is something that should always be aimed for.
+
+ Consider the case where you have some existing beans where the
+ underlying classes already have initialization callback methods that
+ are named at variance with the convention. You can
+ always override the default by specifying (in XML
+ that is) the method name using the 'init-method'
+ and 'destroy-method' attributes on the
+ <bean/> element itself.
+
+ Finally, please be aware that the Spring container guarantees
+ that a configured initialization callback is called immediately after
+ a bean has been supplied with all of its dependencies. This means that
+ the initialization callback will be called on the raw bean reference,
+ which means that any AOP interceptors or suchlike that will ultimately
+ be applied to the bean will not yet be in place. A target bean is
+ fully created first, then an
+ AOP proxy (for example) with its interceptor chain is applied. Note
+ that, if the target bean and the proxy are defined separately, your
+ code can even interact with the raw target bean, bypassing the proxy.
+ Hence, it would be very inconsistent to apply the interceptors to the
+ init method, since that would couple the lifecycle of the target bean
+ with its proxy/interceptors and leave strange semantics when talking
+ to the raw target bean directly.
+
+
+
+ Combining lifecycle mechanisms
+
+ As of Spring 2.5, there are three options for controlling bean
+ lifecycle behavior: the InitializingBean
+ and DisposableBean
+ callback interfaces; custom init() and
+ destroy() methods; and the @PostConstruct
+ and @PreDestroy
+ annotations.
+
+ When combining different lifecycle mechanisms - for example, in
+ a class hierarchy in which various lifecycle mechanisms are in use -
+ developers should be aware of the order in which these mechanisms are
+ applied. The following is the ordering for initialization
+ methods:
+
+
+
+ Methods annotated with
+ @PostConstruct
+
+
+
+ afterPropertiesSet() as defined by the
+ InitializingBean callback
+ interface
+
+
+
+ A custom configured init() method
+
+
+
+ Destroy methods are called in the same order:
+
+
+
+ Methods annotated with
+ @PreDestroy
+
+
+
+ destroy() as defined by the
+ DisposableBean callback
+ interface
+
+
+
+ A custom configured destroy()
+ method
+
+
+
+
+ If multiple lifecycle mechanisms are configured for a given
+ bean, and each mechanism is configured with a different method name,
+ then each configured method will be executed in the order listed
+ above; however, if the same method name is configured - for example,
+ init() for an initialization method - for more
+ than one of the aforementioned lifecycle mechanisms, that method
+ will only be executed once.
+
+
+
+
+ Shutting down the Spring IoC container gracefully in non-web
+ applications
+
+
+ This next section does not apply to web applications (in case
+ the title of this section did not make that abundantly clear).
+ Spring's web-based ApplicationContext
+ implementations already have code in place to handle shutting down
+ the Spring IoC container gracefully when the relevant web
+ application is being shutdown.
+
+
+ If you are using Spring's IoC container in a non-web application
+ environment, for example in a rich client desktop environment, and you
+ want the container to shutdown gracefully and call the relevant
+ destroy callbacks on your singleton beans, you will need to register a
+ shutdown hook with the JVM. This is quite easy to do (see below), and
+ will ensure that your Spring IoC container shuts down gracefully and
+ that all resources held by your singletons are released. Of course it
+ is still up to you to both configure the destroy callbacks for your
+ singletons and implement such destroy callbacks correctly.
+
+ So to register a shutdown hook that enables the graceful
+ shutdown of the relevant Spring IoC container, you simply need to call
+ the registerShutdownHook() method that is
+ declared on the AbstractApplicationContext
+ class. To wit...
+
+ 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"});
+
+ // add a shutdown hook for the above context...
+ ctx.registerShutdownHook();
+
+ // app runs here...
+
+ // main method exits, hook is called prior to the app shutting down...
+ }
+}
+
+
+
+
+ Knowing who you are
+
+
+ BeanFactoryAware
+
+ A class which implements the
+ org.springframework.beans.factory.BeanFactoryAware
+ interface is provided with a reference to the
+ BeanFactory that created it, when it is
+ created by that BeanFactory.
+
+ public interface BeanFactoryAware {
+
+ void setBeanFactory(BeanFactory beanFactory) throws BeansException;
+}
+
+ This allows beans to manipulate the
+ BeanFactory that created them
+ programmatically, through the
+ BeanFactory interface, or by casting
+ the reference to a known subclass of this which exposes additional
+ functionality. Primarily this would consist of programmatic retrieval
+ of other beans. While there are cases when this capability is useful,
+ it should generally be avoided, since it couples the code to Spring
+ and does not follow the Inversion of Control style, where
+ collaborators are provided to beans as properties.
+
+ An alternative option that is equivalent in effect to the
+ BeanFactoryAware-based approach is to
+ use the
+ org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean.
+ (It should be noted that this approach still does not reduce the
+ coupling to Spring, but it does not violate the central principle of
+ IoC as much as the
+ BeanFactoryAware-based
+ approach.)
+
+ The ObjectFactoryCreatingFactoryBean is a
+ FactoryBean
+ implementation that returns a reference to an object (factory) that
+ can in turn be used to effect a bean lookup. The
+ ObjectFactoryCreatingFactoryBean class does
+ itself implement the BeanFactoryAware
+ interface; what client beans are actually injected with is an instance
+ of the ObjectFactory interface. This is
+ a Spring-specific interface (and hence there is still no total
+ decoupling from Spring), but clients can then use the
+ ObjectFactory's
+ getObject() method to effect the bean lookup
+ (under the hood the ObjectFactory
+ implementation instance that is returned simply delegates down to a
+ BeanFactory to actually lookup a bean
+ by name). All that you need to do is supply the
+ ObjectFactoryCreatingFactoryBean with the name
+ of the bean that is to be looked up. Let's look at an example:
+
+ package x.y;
+
+public class NewsFeed {
+
+ private String news;
+
+ public void setNews(String news) {
+ this.news = news;
+ }
+
+ public String getNews() {
+ return this.toString() + ": '" + news + "'";
+ }
+}
+
+ package x.y;
+
+import org.springframework.beans.factory.ObjectFactory;
+
+public class NewsFeedManager {
+
+ private ObjectFactory factory;
+
+ public void setFactory(ObjectFactory factory) {
+ this.factory = factory;
+ }
+
+ public void printNews() {
+ // here is where the lookup is performed; note that there is no
+ // need to hard code the name of the bean that is being looked up...
+ NewsFeed news = (NewsFeed) factory.getObject();
+ System.out.println(news.getNews());
+ }
+}
+
+ Find below the XML configuration to wire together the above
+ classes using the
+ ObjectFactoryCreatingFactoryBean
+ approach.
+
+ <beans>
+ <bean id="newsFeedManager" class="x.y.NewsFeedManager">
+ <property name="factory">
+ <bean
+class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
+ <property name="targetBeanName">
+ <idref local="newsFeed" />
+ </property>
+ </bean>
+ </property>
+ </bean>
+ <bean id="newsFeed" class="x.y.NewsFeed" scope="prototype">
+ <property name="news" value="... that's fit to print!" />
+ </bean>
+</beans>
+
+ And here is a small driver program to test the fact that new
+ (prototype) instances of the newsFeed bean are
+ actually being returned for each call to the injected
+ ObjectFactory inside the
+ NewsFeedManager's
+ printNews() method.
+
+ import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import x.y.NewsFeedManager;
+
+public class Main {
+
+ public static void main(String[] args) throws Exception {
+
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
+ NewsFeedManager manager = (NewsFeedManager) ctx.getBean("newsFeedManager");
+ manager.printNews();
+ manager.printNews();
+ }
+}
+
+ The output from running the above program will look like so
+ (results will of course vary on your machine).
+
+ x.y.NewsFeed@1292d26: '... that's fit to print!'
+x.y.NewsFeed@5329c5: '... that's fit to print!'
+
+ As of Spring 2.5, you can rely upon autowiring of the
+ BeanFactory as yet another alternative
+ to implementing the BeanFactoryAware
+ interface. The "traditional" constructor and
+ byType autowiring modes (as described in the
+ section entitled ) are now
+ capable of providing a dependency of type
+ BeanFactory 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 BeanFactory will be
+ autowired into a field, constructor argument, or method parameter that
+ is expecting the BeanFactory type as
+ long as the field, constructor, or method in question carries the
+ @Autowired annotation. For more
+ information, see the section entitled .
+
+
+
+ BeanNameAware
+
+ If a bean implements the
+ org.springframework.beans.factory.BeanNameAware
+ interface and is deployed in a
+ BeanFactory, the
+ BeanFactory will call the bean through
+ this interface to inform the bean of the name it
+ was deployed under. The callback will be invoked after population of
+ normal bean properties but before an initialization callback like
+ InitializingBean's
+ afterPropertiesSet or a custom
+ init-method.
+
+
+
+
+
+ Bean definition inheritance
+
+ A bean definition potentially contains a large amount of
+ configuration information, including container specific information (for
+ example initialization method, static factory method name, and so forth)
+ and constructor arguments and property values. A child bean definition is
+ a bean definition that inherits configuration data from a parent
+ definition. It is then able to override some values, or add others, as
+ needed. Using parent and child bean definitions can potentially save a lot
+ of typing. Effectively, this is a form of templating.
+
+ When working with a BeanFactory
+ programmatically, child bean definitions are represented by the
+ ChildBeanDefinition class. Most users will never
+ work with them on this level, instead configuring bean definitions
+ declaratively in something like the XmlBeanFactory.
+ When using XML-based configuration metadata a child bean definition is
+ indicated simply by using the 'parent' attribute,
+ specifying the parent bean as the value of this attribute.
+
+ <bean id="inheritedTestBean" abstract="true"
+ class="org.springframework.beans.TestBean">
+ <property name="name" value="parent"/>
+ <property name="age" value="1"/>
+</bean>
+
+<bean id="inheritsWithDifferentClass"
+ class="org.springframework.beans.DerivedTestBean"
+ parent="inheritedTestBean" init-method="initialize">
+
+ <property name="name" value="override"/>
+ <!-- the age property value of 1 will be inherited from parent -->
+
+</bean>
+
+ A child bean definition will use the bean class from the parent
+ definition if none is specified, but can also override it. In the latter
+ case, the child bean class must be compatible with the parent, that is it
+ must accept the parent's property values.
+
+ A child bean definition will inherit constructor argument values,
+ property values and method overrides from the parent, with the option to
+ add new values. If any init-method, destroy-method and/or
+ static factory method settings are specified, they will
+ override the corresponding parent settings.
+
+ The remaining settings will always be taken
+ from the child definition: depends on,
+ autowire mode, dependency check,
+ singleton, scope, lazy
+ init.
+
+ Note that in the example above, we have explicitly marked the parent
+ bean definition as abstract by using the abstract
+ attribute. In the case that the parent definition does not specify a
+ class, and so explicitly marking the parent bean definition as
+ abstract is required:
+
+ <bean id="inheritedTestBeanWithoutClass" abstract="true">
+ <property name="name" value="parent"/>
+ <property name="age" value="1"/>
+</bean>
+
+<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
+ parent="inheritedTestBeanWithoutClass" init-method="initialize">
+ <property name="name" value="override"/>
+ <!-- age will inherit the value of 1 from the parent bean definition-->
+</bean>
+
+ The parent bean cannot get instantiated on its own since it is
+ incomplete, and it is also explicitly marked as
+ abstract. When a definition is defined to be
+ abstract like this, it is usable only as a pure
+ template bean definition that will serve as a parent definition for child
+ definitions. Trying to use such an abstract parent bean
+ on its own (by referring to it as a ref property of another bean, or doing
+ an explicit getBean() call with the parent bean
+ id), will result in an error. Similarly, the container's internal
+ preInstantiateSingletons() method will completely
+ ignore bean definitions which are defined as abstract.
+
+
+ ApplicationContexts (but
+ notBeanFactories) will by
+ default pre-instantiate all singletons. Therefore it is important (at
+ least for singleton beans) that if you have a (parent) bean definition
+ which you intend to use only as a template, and this definition
+ specifies a class, you must make sure to set the
+ 'abstract' attribute to
+ 'true', otherwise the application context will
+ actually (attempt to) pre-instantiate the abstract
+ bean.
+
+
+
+
+ Container extension points
+
+ The IoC component of the Spring Framework has been designed for
+ extension. There is typically no need for an application developer to
+ subclass any of the various BeanFactory or
+ ApplicationContext implementation classes.
+ The Spring IoC container can be infinitely extended by plugging in
+ implementations of special integration interfaces. The next few sections
+ are devoted to detailing all of these various integration
+ interfaces.
+
+
+ Customizing beans using
+ BeanPostProcessors
+
+ The first extension point that we will look at is the
+ BeanPostProcessor interface. This
+ interface defines a number of callback methods
+ that you as an application developer can implement in order to provide
+ your own (or override the containers default) instantiation logic,
+ dependency-resolution logic, and so forth. If you want to do some custom
+ logic after the Spring container has finished instantiating, configuring
+ and otherwise initializing a bean, you can plug in one or more
+ BeanPostProcessor implementations.
+
+ You can configure multiple BeanPostProcessors
+ if you wish. You can control the order in which these
+ BeanPostProcessors execute by setting the
+ 'order' property (you can only set this property if
+ the BeanPostProcessor implements the
+ Ordered interface; if you write your own
+ BeanPostProcessor you should consider
+ implementing the Ordered interface too);
+ consult the Javadoc for the
+ BeanPostProcessor and
+ Ordered interfaces for more
+ details.
+
+
+ BeanPostProcessors operate on bean (or
+ object) instances; that is to say, the Spring IoC
+ container will have instantiated a bean instance for you, and
+ thenBeanPostProcessors get a
+ chance to do their stuff.
+
+ If you want to change the actual bean definition (that is the
+ recipe that defines the bean), then you rather need to use a
+ BeanFactoryPostProcessor (described
+ below in the section entitled .
+
+ Also, BeanPostProcessors are scoped
+ per-container. This is only relevant if you are
+ using container hierarchies. If you define a
+ BeanPostProcessor in one container, it
+ will only do its stuff on the beans in that
+ container. Beans that are defined in another container will not be
+ post-processed by BeanPostProcessors in another
+ container, even if both containers are part of the same
+ hierarchy.
+
+
+ The
+ org.springframework.beans.factory.config.BeanPostProcessor
+ interface consists of exactly two callback methods. When such a class is
+ registered as a post-processor with the container (see below for how
+ this registration is effected), for each bean instance that is created
+ by the container, the post-processor will get a callback from the
+ container both before any container initialization
+ methods (such as afterPropertiesSet and any
+ declared init method) are called, and also afterwards. The
+ post-processor is free to do what it wishes with the bean instance,
+ including ignoring the callback completely. A bean post-processor will
+ typically check for callback interfaces, or do something such as wrap a
+ bean with a proxy; some of the Spring AOP infrastructure classes are
+ implemented as bean post-processors and they do this proxy-wrapping
+ logic.
+
+ It is important to know that a
+ BeanFactory treats bean post-processors
+ slightly differently than an
+ ApplicationContext. An
+ ApplicationContext will
+ automatically detect any beans which are defined in
+ the configuration metadata which is supplied to it that implement the
+ BeanPostProcessor interface, and register
+ them as post-processors, to be then called appropriately by the
+ container on bean creation. Nothing else needs to be done other than
+ deploying the post-processors in a similar fashion to any other bean. On
+ the other hand, when using a BeanFactory
+ implementation, bean post-processors explicitly have to be registered,
+ with code like this:
+
+ ConfigurableBeanFactory factory = new XmlBeanFactory(...);
+
+// now register any needed BeanPostProcessor instances
+MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
+factory.addBeanPostProcessor(postProcessor);
+
+// now start using the factory
+
+ This explicit registration step is not convenient, and this is one
+ of the reasons why the various
+ ApplicationContext implementations are
+ preferred above plain BeanFactory
+ implementations in the vast majority of Spring-backed applications,
+ especially when using BeanPostProcessors.
+
+
+ BeanPostProcessors and AOP
+ auto-proxying
+
+ Classes that implement the
+ BeanPostProcessor interface are
+ special, and so they are treated differently by
+ the container. All BeanPostProcessors
+ and their directly referenced beans will be
+ instantiated on startup, as part of the special startup phase of the
+ ApplicationContext,
+ then all those
+ BeanPostProcessors will be registered
+ in a sorted fashion - and applied to all further beans. Since AOP
+ auto-proxying is implemented as a
+ BeanPostProcessor itself, no
+ BeanPostProcessors or directly
+ referenced beans are eligible for auto-proxying (and thus will not
+ have aspects 'woven' into them.
+
+ For any such bean, you should see an info log message:
+ Bean 'foo' is not eligible for getting processed by
+ all BeanPostProcessors (for example: not eligible for
+ auto-proxying).
+
+
+ Find below some examples of how to write, register, and use
+ BeanPostProcessors in the context of an
+ ApplicationContext.
+
+
+ Example: Hello World,
+ BeanPostProcessor-style
+
+ This first example is hardly compelling, but serves to
+ illustrate basic usage. All we are going to do is code a custom
+ BeanPostProcessor implementation that
+ simply invokes the toString() method of each
+ bean as it is created by the container and prints the resulting string
+ to the system console. Yes, it is not hugely useful, but serves to get
+ the basic concepts across before we move into the second example which
+ is actually useful.
+
+ Find below the custom
+ BeanPostProcessor implementation class
+ definition:
+
+ package scripting;
+
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.BeansException;
+
+public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
+
+ // simply return the instantiated bean as-is
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean; // we could potentially return any object reference here...
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ System.out.println("Bean '" + beanName + "' created : " + bean.toString());
+ return bean;
+ }
+}
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:lang="http://www.springframework.org/schema/lang"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
+
+ <lang:groovy id="messenger"
+ script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
+ <lang:property name="message" value="Fiona Apple Is Just So Dreamy."/>
+ </lang:groovy>
+
+ <!--
+ when the above bean ('messenger') is instantiated, this custom
+ BeanPostProcessor implementation will output the fact to the system console
+ -->
+ <bean class="scripting.InstantiationTracingBeanPostProcessor"/>
+
+</beans>
+
+ Notice how the
+ InstantiationTracingBeanPostProcessor is simply
+ defined; it doesn't even have a name, and because it is a bean it can
+ be dependency injected just like any other bean. (The above
+ configuration also just so happens to define a bean that is backed by
+ a Groovy script. The Spring 2.0 dynamic language support is detailed
+ in the chapter entitled .)
+
+ Find below a small driver script to exercise the above code and
+ configuration;
+
+ 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);
+ }
+}
+
+ The output of executing the above program will be (something
+ like) this:
+
+ Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961
+org.springframework.scripting.groovy.GroovyMessenger@272961
+
+
+
+ Example: The
+ RequiredAnnotationBeanPostProcessor
+
+ Using callback interfaces or annotations in conjunction with a
+ custom BeanPostProcessor implementation
+ is a common means of extending the Spring IoC container. This next
+ example is a bit of a cop-out, in that you are directed to the section
+ entitled which
+ demonstrates the usage of a custom
+ BeanPostProcessor 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.
+
+
+
+
+ Customizing configuration metadata with
+ BeanFactoryPostProcessors
+
+ The next extension point that we will look at is the
+ org.springframework.beans.factory.config.BeanFactoryPostProcessor.
+ The semantics of this interface are similar to the
+ BeanPostProcessor, with one major
+ difference: BeanFactoryPostProcessors operate on the bean
+ configuration metadata; that is, the Spring IoC container will allow
+ BeanFactoryPostProcessors to read the configuration
+ metadata and potentially change it before the
+ container has actually instantiated any other beans.
+
+ You can configure multiple
+ BeanFactoryPostProcessors if you wish. You can
+ control the order in which these
+ BeanFactoryPostProcessors execute by setting the
+ 'order' property (you can only set this property if
+ the BeanFactoryPostProcessor implements
+ the Ordered interface; if you write your
+ own BeanFactoryPostProcessor you should
+ consider implementing the Ordered
+ interface too); consult the Javadoc for the
+ BeanFactoryPostProcessor and
+ Ordered interfaces for more
+ details.
+
+
+ If you want to change the actual bean
+ instances (the objects that are created from the
+ configuration metadata), then you rather need to use a
+ BeanPostProcessor (described above in
+ the section entitled .
+
+ Also, BeanFactoryPostProcessors are scoped
+ per-container. This is only relevant if you are
+ using container hierarchies. If you define a
+ BeanFactoryPostProcessor in one
+ container, it will only do its stuff on the bean
+ definitions in that container. Bean definitions in another container
+ will not be post-processed by
+ BeanFactoryPostProcessors in another container,
+ even if both containers are part of the same hierarchy.
+
+
+ A bean factory post-processor is executed manually (in the case of
+ a BeanFactory) or automatically (in the
+ case of an ApplicationContext) to apply
+ changes of some sort to the configuration metadata that defines a
+ container. Spring includes a number of pre-existing bean factory
+ post-processors, such as PropertyOverrideConfigurer
+ and PropertyPlaceholderConfigurer, both described
+ below. A custom BeanFactoryPostProcessor
+ can also be used to register custom property editors, for example.
+
+ In a BeanFactory, the process of
+ applying a BeanFactoryPostProcessor is
+ manual, and will be similar to this:
+
+ XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
+
+// bring in some property values from a Properties file
+PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
+cfg.setLocation(new FileSystemResource("jdbc.properties"));
+
+// now actually do the replacement
+cfg.postProcessBeanFactory(factory);
+
+ This explicit registration step is not convenient, and this is one
+ of the reasons why the various
+ ApplicationContext implementations are
+ preferred above plain BeanFactory
+ implementations in the vast majority of Spring-backed applications,
+ especially when using
+ BeanFactoryPostProcessors.
+
+
+
+ An ApplicationContext will detect
+ any beans which are deployed into it which implement the
+ BeanFactoryPostProcessor interface, and
+ automatically use them as bean factory post-processors, at the
+ appropriate time. Nothing else needs to be done other than deploying
+ these post-processor in a similar fashion to any other bean.
+
+
+ Just as in the case of BeanPostProcessors,
+ you typically don't want to have
+ BeanFactoryPostProcessors marked as being
+ lazily-initialized. If they are marked as such, then the Spring
+ container will never instantiate them, and thus they won't get a
+ chance to apply their custom logic. If you are using the
+ 'default-lazy-init' attribute on the declaration of
+ your <beans/> element, be sure to mark your
+ various BeanFactoryPostProcessor bean
+ definitions with 'lazy-init="false"'.
+
+
+
+ Example: the
+ PropertyPlaceholderConfigurer
+
+ The PropertyPlaceholderConfigurer
+ is used to externalize property values from a
+ BeanFactory definition, into another
+ separate file in the standard Java Properties
+ format. This is useful to allow the person deploying an application to
+ customize environment-specific properties (for example database URLs,
+ usernames and passwords), without the complexity or risk of modifying
+ the main XML definition file or files for the container.
+
+ Consider the following XML-based configuration metadata
+ fragment, where a DataSource with
+ placeholder values is defined. We will configure some properties from
+ an external Properties file, and at runtime, we
+ will apply a PropertyPlaceholderConfigurer to
+ the metadata which will replace some properties of the
+ DataSource:
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="locations">
+ <value>classpath:com/foo/jdbc.properties</value>
+ </property>
+</bean>
+
+<bean id="dataSource" destroy-method="close"
+ class="org.apache.commons.dbcp.BasicDataSource">
+ <property name="driverClassName" value="${jdbc.driverClassName}"/>
+ <property name="url" value="${jdbc.url}"/>
+ <property name="username" value="${jdbc.username}"/>
+ <property name="password" value="${jdbc.password}"/>
+</bean>
+
+ The actual values come from another file in the standard Java
+ Properties format:
+
+ jdbc.driverClassName=org.hsqldb.jdbcDriver
+jdbc.url=jdbc:hsqldb:hsql://production:9002
+jdbc.username=sa
+jdbc.password=root
+
+ With the context namespace introduced in
+ Spring 2.5, it is possible to configure property placeholders with a
+ dedicated configuration element. Multiple locations may be provided as a
+ comma-separated list for the location attribute.
+
+ <context:property-placeholder location="classpath:com/foo/jdbc.properties"/>
+
+ The PropertyPlaceholderConfigurer doesn't
+ only look for properties in the Properties file
+ you specify, but also checks against the Java
+ System properties if it cannot find a property
+ you are trying to use. This behavior can be customized by setting the
+ systemPropertiesMode property of the configurer. It
+ has three values, one to tell the configurer to always override, one
+ to let it never override and one to let it
+ override only if the property cannot be found in the properties file
+ specified. Please consult the Javadoc for the
+ PropertyPlaceholderConfigurer for more
+ information.
+
+
+ Class name substitution
+
+ The PropertyPlaceholderConfigurer can
+ be used to substitute class names, which is sometimes useful when
+ you have to pick a particular implementation class at runtime. For
+ example:
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="locations">
+ <value>classpath:com/foo/strategy.properties</value>
+ </property>
+ <property name="properties">
+ <value>custom.strategy.class=com.foo.DefaultStrategy</value>
+ </property>
+</bean>
+
+<bean id="serviceStrategy" class="${custom.strategy.class}"/>
+
+ If the class is unable to be resolved at runtime to a valid
+ class, resolution of the bean will fail once it is about to be
+ created (which is during the
+ preInstantiateSingletons() phase of an
+ ApplicationContext for a
+ non-lazy-init bean.)
+
+
+
+
+ Example: the
+ PropertyOverrideConfigurer
+
+ The PropertyOverrideConfigurer, another
+ bean factory post-processor, is similar to the
+ PropertyPlaceholderConfigurer, but in
+ contrast to the latter, the original definitions can have default
+ values or no values at all for bean properties. If an overriding
+ Properties file does not have an entry for a
+ certain bean property, the default context definition is used.
+
+ Note that the bean factory definition is
+ not aware of being overridden, so it is not
+ immediately obvious when looking at the XML definition file that the
+ override configurer is being used. In case that there are multiple
+ PropertyOverrideConfigurer instances that
+ define different values for the same bean property, the last one will
+ win (due to the overriding mechanism).
+
+ Properties file configuration lines are expected to be in the
+ format:
+
+ beanName.property=value
+
+ An example properties file might look like this:
+
+ dataSource.driverClassName=com.mysql.jdbc.Driver
+dataSource.url=jdbc:mysql:mydb
+
+ This example file would be usable against a container definition
+ which contains a bean called dataSource, which
+ has driver and url
+ properties.
+
+ Note that compound property names are also supported, as long as
+ every component of the path except the final property being overridden
+ is already non-null (presumably initialized by the constructors). In
+ this example...
+
+ foo.fred.bob.sammy=123
+
+ ... the sammy property of the
+ bob property of the fred
+ property of the foo bean is being set to the scalar
+ value 123.
+
+ Note: Specified override values are always
+ literal values; they are not translated into bean
+ references. This also applies when the original value in the XML bean
+ definition specifies a bean reference
+
+ With the context namespace introduced in
+ Spring 2.5, it is possible to configure property overriding with a
+ dedicated configuration element:
+
+ <context:property-override location="classpath:override.properties"/>
+
+
+
+
+
+ Customizing instantiation logic using
+ FactoryBeans
+
+ The
+ org.springframework.beans.factory.FactoryBean
+ interface is to be implemented by objects that are themselves
+ factories.
+
+ The FactoryBean interface is a
+ point of pluggability into the Spring IoC containers instantiation
+ logic. If you have some complex initialization code that is better
+ expressed in Java as opposed to a (potentially) verbose amount of XML,
+ you can create your own FactoryBean,
+ write the complex initialization inside that class, and then plug your
+ custom FactoryBean into the
+ container.
+
+ The FactoryBean interface provides
+ three methods:
+
+
+
+ Object getObject(): has to return an
+ instance of the object this factory creates. The instance can
+ possibly be shared (depending on whether this factory returns
+ singletons or prototypes).
+
+
+
+ boolean isSingleton(): has to return
+ true if this
+ FactoryBean returns singletons,
+ false otherwise
+
+
+
+ Class getObjectType(): has to return
+ either the object type returned by the
+ getObject() method or
+ null if the type isn't known in advance
+
+
+
+ The FactoryBean concept and
+ interface is used in a number of places within the Spring Framework; at
+ the time of writing there are over 50 implementations of the
+ FactoryBean interface that ship with
+ Spring itself.
+
+ Finally, there is sometimes a need to ask a container for an
+ actual FactoryBean instance itself, not
+ the bean it produces. This may be achieved by prepending the bean id
+ with '&' (sans quotes) when calling the
+ getBean method of the
+ BeanFactory (including
+ ApplicationContext). So for a given
+ FactoryBean with an id of
+ myBean, invoking getBean("myBean")
+ on the container will return the product of the
+ FactoryBean, but invoking
+ getBean("&myBean") will return the
+ FactoryBean instance itself.
+
+
+
+
+ The ApplicationContext
+
+ While the beans package provides basic
+ functionality for managing and manipulating beans, including in a
+ programmatic way, the context package adds the ApplicationContext
+ interface, which enhances BeanFactory
+ functionality in a more framework-oriented style.
+ Many users will use ApplicationContext in a
+ completely declarative fashion, not even having to create it manually, but
+ instead relying on support classes such as
+ ContextLoader to automatically instantiate an
+ ApplicationContext as part of the normal
+ startup process of a J2EE web-app. (Of course, it is still possible to
+ create an ApplicationContext
+ programmatically.)
+
+ The basis for the context package is the
+ ApplicationContext interface, located in
+ the org.springframework.context package. Deriving from
+ the BeanFactory interface, it provides all
+ the functionality of BeanFactory. To allow
+ working in a more framework-oriented fashion, using layering and
+ hierarchical contexts, the context package also provides the following
+ functionality:
+
+
+
+ MessageSource, providing access
+ to messages in i18n-style.
+
+
+
+ Access to resources, such as URLs and
+ files.
+
+
+
+ Event propagation to beans implementing the
+ ApplicationListener interface.
+
+
+
+ Loading of multiple (hierarchical)
+ contexts, allowing each to be focused on one particular
+ layer, for example the web layer of an application.
+
+
+
+
+ BeanFactory or
+ ApplicationContext?
+
+ Short version: use an
+ ApplicationContext unless you have a
+ really good reason for not doing so. For those of you that are looking
+ for slightly more depth as to the 'but why' of the above recommendation,
+ keep reading.
+
+ As the ApplicationContext includes
+ all functionality of the BeanFactory, it
+ is generally recommended that it be used in preference to the
+ BeanFactory, except for a few limited
+ situations such as in an Applet, where memory
+ consumption might be critical and a few extra kilobytes might make a
+ difference. However, for most 'typical' enterprise applications and
+ systems, the ApplicationContext is what
+ you will want to use. Versions of Spring 2.0 and above make
+ heavy use of the BeanPostProcessor
+ extension point (to effect proxying and suchlike), and if you are
+ using just a plain BeanFactory then a
+ fair amount of support such as transactions and AOP will not take effect
+ (at least not without some extra steps on your part), which could be
+ confusing because nothing will actually be wrong with the
+ configuration.
+
+ Find below a feature matrix that lists what features are provided
+ by the BeanFactory and
+ ApplicationContext interfaces (and
+ attendant implementations). (The following sections describe
+ functionality that ApplicationContext
+ adds to the basic BeanFactory
+ capabilities in a lot more depth than the said feature matrix.)
+
+
+
+
+
+ Internationalization using
+ MessageSources
+
+ The ApplicationContext interface
+ extends an interface called
+ MessageSource, and therefore provides
+ messaging (i18n or internationalization) functionality. Together with
+ the HierarchicalMessageSource, capable of
+ resolving hierarchical messages, these are the basic interfaces Spring
+ provides to do message resolution. Let's quickly review the methods
+ defined there:
+
+
+
+ String getMessage(String code, Object[] args,
+ String default, Locale loc): the basic method used to
+ retrieve a message from the
+ MessageSource. When no message is
+ found for the specified locale, the default message is used. Any
+ arguments passed in are used as replacement values, using the
+ MessageFormat functionality provided
+ by the standard library.
+
+
+
+ String getMessage(String code, Object[] args,
+ Locale loc): essentially the same as the previous
+ method, but with one difference: no default message can be
+ specified; if the message cannot be found, a
+ NoSuchMessageException is thrown.
+
+
+
+ String getMessage(MessageSourceResolvable
+ resolvable, Locale locale): all properties used in the
+ methods above are also wrapped in a class named
+ MessageSourceResolvable, which you
+ can use via this method.
+
+
+
+ When an ApplicationContext gets
+ loaded, it automatically searches for a
+ MessageSource bean defined in the
+ context. The bean has to have the name
+ 'messageSource'. If such a bean is found, all calls
+ to the methods described above will be delegated to the message source
+ that was found. If no message source was found, the
+ ApplicationContext attempts to see if it
+ has a parent containing a bean with the same name. If so, it uses that
+ bean as the MessageSource. If it can't
+ find any source for messages, an empty
+ DelegatingMessageSource will be instantiated
+ in order to be able to accept calls to the methods defined above.
+
+ Spring currently provides two
+ MessageSource implementations. These are
+ the ResourceBundleMessageSource and the
+ StaticMessageSource. Both implement
+ HierarchicalMessageSource in order to do
+ nested messaging. The StaticMessageSource is
+ hardly ever used but provides programmatic ways to add messages to the
+ source. The ResourceBundleMessageSource is more
+ interesting and is the one we will provide an example for:
+
+ <beans>
+ <bean id="messageSource"
+ class="org.springframework.context.support.ResourceBundleMessageSource">
+ <property name="basenames">
+ <list>
+ <value>format</value>
+ <value>exceptions</value>
+ <value>windows</value>
+ </list>
+ </property>
+ </bean>
+</beans>
+
+ This assumes you have three resource bundles defined on your
+ classpath called format,
+ exceptions and windows. Using the
+ JDK standard way of resolving messages through ResourceBundles, any
+ request to resolve a message will be handled. For the purposes of the
+ example, lets assume the contents of two of the above resource bundle
+ files are...
+
+ # in 'format.properties'
+message=Alligators rock!
+
+ # in 'exceptions.properties'
+argument.required=The '{0}' argument is required.
+
+ Some (admittedly trivial) driver code to exercise the
+ MessageSource functionality can be found below.
+ Remember that all ApplicationContext
+ implementations are also MessageSource
+ implementations and so can be cast to the
+ MessageSource interface.
+
+ public static void main(String[] args) {
+ MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
+ String message = resources.getMessage("message", null, "Default", null);
+ System.out.println(message);
+}
+
+ The resulting output from the above program will be...
+
+ Alligators rock!
+
+ So to summarize, the MessageSource is
+ defined in a file called 'beans.xml' (this file
+ exists at the root of your classpath). The
+ 'messageSource' bean definition refers to a number of
+ resource bundles via its basenames property; the
+ three files that are passed in the list to the
+ basenames property exist as files at the root of your
+ classpath (and are called format.properties,
+ exceptions.properties, and
+ windows.properties respectively).
+
+ Lets look at another example, and this time we will look at
+ passing arguments to the message lookup; these arguments will be
+ converted into Strings and inserted into placeholders in the lookup
+ message. This is perhaps best explained with an example:
+
+ <beans>
+
+ <!-- this MessageSource is being used in a web application -->
+ <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
+ <property name="basename" value="test-messages"/>
+ </bean>
+
+ <!-- let's inject the above MessageSource into this POJO -->
+ <bean id="example" class="com.foo.Example">
+ <property name="messages" ref="messageSource"/>
+ </bean>
+
+</beans>
+
+ 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);
+ }
+
+}
+
+ The resulting output from the invocation of the
+ execute() method will be...
+
+ The 'userDao' argument is required.
+
+ With regard to internationalization (i18n), Spring's various
+ MessageResource implementations follow the same
+ locale resolution and fallback rules as the standard JDK
+ ResourceBundle. In short, and continuing with the
+ example 'messageSource' defined previously, if you
+ want to resolve messages against the British (en-GB) locale, you would
+ create files called format_en_GB.properties,
+ exceptions_en_GB.properties, and
+ windows_en_GB.properties respectively.
+
+ Locale resolution is typically going to be managed by the
+ surrounding environment of the application. For the purpose of this
+ example though, we'll just manually specify the locale that we want to
+ resolve our (British) messages against.
+
+ # in 'exceptions_en_GB.properties'
+argument.required=Ebagum lad, the '{0}' argument is required, I say, required.
+
+ 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);
+}
+
+ The resulting output from the running of the above program will
+ be...
+
+ Ebagum lad, the 'userDao' argument is required, I say, required.
+
+ The MessageSourceAware interface can also
+ be used to acquire a reference to any
+ MessageSource that has been defined. Any bean
+ that is defined in an ApplicationContext that
+ implements the MessageSourceAware interface will
+ be injected with the application context's
+ MessageSource when it (the bean) is being created
+ and configured.
+
+ Note: As an alternative to ResourceBundleMessageSource,
+ Spring also provides a ReloadableResourceBundleMessageSource class.
+ This variant supports the same bundle file format but is more flexible than the standard
+ JDK based ResourceBundleMessageSource implementation.
+ 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
+ ReloadableResourceBundleMessageSource javadoc for details.
+
+
+
+ Events
+
+ Event handling in the
+ ApplicationContext is provided through
+ the ApplicationEvent class and
+ ApplicationListener interface. If a bean
+ which implements the ApplicationListener
+ interface is deployed into the context, every time an
+ ApplicationEvent gets published to the
+ ApplicationContext, that bean will be
+ notified. Essentially, this is the standard
+ Observer design pattern. Spring provides the
+ following standard events:
+
+
+ Built-in Events
+
+
+
+
+
+
+
+ Event
+ Explanation
+
+
+
+
+
+ ContextRefreshedEvent
+ Published when the
+ ApplicationContext is initialized
+ or refreshed, e.g. using the refresh()
+ method on the
+ ConfigurableApplicationContext
+ interface. "Initialized" here means that all beans are loaded,
+ post-processor beans are detected and activated, singletons are
+ pre-instantiated, and the
+ ApplicationContext object is
+ ready for use. A refresh may be triggered multiple times,
+ as long as the context hasn't been closed - provided that
+ the chosen ApplicationContext
+ actually supports such "hot" refreshes (which e.g.
+ XmlWebApplicationContext does but
+ GenericApplicationContext doesn't).
+
+
+
+ ContextStartedEvent
+ Published when the
+ ApplicationContext is started,
+ using the start() method on the
+ ConfigurableApplicationContext
+ interface. "Started" here means that all
+ Lifecycle beans will receive
+ an explicit start signal. This will typically be used for
+ restarting after an explicit stop, but may also be used
+ for starting components that haven't been configured for
+ autostart (e.g. haven't started on initialization already).
+
+
+
+ ContextStoppedEvent
+ Published when the
+ ApplicationContext is stopped,
+ using the stop() method on the
+ ConfigurableApplicationContext
+ interface. "Stopped" here means that all
+ Lifecycle beans will receive
+ an explicit stop signal. A stopped context may be restarted
+ through a start() call.
+
+
+
+ ContextClosedEvent
+ Published when the
+ ApplicationContext is closed,
+ using the close() method on the
+ ConfigurableApplicationContext
+ interface. "Closed" here means that all singleton beans
+ are destroyed. A closed context has reached its end of life;
+ it cannot be refreshed or restarted.
+
+
+
+ RequestHandledEvent
+ A web-specific event telling all beans that an
+ HTTP request has been serviced (this will be published
+ after the request has been finished).
+ Note that this event is only applicable for web applications
+ using Spring's
+ DispatcherServlet.
+
+
+
+
+
+ Implementing custom events can be done as well. Simply call the
+ publishEvent() method on the
+ ApplicationContext, specifying a
+ parameter which is an instance of your custom event class implementing
+ ApplicationEvent. Event listeners receive events
+ synchronously. This means the publishEvent()
+ method blocks until all listeners have finished processing the event (it
+ is possible to supply an alternate event publishing strategy via a
+ ApplicationEventMulticaster
+ implementation). Furthermore, when a listener receives an event it
+ operates inside the transaction context of the publisher, if a
+ transaction context is available.
+
+ Let's look at an example. First, the
+ ApplicationContext:
+
+ <bean id="emailer" class="example.EmailBean">
+ <property name="blackList">
+ <list>
+ <value>black@list.org</value>
+ <value>white@list.org</value>
+ <value>john@doe.org</value>
+ </list>
+ </property>
+</bean>
+
+<bean id="blackListListener" class="example.BlackListNotifier">
+ <property name="notificationAddress" value="spam@list.org"/>
+</bean>
+
+ Now, let's look at the actual classes:
+
+ public class EmailBean implements ApplicationContextAware {
+
+ private List blackList;
+ private ApplicationContext ctx;
+
+ public void setBlackList(List blackList) {
+ this.blackList = blackList;
+ }
+
+ public void setApplicationContext(ApplicationContext ctx) {
+ this.ctx = ctx;
+ }
+
+ public void sendEmail(String address, String text) {
+ if (blackList.contains(address)) {
+ BlackListEvent event = new BlackListEvent(address, text);
+ ctx.publishEvent(event);
+ return;
+ }
+ // send email...
+ }
+}
+
+ public class BlackListNotifier implements ApplicationListener {
+
+ private String notificationAddress;
+
+ public void setNotificationAddress(String notificationAddress) {
+ this.notificationAddress = notificationAddress;
+ }
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof BlackListEvent) {
+ // notify appropriate person...
+ }
+ }
+}
+
+ Of course, this particular example could probably be implemented
+ in better ways (perhaps by using AOP features), but it should be
+ sufficient to illustrate the basic event mechanism.
+
+
+
+ Convenient access to low-level resources
+
+ For optimal usage and understanding of application contexts, users
+ should generally familiarize themselves with Spring's
+ Resource abstraction, as described in the
+ chapter entitled .
+
+ An application context is a
+ ResourceLoader, able to be used to load
+ Resources. A
+ Resource is essentially a
+ java.net.URL on steroids (in fact, it just wraps and
+ uses a URL where appropriate), which can be used to obtain low-level
+ resources from almost any location in a transparent fashion, including
+ from the classpath, a filesystem location, anywhere describable with a
+ standard URL, and some other variations. If the resource location string
+ is a simple path without any special prefixes, where those resources
+ come from is specific and appropriate to the actual application context
+ type.
+
+ A bean deployed into the application context may implement the
+ special callback interface,
+ ResourceLoaderAware, to be automatically
+ called back at initialization time with the application context itself
+ passed in as the ResourceLoader. A bean
+ may also expose properties of type
+ Resource, to be used to access static
+ resources, and expect that they will be injected into it like any other
+ properties. The person deploying the bean may specify those
+ Resource properties as simple String
+ paths, and rely on a special JavaBean
+ PropertyEditor that is automatically
+ registered by the context, to convert those text strings to actual
+ Resource objects.
+
+ The location path or paths supplied to an
+ ApplicationContext constructor are
+ actually resource strings, and in simple form are treated appropriately
+ to the specific context implementation (
+ ClassPathXmlApplicationContext treats a simple
+ location path as a classpath location), but may also be used with
+ special prefixes to force loading of definitions from the classpath or a
+ URL, regardless of the actual context type.
+
+
+
+ Convenient ApplicationContext
+ instantiation for web applications
+
+ As opposed to the BeanFactory,
+ which will often be created programmatically,
+ ApplicationContext instances can be
+ created declaratively using for example a
+ ContextLoader. Of course you can also create
+ ApplicationContext instances
+ programmatically using one of the
+ ApplicationContext implementations.
+ First, let's examine the ContextLoader mechanism
+ and its implementations.
+
+ The ContextLoader mechanism comes in two
+ flavors: the ContextLoaderListener and the
+ ContextLoaderServlet. They both have the same
+ functionality but differ in that the listener version cannot be reliably
+ used in Servlet 2.3 containers. Since the Servlet 2.4 specification,
+ servlet context listeners are required to execute immediately after the
+ servlet context for the web application has been created and is
+ available to service the first request (and also when the servlet
+ context is about to be shut down): as such a servlet context listener is
+ an ideal place to initialize the Spring
+ ApplicationContext. It is up to you as to
+ which one you use, but all things being equal you should probably prefer
+ ContextLoaderListener; for more information on
+ compatibility, have a look at the Javadoc for the
+ ContextLoaderServlet.
+
+ You can register an
+ ApplicationContext using the
+ ContextLoaderListener as follows:
+
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml</param-value>
+</context-param>
+
+<listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+</listener>
+
+<!-- or use the ContextLoaderServlet instead of the above listener
+<servlet>
+ <servlet-name>context</servlet-name>
+ <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+</servlet>
+-->
+
+ The listener inspects the
+ 'contextConfigLocation' parameter. If the parameter
+ does not exist, the listener will use
+ /WEB-INF/applicationContext.xml as a default. When it
+ does exist, it will separate the String using
+ predefined delimiters (comma, semicolon and whitespace) and use the
+ values as locations where application contexts will be searched for.
+ Ant-style path patterns are supported as well: e.g.
+ /WEB-INF/*Context.xml (for all files whose name ends
+ with "Context.xml", residing in the "WEB-INF" directory) or
+ /WEB-INF/**/*Context.xml (for all such files in any
+ subdirectory of "WEB-INF").
+
+ The ContextLoaderServlet can be used
+ instead of the ContextLoaderListener. The servlet
+ will use the 'contextConfigLocation' parameter just
+ as the listener does.
+
+
+
+
+ Glue code and the evil singleton
+
+ The majority of the code inside an application is best written in a
+ DI style, where that code is served out of a Spring IoC container, has its
+ own dependencies supplied by the container when it is created, and is
+ completely unaware of the container. However, for the small glue layers of
+ code that are sometimes needed to tie other code together, there is
+ sometimes a need for singleton (or quasi-singleton) style access to a
+ Spring IoC container. For example, third party code may try to construct
+ new objects directly (Class.forName() style), without
+ the ability to force it to get these objects out of a Spring IoC
+ container. If the object constructed by the third party code is just a
+ small stub or proxy, which then uses a singleton style access to a Spring
+ IoC container to get a real object to delegate to, then inversion of
+ control has still been achieved for the majority of the code (the object
+ coming out of the container); thus most code is still unaware of the
+ container or how it is accessed, and remains decoupled from other code,
+ with all ensuing benefits. EJBs may also use this stub/proxy approach to
+ delegate to a plain Java implementation object, coming out of a Spring IoC
+ container. While the Spring IoC container itself ideally does not have to
+ be a singleton, it may be unrealistic in terms of memory usage or
+ initialization times (when using beans in the Spring IoC container such as
+ a Hibernate SessionFactory) for each bean
+ to use its own, non-singleton Spring IoC container.
+
+ As another example, in complex J2EE applications with multiple
+ layers (various JAR files, EJBs, and WAR files packaged as an EAR), with
+ each layer having its own Spring IoC container definition (effectively
+ forming a hierarchy), the preferred approach when there is only one
+ web-app (WAR) in the top hierarchy is to simply create one composite
+ Spring IoC container from the multiple XML definition files from each
+ layer. All of the various Spring IoC container implementations may be
+ constructed from multiple definition files in this fashion. However, if
+ there are multiple sibling web-applications at the root of the hierarchy,
+ it is problematic to create a Spring IoC container for each
+ web-application which consists of mostly identical bean definitions from
+ lower layers, as there may be issues due to increased memory usage, issues
+ with creating multiple copies of beans which take a long time to
+ initialize (for example a Hibernate
+ SessionFactory), and possible issues due to
+ side-effects. As an alternative, classes such as ContextSingletonBeanFactoryLocator
+ or SingletonBeanFactoryLocator
+ may be used to demand-load multiple hierarchical (that is one container is
+ the parent of another) Spring IoC container instances in a singleton
+ fashion, which may then be used as the parents of the web-application
+ Spring IoC container instances. The result is that bean definitions for
+ lower layers are loaded only as needed, and loaded only once.
+
+ You can see a detailed example of the usage of these classes by
+ viewing the Javadoc for the SingletonBeanFactoryLocator
+ and ContextSingletonBeanFactoryLocator
+ classes. As mentioned in the chapter on EJBs,
+ the Spring convenience base classes for EJBs normally use a non-singleton
+ BeanFactoryLocator implementation, which is
+ easily replaced by the use of
+ SingletonBeanFactoryLocator and
+ ContextSingletonBeanFactoryLocator.
+
+
+
+ Deploying a Spring ApplicationContext as a J2EE RAR file
+
+ Since Spring 2.5, it is possible to deploy a Spring ApplicationContext
+ as a RAR file, encapsulating the context and all of its required bean classes
+ and library JARs in a J2EE RAR deployment unit. This is the equivalent of
+ bootstrapping a standalone ApplicationContext, just hosted in J2EE environment,
+ being able to access the J2EE server's facilities. RAR deployment is intended
+ as a more 'natural' alternative to the not uncommon scenario of deploying a
+ headless WAR file - i.e. a WAR file without any HTTP entry points, just used
+ for bootstrapping a Spring ApplicationContext in a J2EE environment.
+
+ RAR deployment is ideal for application contexts that do not need any
+ HTTP entry points but rather just consist of message endpoints and scheduled
+ jobs etc. Beans in such a context may use application server resources such
+ as the JTA transaction manager and JNDI-bound JDBC DataSources and JMS
+ ConnectionFactory instances, and may also register with the platform's
+ JMX server - all through Spring's standard transaction management and
+ JNDI and JMX support facilities. Application components may also interact
+ with the application's server JCA WorkManager through Spring's
+ TaskExecutor abstraction.
+
+ Check out the JavaDoc of the
+ SpringContextResourceAdapter
+ class for the configuration details involved in RAR deployment.
+
+ For simple deployment needs, all you need to do is the following:
+ Package all application classes into a RAR file (which is just a standard
+ JAR file with a different file extension), add all required library jars
+ into the root of the RAR archive, add a "META-INF/ra.xml" deployment descriptor
+ (as shown in SpringContextResourceAdapter's JavaDoc)
+ as well as the corresponding Spring XML bean definition file(s)
+ (typically "META-INF/applicationContext.xml"), and drop the resulting RAR
+ file into your application server's deployment directory!
+
+ NOTE: Such RAR deployment units are usually self-contained;
+ they do not expose components to the 'outside' world, not even to other
+ modules of the same application. Interaction with a RAR-based ApplicationContext
+ usually happens through JMS destinations that it shares with other modules.
+ A RAR-based ApplicationContext may also - for example - schedule some jobs,
+ reacting to new files in the file system (or the like). If it actually needs
+ to allow for synchronous access from the outside, it could for example export
+ RMI endpoints, which of course may be used by other application modules
+ on the same machine as well.
+
+
+
+ Annotation-based configuration
+
+ As mentioned in the section entitled , using a
+ BeanPostProcessor 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 @Required annotation. As of
+ Spring 2.5, it is now possible to follow that same general approach to
+ drive Spring's dependency injection. Essentially, the
+ @Autowired annotation provides the same
+ capabilities as described in but
+ with more fine-grained control and wider applicability. Spring 2.5 also
+ adds support for JSR-250 annotations such as
+ @Resource,
+ @PostConstruct, and
+ @PreDestroy. Of course, these options are
+ only available if you are using at least Java 5 (Tiger) and thus have
+ access to source level annotations. Use of these annotations also requires
+ that certain BeanPostProcessors be
+ registered within the Spring container. As always, these can be registered
+ as individual bean definitions, but they can also be implicitly registered
+ by including the following tag in an XML-based Spring configuration
+ (notice the inclusion of the 'context'
+ namespace):
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:annotation-config/>
+
+</beans>
+
+ (The implicitly registered post-processors include AutowiredAnnotationBeanPostProcessor,
+ CommonAnnotationBeanPostProcessor,
+ PersistenceAnnotationBeanPostProcessor,
+ as well as the aforementioned RequiredAnnotationBeanPostProcessor.)
+
+
+ Note that <context:annotation-config/> only looks for
+ annotations on beans in the same application context it is defined in.
+ This means that, if you put <context:annotation-config/> in a
+ WebApplicationContext for a DispatcherServlet, it only
+ checks for @Autowired beans in your controllers, and not your services.
+ See for more information.
+
+
+
+ @Required
+
+ The @Required annotation applies
+ to bean property setter methods, as in the following example:
+
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Required
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+}
+
+ This annotation simply indicates that the affected bean property must
+ be populated at configuration time: either through an explicit property value
+ in a bean definition or through autowiring. The container will throw an exception
+ if the affected bean property has not been populated; this allows for eager and
+ explicit failure, avoiding NullPointerExceptions or the
+ like later on. Note that it is still recommended to put assertions into the
+ bean class itself (for example into an init method) in order to enforce those
+ required references and values even when using the class outside of a container.
+
+
+
+ @Autowired
+
+ As expected, the @Autowired
+ annotation may be applied to "traditional" setter methods:
+
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Autowired
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+}
+
+ The annotation may also be applied to methods with arbitrary names
+ and/or multiple arguments:
+
+ public class MovieRecommender {
+
+ private MovieCatalog movieCatalog;
+
+ private CustomerPreferenceDao customerPreferenceDao;
+
+ @Autowired
+ public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
+ this.movieCatalog = movieCatalog;
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
+
+ // ...
+}
+
+ The @Autowired annotation may even
+ be applied on constructors and fields:
+
+ public class MovieRecommender {
+
+ @Autowired
+ private MovieCatalog movieCatalog;
+
+ private CustomerPreferenceDao customerPreferenceDao;
+
+ @Autowired
+ public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
+
+ // ...
+}
+
+ It is also possible to provide all beans of a
+ particular type from the
+ ApplicationContext by adding the
+ annotation to a field or method that expects an array of that
+ type:
+
+ public class MovieRecommender {
+
+ @Autowired
+ private MovieCatalog[] movieCatalogs;
+
+ // ...
+}
+
+ The same applies for typed collections:
+
+ public class MovieRecommender {
+
+ private Set<MovieCatalog> movieCatalogs;
+
+ @Autowired
+ public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
+ this.movieCatalogs = movieCatalogs;
+ }
+
+ // ...
+}
+
+ Even typed Maps may be autowired as long as the expected key type
+ is String. The Map values will contain all beans
+ of the expected type, and the keys will contain the corresponding bean
+ names:
+
+ public class MovieRecommender {
+
+ private Map<String, MovieCatalog> movieCatalogs;
+
+ @Autowired
+ public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
+ this.movieCatalogs = movieCatalogs;
+ }
+
+ // ...
+}
+
+ By default, the autowiring will fail whenever
+ zero candidate beans are available; the default
+ behavior is to treat annotated methods, constructors, and fields as
+ indicating required dependencies. This behavior can
+ be changed as demonstrated below.
+
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Autowired(required=false)
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+
+ // ...
+}
+
+
+ Only one annotated constructor per-class
+ may be marked as required, but multiple non-required
+ constructors can be annotated. In that case, each will be considered
+ among the candidates and Spring will use the greediest
+ constructor whose dependencies can be satisfied.
+
+ Prefer the use of @Autowired's
+ required attribute over the @Required
+ annotation. The required attribute indicates that
+ the property is not required for autowiring purposes, simply skipping
+ it if it cannot be autowired. @Required,
+ on the other hand, is stronger in that it enforces the property to
+ have been set in any of the container's supported ways; if no value
+ has been injected, a corresponding exception will be raised.
+
+
+ @Autowired may also be used for
+ well-known "resolvable dependencies": the BeanFactory
+ interface, the ApplicationContext interface,
+ the ResourceLoader interface,
+ the ApplicationEventPublisher interface
+ and the MessageSource interface.
+ These interfaces (and their extended interfaces such as
+ ConfigurableApplicationContext or
+ ResourcePatternResolver) will be
+ automatically resolved, with no special setup necessary.
+
+ public class MovieRecommender {
+
+ @Autowired
+ private ApplicationContext context;
+
+ public MovieRecommender() {
+ }
+
+ // ...
+}
+
+
+
+ Fine-tuning annotation-based autowiring with qualifiers
+
+ Since autowiring by type may lead to multiple candidates, it is
+ often necessary to have more control over the selection process. One way
+ to accomplish this is with Spring's
+ @Qualifier annotation. This allows for
+ associating qualifier values with specific arguments, narrowing the
+ set of type matches so that a specific bean is chosen for each argument.
+ In the simplest case, this can be a plain descriptive value:
+
+ public class MovieRecommender {
+
+ @Autowired
+ @Qualifier("main")
+ private MovieCatalog movieCatalog;
+
+ // ...
+}
+
+ The @Qualifier annotation can also
+ be specified on individual constructor arguments or method
+ parameters:
+
+ public class MovieRecommender {
+
+ private MovieCatalog movieCatalog;
+
+ private CustomerPreferenceDao customerPreferenceDao;
+
+ @Autowired
+ public void prepare(@Qualifier("main") MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
+ this.movieCatalog = movieCatalog;
+ this.customerPreferenceDao = customerPreferenceDao;
+ }
+
+ // ...
+}
+
+ The corresponding bean definitions would look like as follows.
+ The bean with qualifier value "main" would be wired with the
+ constructor argument that has been qualified with the same value.
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:annotation-config/>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier value="main"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier value="action"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean id="movieRecommender" class="example.MovieRecommender"/>
+
+</beans>
+
+
+ For a fallback match, the bean name is considered as a default qualifier
+ value. This means that the bean may be defined with an id "main" instead of
+ the nested qualifier element, leading to the same matching result. However,
+ note that while this can be used to refer to specific beans by name,
+ @Autowired is fundamentally about type-driven
+ injection with optional semantic qualifiers. This means that qualifier values,
+ even when using the bean name fallback, always have narrowing semantics within
+ the set of type matches; they do not semantically express a reference to a
+ unique bean id. Good qualifier values would be "main" or "EMEA" or "persistent",
+ expressing characteristics of a specific component - independent from the bean
+ id (which may be auto-generated in case of an anonymous bean definition like
+ the one above).
+
+ Qualifiers also apply to typed collections (as discussed above):
+ e.g. to Set<MovieCatalog>. In such a case,
+ all matching beans according to the declared qualifiers are going to
+ be injected as a collection. This implies that qualifiers do not have
+ to be unique; they rather simply constitute filtering criteria.
+ For example, there could be multiple MovieCatalog
+ beans defined with the same qualifier value "action"; all of which
+ would be injected into a Set<MovieCatalog>
+ annotated with @Qualifier("action").
+
+
+ If you intend to express annotation-driven injection by name,
+ do not primarily use @Autowired -
+ even if is technically capable of referring to a bean name through
+ @Qualifier values. Instead,
+ prefer the JSR-250 @Resource
+ 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.
+
+ As a specific consequence of this semantic difference,
+ beans which are themselves defined as a collection or map type
+ cannot be injected via @Autowired
+ since type matching is not properly applicable to them.
+ Use @Resource for such beans,
+ referring to the specific collection/map bean by unique name.
+
+ Note: In contrast to
+ @Autowired which is applicable to
+ fields, constructors and multi-argument methods (allowing for
+ narrowing through qualifier annotations at the parameter level),
+ @Resource is only supported for
+ fields and bean property setter methods with a single argument.
+ As a consequence, stick with qualifiers if your injection target
+ is a constructor or a multi-argument method.
+
+
+ You may create your own custom qualifier annotations as well.
+ Simply define an annotation and provide the
+ @Qualifier annotation within your
+ definition:
+
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface Genre {
+
+ String value();
+}
+
+ Then you can provide the custom qualifier on autowired fields and
+ parameters:
+
+ public class MovieRecommender {
+
+ @Autowired
+ @Genre("Action")
+ private MovieCatalog actionCatalog;
+
+ private MovieCatalog comedyCatalog;
+
+ @Autowired
+ public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
+ this.comedyCatalog = comedyCatalog;
+ }
+
+ // ...
+}
+
+ The next step is to provide the information on the candidate bean
+ definitions. You can add <qualifier/> tags as
+ sub-elements of the <bean/> tag and then
+ specify the 'type' and 'value' to
+ match your custom qualifier annotations. The type will be matched
+ against the fully-qualified class name of the annotation, or as a
+ convenience when there is no risk of conflicting names, you may use the
+ 'short' class name. Both are demonstrated in the following
+ example.
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:annotation-config/>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier type="Genre" value="Action"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier type="example.Genre" value="Comedy"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean id="movieRecommender" class="example.MovieRecommender"/>
+
+</beans>
+
+
+ In the next section, entitled ,
+ you will see an annotation-based alternative to providing the qualifier
+ metadata in XML. Specifically, see: .
+
+
+ In some cases, it may be sufficient to use an annotation without a
+ value. This may be useful when the annotation serves a more generic
+ purpose and could be applied across several different types of
+ dependencies. For example, you may provide an
+ offline catalog that would be searched when no
+ Internet connection is available. First define the simple
+ annotation:
+
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface Offline {
+
+}
+
+ Then add the annotation to the field or property to be
+ autowired:
+
+ public class MovieRecommender {
+
+ @Autowired
+ @Offline
+ private MovieCatalog offlineCatalog;
+
+ // ...
+}
+
+ Now the bean definition only needs a qualifier
+ 'type':
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier type="Offline"/>
+ <!-- inject any dependencies required by this bean -->
+</bean>
+
+ It is also possible to define custom qualifier annotations that
+ accept named attributes in addition to or instead of the simple
+ 'value' attribute. If multiple attribute values are
+ then specified on a field or parameter to be autowired, a bean
+ definition must match all such attribute values to
+ be considered an autowire candidate. As an example, consider the
+ following annotation definition:
+
+ @Target({ElementType.FIELD, ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Qualifier
+public @interface MovieQualifier {
+
+ String genre();
+
+ Format format();
+}
+
+ In this case Format is an enum:
+
+ public enum Format {
+
+ VHS, DVD, BLURAY
+}
+
+ The fields to be autowired are annotated with the custom qualifier
+ and include values for both attributes: 'genre' and
+ 'format'.
+
+ 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;
+
+ // ...
+}
+
+ Finally, the bean definitions should contain matching qualifier
+ values. This example also demonstrates that bean
+ meta attributes may be used instead of the
+ <qualifier/> sub-elements. If available, the
+ <qualifier/> and its attributes would take
+ precedence, but the autowiring mechanism will fallback on the values
+ provided within the <meta/> tags if no such
+ qualifier is present (see the last 2 bean definitions below).
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:annotation-config/>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier type="MovieQualifier">
+ <attribute key="format" value="VHS"/>
+ <attribute key="genre" value="Action"/>
+ </qualifier>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean class="example.SimpleMovieCatalog">
+ <qualifier type="MovieQualifier">
+ <attribute key="format" value="VHS"/>
+ <attribute key="genre" value="Comedy"/>
+ </qualifier>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean class="example.SimpleMovieCatalog">
+ <meta key="format" value="DVD"/>
+ <meta key="genre" value="Action"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+ <bean class="example.SimpleMovieCatalog">
+ <meta key="format" value="BLURAY"/>
+ <meta key="genre" value="Comedy"/>
+ <!-- inject any dependencies required by this bean -->
+ </bean>
+
+</beans>
+
+
+
+ CustomAutowireConfigurer
+
+ The CustomAutowireConfigurer
+ is a BeanFactoryPostProcessor that
+ enables further customization of the autowiring process. Specifically,
+ it allows you to register your own custom qualifier annotation types
+ even if they are not themselves annotated with Spring's
+ @Qualifier annotation.
+
+ <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
+ <property name="customQualifierTypes">
+ <set>
+ <value>example.CustomQualifier</value>
+ </set>
+ </property>
+</bean>
+
+ Note that the particular implementation of
+ AutowireCandidateResolver that will be
+ activated for the application context depends upon the Java version. If
+ running on less than Java 5, the qualifier annotations are not
+ supported, and therefore autowire candidates are solely determined by
+ the 'autowire-candidate' value of each bean
+ definition as well as any
+ 'default-autowire-candidates' pattern(s) available on
+ the <beans/> element. If running on Java 5 or
+ greater, the presence of @Qualifier
+ annotations or any custom annotations registered with the
+ CustomAutowireConfigurer will also play a
+ role.
+
+ Regardless of the Java version, the determination of a "primary"
+ candidate (when multiple beans qualify as autowire candidates) is the
+ same: if exactly one bean definition among the candidates has a
+ 'primary' attribute set to 'true',
+ it will be selected.
+
+
+
+ @Resource
+
+ Spring also supports injection using the JSR-250
+ @Resource annotation on fields or
+ bean property setter methods. This is a common pattern found in
+ Java EE 5 and Java 6 (e.g. in JSF 1.2 managed beans or JAX-WS 2.0
+ endpoints), which Spring supports for Spring-managed objects as well.
+
+ @Resource takes a 'name' attribute,
+ and by default Spring will interpret that value as the bean name to be
+ injected. In other words, it follows by-name
+ semantics as demonstrated in this example:
+
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Resource(name="myMovieFinder")
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+}
+
+ If no name is specified explicitly, then the default name
+ will be derived from the name of the field or setter method:
+ In case of a field, it will simply be equivalent to the field name;
+ in case of a setter method, it will be equivalent to the bean
+ property name. So the following example is going to have the bean
+ with name "movieFinder" injected into its setter method:
+
+ public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Resource
+ public void setMovieFinder(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+}
+
+
+ The name provided with the annotation will be resolved as a bean
+ name by the BeanFactory of which the
+ CommonAnnotationBeanPostProcessor is aware.
+ Note that the names may be resolved via JNDI if Spring's SimpleJndiBeanFactory
+ is configured explicitly. However, it is recommended to rely on the
+ default behavior and simply use Spring's JNDI lookup capabilities to
+ preserve the level of indirection.
+
+
+ Similar to @Autowired,
+ @Resource may fall back to standard bean type
+ matches (i.e. find a primary type match instead of a specific named bean)
+ as well as resolve well-known "resolvable dependencies":
+ the BeanFactory interface,
+ the ApplicationContext interface,
+ the ResourceLoader interface,
+ the ApplicationEventPublisher interface
+ and the MessageSource interface.
+ Note that this only applies to @Resource
+ usage with no explicit name specified!
+
+ So the following example will have its customerPreferenceDao
+ field looking for a bean with name "customerPreferenceDao" first, then falling
+ back to a primary type match for the type CustomerPreferenceDao.
+ The "context" field will simply be injected based on the known resolvable dependency
+ type ApplicationContext.
+
+ public class MovieRecommender {
+
+ @Resource
+ private CustomerPreferenceDao customerPreferenceDao;
+
+ @Resource
+ private ApplicationContext context;
+
+ public MovieRecommender() {
+ }
+
+ // ...
+}
+
+
+
+ @PostConstruct and
+ @PreDestroy
+
+ The CommonAnnotationBeanPostProcessor not
+ only recognizes the @Resource annotation
+ but also the JSR-250 lifecycle annotations.
+ Introduced in Spring 2.5, the support for these annotations offers yet
+ another alternative to those described in the sections on initialization
+ callbacks and destruction
+ callbacks. Provided that the
+ CommonAnnotationBeanPostProcessor is registered
+ within the Spring ApplicationContext, a
+ method carrying one of these annotations will be invoked at the same
+ point in the lifecycle as the corresponding Spring lifecycle interface's
+ method or explicitly declared callback method. In the example below, the
+ cache will be pre-populated upon initialization and cleared upon
+ destruction.
+
+ public class CachingMovieLister {
+
+ @PostConstruct
+ public void populateMovieCache() {
+ // populates the movie cache upon initialization...
+ }
+
+ @PreDestroy
+ public void clearMovieCache() {
+ // clears the movie cache upon destruction...
+ }
+}
+
+
+ For details regarding the effects of combining various lifecycle
+ mechanisms, see .
+
+
+
+
+
+ Classpath scanning for managed components
+
+ Thus far most of the examples within this chapter have used XML for
+ specifying the configuration metadata that produces each
+ BeanDefinition within the Spring container.
+ The previous section ()
+ demonstrated the possibility of providing a considerable amount of the
+ configuration metadata using source-level annotations. Even in those
+ examples however, the "base" bean definitions were explicitly defined in
+ the XML file while the annotations were driving the dependency injection
+ only. The current section introduces an option for implicitly detecting the
+ candidate components by scanning the classpath and
+ matching against filters.
+
+
+ @Component and further stereotype
+ annotations
+
+ Beginning with Spring 2.0, the
+ @Repository annotation was introduced as
+ a marker for any class that fulfills the role or
+ stereotype of a repository (a.k.a. Data Access
+ Object or DAO). Among the possibilities for leveraging such a marker is
+ the automatic translation of exceptions as described in .
+
+ Spring 2.5 introduces further stereotype annotations:
+ @Component,
+ @Service and
+ @Controller.
+ @Component serves as a generic stereotype
+ for any Spring-managed component; whereas,
+ @Repository,
+ @Service, and
+ @Controller serve as specializations of
+ @Component for more specific use cases
+ (e.g., in the persistence, service, and presentation layers,
+ respectively). What this means is that you can annotate your component
+ classes with @Component, but by
+ annotating them with @Repository,
+ @Service, or
+ @Controller instead, your classes are
+ more properly suited for processing by tools or associating with aspects.
+ For example, these stereotype annotations make ideal targets for
+ pointcuts. Of course, it is also possible that
+ @Repository,
+ @Service, and
+ @Controller may carry additional
+ semantics in future releases of the Spring Framework. Thus, if you are
+ making a decision between using @Component
+ or @Service for your service layer,
+ @Service is clearly the better choice.
+ Similarly, as stated above, @Repository
+ is already supported as a marker for automatic exception translation in
+ your persistence layer.
+
+
+
+ Auto-detecting components
+
+ Spring provides the capability of automatically detecting
+ 'stereotyped' classes and registering corresponding
+ BeanDefinitions with the
+ ApplicationContext. For example, the
+ following two classes are eligible for such autodetection:
+
+ @Service
+public class SimpleMovieLister {
+
+ private MovieFinder movieFinder;
+
+ @Autowired
+ public SimpleMovieLister(MovieFinder movieFinder) {
+ this.movieFinder = movieFinder;
+ }
+}
+
+ @Repository
+public class JpaMovieFinder implements MovieFinder {
+ // implementation elided for clarity
+}
+
+ To autodetect these classes and register the corresponding beans
+ requires the inclusion of the following element in XML where
+ 'basePackage' would be a common parent package for the two classes (or
+ alternatively a comma-separated list could be specified that included
+ the parent package of each class).
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="org.example"/>
+
+</beans>
+
+
+ Note that the scanning of classpath packages requires
+ the presence of corresponding directory entries in the classpath.
+ When building jars with Ant, make sure to not
+ activate the files-only switch of the jar task!
+
+
+ Furthermore, the
+ AutowiredAnnotationBeanPostProcessor and
+ CommonAnnotationBeanPostProcessor are
+ both included implicitly when using the component-scan element. That
+ means that the two components are autodetected and
+ wired together - all without any bean configuration metadata provided in
+ XML.
+
+
+ The registration of those post-processors can be disabled by
+ including the annotation-config attribute with a
+ value of 'false'.
+
+
+
+
+ Using filters to customize scanning
+
+ By default, classes annotated with
+ @Component,
+ @Repository,
+ @Service, or
+ @Controller (or classes annotated with a
+ custom annotation that itself is annotated with
+ @Component) are the only detected
+ candidate components. However it is simple to modify and extend this
+ behavior by applying custom filters. These can be added as either
+ include-filter or
+ exclude-filter sub-elements of the
+ 'component-scan' element. Each filter element requires
+ the 'type' and 'expression'
+ attributes. Five filtering options exist as described below.
+
+
+ Filter Types
+
+
+
+
+
+
+
+ Filter Type
+ Example Expression
+ Description
+
+
+
+
+ annotation
+ org.example.SomeAnnotation
+ An annotation to be present at the type level in target components.
+
+
+ assignable
+ org.example.SomeClass
+ A class (or interface) that the target components are assignable to (extend/implement).
+
+
+ aspectj
+ org.example..*Service+
+ An AspectJ type expression to be matched by the target components.
+
+
+ regex
+ org\.example\.Default.*
+ A regex expression to be matched by the target components' class names.
+
+
+ custom
+ org.example.MyCustomTypeFilter
+ A custom implementation of the org.springframework.core.type.TypeFilter interface.
+
+
+
+
+
+ Find below an example of the XML configuration for ignoring all
+ @Repository annotations and using "stub"
+ repositories instead.
+
+ <beans ...>
+
+ <context:component-scan base-package="org.example">
+ <context:include-filter type="regex" expression=".*Stub.*Repository"/>
+ <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
+ </context:component-scan>
+
+</beans>
+
+
+ It is also possible to disable the default filters by providing
+ use-default-filters="false" as an attribute of
+ the <component-scan/> element. This will in effect disable
+ automatic detection of classes annotated with
+ @Component,
+ @Repository,
+ @Service, or
+ @Controller.
+
+
+
+
+ Naming autodetected components
+
+ When a component is autodetected as part of the scanning process,
+ its bean name will be generated by the
+ BeanNameGenerator strategy known to that
+ scanner. By default, any Spring 'stereotype' annotation
+ (@Component,
+ @Repository,
+ @Service, and
+ @Controller) that contains a
+ name value will thereby provide that name to the
+ corresponding bean definition. If such an annotation contains no
+ name value or for any other detected component (such as
+ those discovered due to custom filters), the default bean name generator
+ will return the uncapitalized non-qualified class name. For example, if
+ the following two components were detected, the names would be
+ 'myMovieLister' and 'movieFinderImpl':
+
+ @Service("myMovieLister")
+public class SimpleMovieLister {
+ // ...
+}
+
+ @Repository
+public class MovieFinderImpl implements MovieFinder {
+ // ...
+}
+
+
+ If you don't want to rely on the default bean-naming strategy,
+ you may provide a custom bean-naming strategy. First, implement the
+ BeanNameGenerator
+ interface, and be sure to include a default no-arg constructor. Then,
+ provide the fully-qualified class name when configuring the
+ scanner:
+
+
+ <beans ...>
+
+ <context:component-scan base-package="org.example"
+ name-generator="org.example.MyNameGenerator" />
+
+</beans>
+
+ 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.
+
+
+
+ Providing a scope for autodetected components
+
+ As with Spring-managed components in general, the default and by
+ far most common scope is 'singleton'. However, there are times when
+ other scopes are needed. Therefore Spring 2.5 introduces a new
+ @Scope annotation as well. Simply provide
+ the name of the scope within the annotation, such as:
+
+ @Scope("prototype")
+@Repository
+public class MovieFinderImpl implements MovieFinder {
+ // ...
+}
+
+
+ If you would like to provide a custom strategy for scope
+ resolution rather than relying on the annotation-based approach,
+ implement the ScopeMetadataResolver
+ interface, and be sure to include a default no-arg constructor. Then,
+ provide the fully-qualified class name when configuring the
+ scanner:
+
+
+ <beans ...>
+
+ <context:component-scan base-package="org.example"
+ scope-resolver="org.example.MyScopeResolver" />
+
+</beans>
+
+ When using certain non-singleton scopes, it may be necessary to
+ generate proxies for the scoped objects. The reasoning is described in
+ detail within the section entitled . For this purpose, a
+ scoped-proxy 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:
+
+ <beans ...>
+
+ <context:component-scan base-package="org.example"
+ scoped-proxy="interfaces" />
+
+</beans>
+
+
+
+ Providing qualifier metadata with annotations
+
+ The @Qualifier annotation was
+ introduced in the section above entitled
+ . The
+ examples in that section demonstrated use of the
+ @Qualifier annotation as well
+ as custom qualifier annotations to provide fine-grained control
+ when resolving autowire candidates. Since those examples were
+ based on XML bean definitions, the qualifier metadata was provided
+ on the candidate bean definitions using the 'qualifier'
+ or 'meta' sub-elements of the 'bean'
+ element in the XML. When relying upon classpath scanning for
+ autodetection of components, then the qualifier metadata may
+ be provided with type-level annotations on the candidate class.
+ The following three examples demonstrate this technique.
+
+ @Component
+@Qualifier("Action")
+public class ActionMovieCatalog implements MovieCatalog {
+ // ...
+}
+
+ @Component
+@Genre("Action")
+public class ActionMovieCatalog implements MovieCatalog {
+ // ...
+}
+
+ @Component
+@Offline
+public class CachingMovieCatalog implements MovieCatalog {
+ // ...
+}
+
+ As with most of the annotation-based alternatives, keep
+ in mind that the annotation metadata is bound to the class
+ definition itself, while the use of XML allows for multiple
+ beans of the same type to provide variations
+ in their qualifier metadata since that metadata is provided
+ per-instance rather than per-class.
+
+
+
+
+ Registering a LoadTimeWeaver
+
+ The context namespace introduced in Spring 2.5
+ provides a load-time-weaver element.
+
+ <beans ...>
+
+ <context:load-time-weaver/>
+
+</beans>
+
+ Adding this element to an XML-based Spring configuration file
+ activates a Spring LoadTimeWeaver for the
+ ApplicationContext. Any bean within that
+ ApplicationContext may implement
+ LoadTimeWeaverAware thereby receiving a
+ reference to the load-time weaver instance. This is particularly useful in
+ combination with Spring's JPA support where
+ load-time weaving may be necessary for JPA class transformation. Consult
+ the LocalContainerEntityManagerFactoryBean Javadoc
+ for more detail. For more on AspectJ load-time weaving, see .
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/cci.xml b/spring-framework-reference/src/cci.xml
new file mode 100644
index 00000000000..4dcdad0c4d6
--- /dev/null
+++ b/spring-framework-reference/src/cci.xml
@@ -0,0 +1,1155 @@
+
+
+ JCA CCI
+
+
+ Introduction
+
+ J2EE provides a specification to standardize access to enterprise information systems (EIS):
+ the JCA (Java Connector Architecture). This specification is divided into several different parts:
+
+
+
+ SPI (Service provider interfaces) that the connector provider
+ must implement. These interfaces constitute a resource adapter which
+ can be deployed on a J2EE application server. In such a scenario, the
+ server manages connection pooling, transaction and security (managed
+ mode). The application server is also responsible for managing the
+ configuration, which is held outside the client application. A connector
+ can be used without an application server as well; in this case, the
+ application must configure it directly (non-managed mode).
+
+
+
+ CCI (Common Client Interface) that an application can use to
+ interact with the connector and thus communicate with an EIS. An API
+ for local transaction demarcation is provided as well.
+
+
+
+ The aim of the Spring CCI support is to provide classes to access
+ a CCI connector in typical Spring style, leveraging the Spring Framework's general
+ resource and transaction management facilities.
+
+
+ The client side of connectors doesn't alway use CCI. Some
+ connectors expose their own APIs, only providing JCA resource adapter to
+ use the system contracts of a J2EE container (connection pooling, global
+ transactions, security). Spring does not offer special support for such
+ connector-specific APIs.
+
+
+
+
+ Configuring CCI
+
+
+ Connector configuration
+
+ The base resource to use JCA CCI is the
+ ConnectionFactory interface. The connector used
+ must provide an implementation of this interface.
+
+ To use your connector, you can deploy it on your application
+ server and fetch the ConnectionFactory from the
+ server's JNDI environment (managed mode). The connector must be
+ packaged as a RAR file (resource adapter archive) and contain a
+ ra.xml file to describe its deployment
+ characteristics. The actual name of the resource is specified when
+ you deploy it. To access it within Spring, simply use Spring's
+ JndiObjectFactoryBean to fetch the factory
+ by its JNDI name.
+
+ Another way to use a connector is to embed it in your application
+ (non-managed mode), not using an application server to deploy and
+ configure it. Spring offers the possibility to configure a connector
+ as a bean, through a provided FactoryBean
+ (LocalConnectionFactoryBean). In this manner,
+ you only need the connector library in the classpath (no RAR file and
+ no ra.xml descriptor needed). The library must
+ be extracted from the connector's RAR file, if necessary.
+
+ Once you have got access to your ConnectionFactory
+ instance, you can inject it into your components. These components can
+ either be coded against the plain CCI API or leverage Spring's support
+ classes for CCI access (e.g. CciTemplate).
+
+
+ When you use a connector in
+ non-managed mode, you can't use global transactions because the resource
+ is never enlisted / delisted in the current global transaction of the
+ current thread. The resource is simply not aware of any global J2EE
+ transactions that might be running.
+
+
+
+
+ ConnectionFactory configuration in Spring
+
+ In order to make connections to the EIS, you need to obtain a
+ ConnectionFactory from the application server if
+ you are in a managed mode, or directly from Spring if you are in a
+ non-managed mode.
+
+ In a managed mode, you access a ConnectionFactory
+ from JNDI; its properties will be configured in the application server.
+
+
+
+]]>
+
+ In non-managed mode, you must configure the ConnectionFactory
+ you want to use in the configuration of Spring as a JavaBean. The
+ LocalConnectionFactoryBean class offers this
+ setup style, passing in the ManagedConnectionFactory
+ implementation of your connector, exposing the application-level
+ CCI ConnectionFactory.
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ You can't directly instantiate a specific
+ ConnectionFactory. You need to go through
+ the corresponding implementation of the
+ ManagedConnectionFactory interface for your
+ connector. This interface is part of the JCA SPI specification.
+
+
+
+
+ Configuring CCI connections
+
+ JCA CCI allow the developer to configure the connections to the
+ EIS using the ConnectionSpec implementation of your
+ connector. In order to configure its properties, you need to wrap the
+ target connection factory with a dedicated adapter,
+ ConnectionSpecConnectionFactoryAdapter. So, the
+ dedicated ConnectionSpec can be configured with the
+ property connectionSpec (as an inner bean).
+
+ This property is not mandatory because the CCI
+ ConnectionFactory interface defines two different
+ methods to obtain a CCI connection. Some of the
+ ConnectionSpec properties can often be configured
+ in the application server (in managed mode) or on the corresponding local
+ ManagedConnectionFactory implementation.
+
+
+
+ Spring provides a ConnectionSpecConnectionFactoryAdapter
+ that allows for specifying a ConnectionSpec instance
+ to use for all operations on a given factory. If the adapter's
+ connectionSpec property is specified, the adapter
+ uses the getConnection variant without argument,
+ else the one with the ConnectionSpec argument.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ Using a single CCI connection
+
+ If you want to use a single CCI connection, Spring provides a further
+ ConnectionFactory adapter to manage this. The
+ SingleConnectionFactory adapter class will open a single
+ connection lazily and close it when this bean is destroyed at application
+ shutdown. This class will expose special Connection
+ proxies that behave accordingly, all sharing the same underlying physical
+ connection.
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+ This ConnectionFactory adapter cannot directly be
+ configured with a ConnectionSpec. Use an
+ intermediary ConnectionSpecConnectionFactoryAdapter
+ that the SingleConnectionFactory talks to
+ if you require a single connection for a specific
+ ConnectionSpec.
+
+
+
+
+
+ Using Spring's CCI access support
+
+
+ Record conversion
+
+ One of the aims of the JCA CCI support is to provide convenient
+ facilities for manipulating CCI records. The developer can specify the
+ strategy to create records and extract datas from records, for use
+ with Spring's CciTemplate. The following interfaces will configure the
+ strategy to use input and output records if you don't want to work
+ with records directly in your application.
+
+ In order to create an input Record, the
+ developer can use a dedicated implementation of the
+ RecordCreator interface.
+
+
+
+ As you can see, the createRecord(..) method
+ receives a RecordFactory instance as parameter,
+ which corresponds to the RecordFactory of the
+ ConnectionFactory used. This reference can be
+ used to create IndexedRecord or
+ MappedRecord instances. The following sample
+ shows how to use the RecordCreator interface
+ and indexed/mapped records.
+
+
+
+ An output Record can be used to receive
+ data back from the EIS. Hence, a specific implementation of the
+ RecordExtractor interface can be passed to
+ Spring's CciTemplate for extracting data from the output
+ Record.
+
+
+
+ The following sample shows how to use the RecordExtractor interface.
+
+
+
+
+
+ The CciTemplate
+
+ The CciTemplate is the central class of the core CCI support package
+ (org.springframework.jca.cci.core). It simplifies
+ the use of CCI since it handles the creation and release of resources.
+ This helps to avoid common errors like forgetting to always close the
+ connection. It cares for the lifecycle of connection and interaction
+ objects, letting application code focus on generating input records
+ from application data and extracting application data from output
+ records.
+
+ The JCA CCI specification defines two distinct methods to call
+ operations on an EIS. The CCI Interaction
+ interface provides two execute method signatures:
+
+
+
+ Depending on the template method called, CciTemplate
+ will know which execute method to call on the interaction.
+ In any case, a correctly initialized InteractionSpec
+ instance is mandatory.
+
+ CciTemplate.execute(..) can be used in two ways:
+
+
+
+ With direct Record arguments. In this case,
+ you simply need to pass the CCI input record in, and the returned object
+ be the corresponding CCI output record.
+
+
+
+ With application objects, using record mapping. In this case,
+ you need to provide corresponding RecordCreator
+ and RecordExtractor instances.
+
+
+
+
+ With the first approach, the following methods of the template
+ will be used. These methods directly correspond to those on the
+ Interaction interface.
+
+
+
+ With the second approach, we need to specify the record creation
+ and record extraction strategies as arguments. The interfaces used
+ are those describe in the previous section on record conversion.
+ The corresponding CciTemplate methods are the
+ following:
+
+
+
+ Unless the outputRecordCreator property is
+ set on the template (see the following section), every method will call
+ the corresponding execute method of the CCI
+ Interaction with two parameters:
+ InteractionSpec and input Record,
+ receiving an output Record as return value.
+
+
+ CciTemplate also provides methods to create
+ IndexRecord and MappedRecord
+ outside a RecordCreator implementation, through
+ its createIndexRecord(..) and
+ createMappedRecord(..) methods. This can be used
+ within DAO implementations to create Record
+ instances to pass into corresponding
+ CciTemplate.execute(..) methods.
+
+
+
+
+
+ DAO support
+
+ Spring's CCI support provides a abstract class for DAOs,
+ supporting injection of a ConnectionFactory
+ or a CciTemplate instances. The name of the
+ class is CciDaoSupport: It provides simple
+ setConnectionFactory and
+ setCciTemplate methods. Internally, this
+ class will create a CciTemplate instance
+ for a passed-in ConnectionFactory, exposing
+ it to concrete data access implementations in subclasses.
+
+
+
+
+
+ Automatic output record generation
+
+ If the connector used only supports the
+ Interaction.execute(..) method with input and output
+ records as parameters (that is, it requires the desired output record
+ to be passed in instead of returning an appropriate output record),
+ you can set the outputRecordCreator property of the
+ CciTemplate to automatically generate an output
+ record to be filled by the JCA connector when the response is received.
+ This record will be then returned to the caller of the template.
+
+ This property simply holds an implementation of the
+ RecordCreator interface, used for that purpose.
+ The RecordCreator interface has already been
+ discussed in the section entitled .
+ The outputRecordCreator
+ property must be directly specified on the CciTemplate.
+ This could be done in the application code like so:
+
+
+
+ Or (recommended) in the Spring configuration, if the CciTemplate
+ is configured as a dedicated bean instance:
+
+
+
+
+
+
+]]>
+
+
+ As the CciTemplate class is thread-safe, it will
+ usually be configured as a shared instance.
+
+
+
+
+ Summary
+
+ The following table summarizes the mechanisms of the
+ CciTemplate class and the corresponding methods
+ called on the CCI Interaction interface:
+ Usage of Interaction execute methods
+
+
+
+
+ CciTemplate method signature
+
+ CciTemplate outputRecordCreator
+ property
+
+ execute method called on the CCI
+ Interaction
+
+
+
+
+
+ Record execute(InteractionSpec,
+ Record)
+
+ not set
+
+ Record execute(InteractionSpec,
+ Record)
+
+
+
+ Record execute(InteractionSpec,
+ Record)
+
+ set
+
+ boolean execute(InteractionSpec, Record,
+ Record)
+
+
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+ not set
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+ set
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+
+
+ Record execute(InteractionSpec,
+ RecordCreator)
+
+ not set
+
+ Record execute(InteractionSpec,
+ Record)
+
+
+
+ Record execute(InteractionSpec,
+ RecordCreator)
+
+ set
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+
+
+ Record execute(InteractionSpec, Record,
+ RecordExtractor)
+
+ not set
+
+ Record execute(InteractionSpec,
+ Record)
+
+
+
+ Record execute(InteractionSpec, Record,
+ RecordExtractor)
+
+ set
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+
+
+ Record execute(InteractionSpec,
+ RecordCreator, RecordExtractor)
+
+ not set
+
+ Record execute(InteractionSpec,
+ Record)
+
+
+
+ Record execute(InteractionSpec,
+ RecordCreator, RecordExtractor)
+
+ set
+
+ void execute(InteractionSpec, Record,
+ Record)
+
+
+
+
+
+
+
+ Using a CCI Connection and Interaction directly
+
+ CciTemplate also offers the possibility to
+ work directly with CCI connections and interactions, in the same manner
+ as JdbcTemplate and JmsTemplate.
+ This is useful when you want to perform multiple operations on a CCI
+ connection or interaction, for example.
+
+ The interface ConnectionCallback provides a
+ CCI Connection as argument, in order to perform
+ custom operations on it, plus the CCI ConnectionFactory
+ which the Connection was created with. The latter
+ can be useful for example to get an associated RecordFactory
+ instance and create indexed/mapped records, for example.
+
+
+
+ The interface InteractionCallback provides
+ the CCI Interaction, in order to perform custom
+ operations on it, plus the corresponding CCI ConnectionFactory.
+
+
+
+
+
+ InteractionSpec objects
+ can either be shared across multiple template calls or newly created
+ inside every callback method. This is completely up to the DAO implementation.
+
+
+
+
+ Example for CciTemplate usage
+
+ In this section, the usage of the CciTemplate
+ will be shown to acces to a CICS with ECI mode, with the IBM CICS ECI
+ connector.
+
+ Firstly, some initializations on the CCI
+ InteractionSpec must be done to specify which CICS
+ program to access and how to interact with it.
+
+
+
+ Then the program can use CCI via Spring's template and specify
+ mappings between custom objects and CCI Records.
+
+
+
+ As discussed previously, callbacks can be used to work
+ directly on CCI connections or interactions.
+
+ // do something...
+
+
+ With a ConnectionCallback,
+ the Connection used will be managed and closed by
+ the CciTemplate, but any interactions created
+ on the connection must be managed by the callback implementation.
+
+
+ For a more specific callback, you can implement an
+ InteractionCallback. The passed-in
+ Interaction will be managed and closed by the
+ CciTemplate in this case.
+
+
+
+ For the examples above, the corresponding configuration of the
+ involved Spring beans could look like this in non-managed mode:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ In managed mode (that is, in a J2EE environment), the configuration
+ could look as follows:
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ Modeling CCI access as operation objects
+
+ The org.springframework.jca.cci.object package
+ contains support classes that allow you to access the EIS in a different
+ style: through reusable operation objects, analogous to Spring's JDBC
+ operation objects (see JDBC chapter). This will usually encapsulate the
+ CCI API: an application-level input object will be passed to the operation
+ object, so it can construct the input record and then convert the received
+ record data to an application-level output object and return it.
+
+ Note: This approach is internally based on the
+ CciTemplate class and the RecordCreator
+ / RecordExtractor interfaces, reusing the machinery of
+ Spring's core CCI support.
+
+
+ MappingRecordOperation
+
+ MappingRecordOperation essentially performs the
+ same work as CciTemplate, but represents a specific,
+ pre-configured operation as an object. It provides two template methods
+ to specify how to convert an input object to a input record, and how to
+ convert an output record to an output object (record mapping):
+
+
+
+ createInputRecord(..) to specify how to
+ convert an input object to an input Record
+
+
+
+ extractOutputData(..) to specify how to
+ extract an output object from an output Record
+
+
+
+ Here are the signatures of these methods:
+
+
+
+ Thereafter, in order to execute an EIS operation, you need to use
+ a single execute method, passing in an application-level input object
+ and receiving an application-level output object as result:
+
+
+
+ As you can see, contrary to the CciTemplate class,
+ this execute(..) method does not have an
+ InteractionSpec as argument. Instead, the
+ InteractionSpec is global to the operation.
+ The following constructor must be used to instantiate an operation
+ object with a specific InteractionSpec:
+
+
+
+
+
+ MappingCommAreaOperation
+
+ Some connectors use records based on a COMMAREA which represents
+ an array of bytes containing parameters to send to the EIS and data
+ returned by it. Spring provides a special operation class for working
+ directly on COMMAREA rather than on records. The
+ MappingCommAreaOperation class extends the
+ MappingRecordOperation class to provide such special
+ COMMAREA support. It implicitly uses the CommAreaRecord
+ class as input and output record type, and provides two new methods to
+ convert an input object into an input COMMAREA and the output COMMAREA
+ into an output object.
+
+
+
+
+
+ Automatic output record generation
+
+ As every MappingRecordOperation subclass is
+ based on CciTemplate internally, the same way to automatically generate
+ output records as with CciTemplate is available.
+ Every operation object provides a corresponding
+ setOutputRecordCreator(..) method. For further information,
+ see the section entitled .
+
+
+
+ Summary
+
+ The operation object approach uses records in the same manner
+ as the CciTemplate class.
+
+
+ Usage of Interaction execute methods
+
+
+
+
+ MappingRecordOperation method
+ signature
+
+ MappingRecordOperation
+ outputRecordCreator property
+
+ execute method called on the CCI
+ Interaction
+
+
+
+
+
+ Object execute(Object)
+
+ not set
+
+ Record execute(InteractionSpec,
+ Record)
+
+
+
+ Object execute(Object)
+
+ set
+
+ boolean execute(InteractionSpec, Record,
+ Record)
+
+
+
+
+
+
+
+ Example for MappingRecordOperation usage
+
+ In this section, the usage of the
+ MappingRecordOperation will be shown to access a
+ database with the Blackbox CCI connector.
+
+
+ The original version of this connector is provided by the J2EE SDK
+ (version 1.3), available from Sun.
+
+
+ Firstly, some initializations on the CCI
+ InteractionSpec must be done to specify which SQL
+ request to execute. In this sample, we directly define the way to
+ convert the parameters of the request to a CCI record and the way to
+ convert the CCI result record to an instance of the
+ Person class.
+
+
+
+ Then the application can execute the operation object, with the
+ person identifier as argument. Note that operation object could be
+ set up as shared instance, as it is thread-safe.
+
+
+
+ The corresponding configuration of Spring beans could look
+ as follows in non-managed mode:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ In managed mode (that is, in a J2EE environment), the configuration
+ could look as follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ Example for MappingCommAreaOperation usage
+
+ In this section, the usage of the
+ MappingCommAreaOperation will be shown: accessing
+ a CICS with ECI mode with the IBM CICS ECI connector.
+
+ Firstly, the CCI InteractionSpec needs to be
+ initialized to specify which CICS program to access and how to interact
+ with it.
+
+
+
+ The abstract EciMappingOperation class can
+ then be subclassed to specify mappings between custom objects and
+ Records.
+
+
+
+ The corresponding configuration of Spring beans could look
+ as follows in non-managed mode:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ In managed mode (that is, in a J2EE environment), the configuration
+ could look as follows:
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ Transactions
+
+ JCA specifies several levels of transaction support for resource adapters.
+ The kind of transactions that your resource adapter supports is specified
+ in its ra.xml file. There are essentially three options:
+ none (for example with CICS EPI connector), local transactions (for
+ example with a CICS ECI connector), global transactions (for example with an
+ IMS connector).
+
+
+
+
+
+ ]]><!-- <transaction-support>NoTransaction</transaction-support> --><!-- <transaction-support>LocalTransaction</transaction-support> -->XATransaction
+
+
+
+]]>
+
+ For global transactions, you can use Spring's generic transaction
+ infrastructure to demarcate transactions, with JtaTransactionManager as
+ backend (delegating to the J2EE server's distributed transaction coordinator
+ underneath).
+
+ For local transactions on a single CCI ConnectionFactory,
+ Spring provides a specific transaction management strategy for CCI, analogous
+ to the DataSourceTransactionManager for JDBC. The CCI API
+ defines a local transaction object and corresponding local transaction
+ demarcation methods. Spring's CciLocalTransactionManager
+ executes such local CCI transactions, fully compliant with Spring's generic
+ PlatformTransactionManager abstraction.
+
+
+
+
+
+
+
+]]>
+
+ Both transaction strategies can be used with any of Spring's
+ transaction demarcation facilities, be it declarative or programmatic.
+ This is a consequence of Spring's generic
+ PlatformTransactionManager abstraction, which
+ decouples transaction demarcation from the actual execution strategy.
+ Simply switch between JtaTransactionManager and
+ CciLocalTransactionManager as needed, keeping
+ your transaction demarcation as-is.
+
+ For more information on Spring's transaction facilities, see the
+ chapter entitled .
+
+
diff --git a/spring-framework-reference/src/dao.xml b/spring-framework-reference/src/dao.xml
new file mode 100644
index 00000000000..2e19e5393aa
--- /dev/null
+++ b/spring-framework-reference/src/dao.xml
@@ -0,0 +1,125 @@
+
+
+ DAO support
+
+ Introduction
+
+ The Data Access Object (DAO) support in Spring is aimed at
+ making it easy to work with data access technologies like
+ JDBC, Hibernate 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.
+
+
+
+ Consistent exception hierarchy
+
+ Spring provides a convenient translation from technology-specific
+ exceptions like SQLException to its own
+ exception class hierarchy with the
+ DataAccessException 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.
+
+
+ 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.
+
+
+ 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
+ HibernateExceptions and
+ JDOExceptions itself, preferably via delegating
+ to SessionFactoryUtils'
+ convertHibernateAccessException(..) or
+ convertJdoAccessException methods respectively.
+ These methods convert the exceptions to ones that are compatible
+ with the exceptions in the org.springframework.dao
+ exception hierarchy. As JDOExceptions are
+ unchecked, they can simply get thrown too, sacrificing generic DAO
+ abstraction in terms of exceptions though.
+
+
+ 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
+ DataAccessException hierarchy.)
+
+
+
+
+
+
+
+
+ Consistent abstract classes for DAO support
+
+ To make it easier to work with a variety of data access technologies
+ such as JDBC, JDO and Hibernate in a consistent way, Spring provides
+ a set of abstract DAO classes that one can extend.
+ These abstract classes have methods for providing the data source and
+ any other configuration settings that are specific to the relevant
+ data-access technology.
+
+
+
+
+ JdbcDaoSupport - superclass for JDBC data
+ access objects. Requires a DataSource
+ to be provided; in turn, this class provides a
+ JdbcTemplate instance initialized from the
+ supplied DataSource to subclasses.
+
+
+
+
+ HibernateDaoSupport - superclass for
+ Hibernate data access objects. Requires a
+ SessionFactory to be provided;
+ in turn, this class provides a
+ HibernateTemplate instance initialized
+ from the supplied SessionFactory
+ to subclasses. Can alternatively be initialized directly via a
+ HibernateTemplate, to reuse the latters
+ settings like SessionFactory,
+ flush mode, exception translator, and so forth.
+
+
+
+
+ JdoDaoSupport - super class for JDO data
+ access objects. Requires a
+ PersistenceManagerFactory
+ to be provided; in turn, this class provides a
+ JdoTemplate instance initialized from the
+ supplied PersistenceManagerFactory
+ to subclasses.
+
+
+
+
+ JpaDaoSupport - super class for JPA data
+ access objects. Requires a
+ EntityManagerFactory to be provided;
+ in turn, this class provides a JpaTemplate
+ instance initialized from the supplied
+ EntityManagerFactory to subclasses.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/dtd.xml b/spring-framework-reference/src/dtd.xml
new file mode 100644
index 00000000000..1108904986e
--- /dev/null
+++ b/spring-framework-reference/src/dtd.xml
@@ -0,0 +1,681 @@
+
+
+ spring-beans-2.0.dtd
+
+ <!--
+ Spring XML Beans DTD, version 2.0
+ Authors: Rod Johnson, Juergen Hoeller, Alef Arendsen, Colin Sampaleanu, Rob Harrop
+
+ This defines a simple and consistent way of creating a namespace
+ of JavaBeans objects, managed by a Spring BeanFactory, read by
+ XmlBeanDefinitionReader (with DefaultBeanDefinitionDocumentReader).
+
+ This document type is used by most Spring functionality, including
+ web application contexts, which are based on bean factories.
+
+ Each "bean" element in this document defines a JavaBean.
+ Typically the bean class is specified, along with JavaBean properties
+ and/or constructor arguments.
+
+ A bean instance can be a "singleton" (shared instance) or a "prototype"
+ (independent instance). Further scopes can be provided by extended
+ bean factories, for example in a web environment.
+
+ References among beans are supported, that is, setting a JavaBean property
+ or a constructor argument to refer to another bean in the same factory
+ (or an ancestor factory).
+
+ As alternative to bean references, "inner bean definitions" can be used.
+ Singleton flags of such inner bean definitions are effectively ignored:
+ Inner beans are typically anonymous prototypes.
+
+ There is also support for lists, sets, maps, and java.util.Properties
+ as bean property types or constructor argument types.
+
+ For simple purposes, this DTD is sufficient. As of Spring 2.0,
+ XSD-based bean definitions are supported as more powerful alternative.
+
+ XML documents that conform to this DTD should declare the following doctype:
+
+ <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
+ "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
+-->
+
+
+<!--
+ The document root. A document can contain bean definitions only,
+ imports only, or a mixture of both (typically with imports first).
+-->
+<!ELEMENT beans (
+ description?,
+ (import | alias | bean)*
+)>
+
+<!--
+ Default values for all bean definitions. Can be overridden at
+ the "bean" level. See those attribute definitions for details.
+-->
+<!ATTLIST beans default-lazy-init (true | false) "false">
+<!ATTLIST beans default-autowire (no | byName | byType | constructor | autodetect) "no">
+<!ATTLIST beans default-dependency-check (none | objects | simple | all) "none">
+<!ATTLIST beans default-init-method CDATA #IMPLIED>
+<!ATTLIST beans default-destroy-method CDATA #IMPLIED>
+<!ATTLIST beans default-merge (true | false) "false">
+
+<!--
+ Element containing informative text describing the purpose of the enclosing
+ element. Always optional.
+ Used primarily for user documentation of XML bean definition documents.
+-->
+<!ELEMENT description (#PCDATA)>
+
+
+<!--
+ Specifies an XML bean definition resource to import.
+-->
+<!ELEMENT import EMPTY>
+
+<!--
+ The relative resource location of the XML bean definition file to import,
+ for example "myImport.xml" or "includes/myImport.xml" or "../myImport.xml".
+-->
+<!ATTLIST import resource CDATA #REQUIRED>
+
+
+<!--
+ Defines an alias for a bean, which can reside in a different definition file.
+-->
+<!ELEMENT alias EMPTY>
+
+<!--
+ The name of the bean to define an alias for.
+-->
+<!ATTLIST alias name CDATA #REQUIRED>
+
+<!--
+ The alias name to define for the bean.
+-->
+<!ATTLIST alias alias CDATA #REQUIRED>
+
+<!--
+ Allows for arbitrary metadata to be attached to a bean definition.
+-->
+<!ELEMENT meta EMPTY>
+
+<!--
+ Specifies the key name of the metadata parameter being defined.
+-->
+<!ATTLIST meta key CDATA #REQUIRED>
+
+<!--
+ Specifies the value of the metadata parameter being defined as a String.
+-->
+<!ATTLIST meta value CDATA #REQUIRED>
+
+<!--
+ Defines a single (usually named) bean.
+
+ A bean definition may contain nested tags for constructor arguments,
+ property values, lookup methods, and replaced methods. Mixing constructor
+ injection and setter injection on the same bean is explicitly supported.
+-->
+<!ELEMENT bean (
+ description?,
+ (meta | constructor-arg | property | lookup-method | replaced-method)*
+)>
+
+<!--
+ Beans can be identified by an id, to enable reference checking.
+
+ There are constraints on a valid XML id: if you want to reference your bean
+ in Java code using a name that's illegal as an XML id, use the optional
+ "name" attribute. If neither is given, the bean class name is used as id
+ (with an appended counter like "#2" if there is already a bean with that name).
+-->
+<!ATTLIST bean id ID #IMPLIED>
+
+<!--
+ Optional. Can be used to create one or more aliases illegal in an id.
+ Multiple aliases can be separated by any number of spaces, commas, or
+ semi-colons (or indeed any mixture of the three).
+-->
+<!ATTLIST bean name CDATA #IMPLIED>
+
+<!--
+ Each bean definition must specify the fully qualified name of the class,
+ except if it pure serves as parent for child bean definitions.
+-->
+<!ATTLIST bean class CDATA #IMPLIED>
+
+<!--
+ Optionally specify a parent bean definition.
+
+ Will use the bean class of the parent if none specified, but can
+ also override it. In the latter case, the child bean class must be
+ compatible with the parent, i.e. accept the parent's property values
+ and constructor argument values, if any.
+
+ A child bean definition will inherit constructor argument values,
+ property values and method overrides from the parent, with the option
+ to add new values. If init method, destroy method, factory bean and/or factory
+ method are specified, they will override the corresponding parent settings.
+
+ The remaining settings will always be taken from the child definition:
+ depends on, autowire mode, dependency check, scope, lazy init.
+-->
+<!ATTLIST bean parent CDATA #IMPLIED>
+
+<!--
+ The scope of this bean: typically "singleton" (one shared instance,
+ which will be returned by all calls to getBean() with the id),
+ or "prototype" (independent instance resulting from each call to
+ getBean(). Default is "singleton".
+
+ Singletons are most commonly used, and are ideal for multi-threaded
+ service objects. Further scopes, such as "request" or "session",
+ might be supported by extended bean factories (for example, in a
+ web environment).
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+
+ Inner bean definitions inherit the singleton status of their containing
+ bean definition, unless explicitly specified: The inner bean will be a
+ singleton if the containing bean is a singleton, and a prototype if
+ the containing bean has any other scope.
+-->
+<!ATTLIST bean scope CDATA #IMPLIED>
+
+<!--
+ Is this bean "abstract", i.e. not meant to be instantiated itself but
+ rather just serving as parent for concrete child bean definitions.
+ Default is "false". Specify "true" to tell the bean factory to not try to
+ instantiate that particular bean in any case.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per abstract bean definition.
+-->
+<!ATTLIST bean abstract (true | false) #IMPLIED>
+
+<!--
+ If this bean should be lazily initialized.
+ If false, it will get instantiated on startup by bean factories
+ that perform eager initialization of singletons.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+-->
+<!ATTLIST bean lazy-init (true | false | default) "default">
+
+<!--
+ Indicates whether or not this bean should be considered when looking
+ for candidates to satisfy another beans autowiring requirements.
+-->
+<!ATTLIST bean autowire-candidate (true | false) #IMPLIED>
+
+<!--
+ Optional attribute controlling whether to "autowire" bean properties.
+ This is an automagical process in which bean references don't need to be coded
+ explicitly in the XML bean definition file, but Spring works out dependencies.
+
+ There are 5 modes:
+
+ 1. "no"
+ The traditional Spring default. No automagical wiring. Bean references
+ must be defined in the XML file via the <ref> element. We recommend this
+ in most cases as it makes documentation more explicit.
+
+ 2. "byName"
+ Autowiring by property name. If a bean of class Cat exposes a dog property,
+ Spring will try to set this to the value of the bean "dog" in the current factory.
+ If there is no matching bean by name, nothing special happens;
+ use dependency-check="objects" to raise an error in that case.
+
+ 3. "byType"
+ Autowiring if there is exactly one bean of the property type in the bean factory.
+ If there is more than one, a fatal error is raised, and you can't use byType
+ autowiring for that bean. If there is none, nothing special happens;
+ use dependency-check="objects" to raise an error in that case.
+
+ 4. "constructor"
+ Analogous to "byType" for constructor arguments. If there isn't exactly one bean
+ of the constructor argument type in the bean factory, a fatal error is raised.
+
+ 5. "autodetect"
+ Chooses "constructor" or "byType" through introspection of the bean class.
+ If a default constructor is found, "byType" gets applied.
+
+ The latter two are similar to PicoContainer and make bean factories simple to
+ configure for small namespaces, but doesn't work as well as standard Spring
+ behaviour for bigger applications.
+
+ Note that explicit dependencies, i.e. "property" and "constructor-arg" elements,
+ always override autowiring. Autowire behavior can be combined with dependency
+ checking, which will be performed after all autowiring has been completed.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+-->
+<!ATTLIST bean autowire (no | byName | byType | constructor | autodetect | default) "default">
+
+<!--
+ Optional attribute controlling whether to check whether all this
+ beans dependencies, expressed in its properties, are satisfied.
+ Default is no dependency checking.
+
+ "simple" type dependency checking includes primitives and String;
+ "objects" includes collaborators (other beans in the factory);
+ "all" includes both types of dependency checking.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+-->
+<!ATTLIST bean dependency-check (none | objects | simple | all | default) "default">
+
+<!--
+ The names of the beans that this bean depends on being initialized.
+ The bean factory will guarantee that these beans get initialized before.
+
+ Note that dependencies are normally expressed through bean properties or
+ constructor arguments. This property should just be necessary for other kinds
+ of dependencies like statics (*ugh*) or database preparation on startup.
+
+ Note: This attribute will not be inherited by child bean definitions.
+ Hence, it needs to be specified per concrete bean definition.
+-->
+<!ATTLIST bean depends-on CDATA #IMPLIED>
+
+<!--
+ Optional attribute for the name of the custom initialization method
+ to invoke after setting bean properties. The method must have no arguments,
+ but may throw any exception.
+-->
+<!ATTLIST bean init-method CDATA #IMPLIED>
+
+<!--
+ Optional attribute for the name of the custom destroy method to invoke
+ on bean factory shutdown. The method must have no arguments,
+ but may throw any exception.
+
+ Note: Only invoked on beans whose lifecycle is under full control
+ of the factory - which is always the case for singletons, but not
+ guaranteed for any other scope.
+-->
+<!ATTLIST bean destroy-method CDATA #IMPLIED>
+
+<!--
+ Optional attribute specifying the name of a factory method to use to
+ create this object. Use constructor-arg elements to specify arguments
+ to the factory method, if it takes arguments. Autowiring does not apply
+ to factory methods.
+
+ If the "class" attribute is present, the factory method will be a static
+ method on the class specified by the "class" attribute on this bean
+ definition. Often this will be the same class as that of the constructed
+ object - for example, when the factory method is used as an alternative
+ to a constructor. However, it may be on a different class. In that case,
+ the created object will *not* be of the class specified in the "class"
+ attribute. This is analogous to FactoryBean behavior.
+
+ If the "factory-bean" attribute is present, the "class" attribute is not
+ used, and the factory method will be an instance method on the object
+ returned from a getBean call with the specified bean name. The factory
+ bean may be defined as a singleton or a prototype.
+
+ The factory method can have any number of arguments. Autowiring is not
+ supported. Use indexed constructor-arg elements in conjunction with the
+ factory-method attribute.
+
+ Setter Injection can be used in conjunction with a factory method.
+ Method Injection cannot, as the factory method returns an instance,
+ which will be used when the container creates the bean.
+-->
+<!ATTLIST bean factory-method CDATA #IMPLIED>
+
+<!--
+ Alternative to class attribute for factory-method usage.
+ If this is specified, no class attribute should be used.
+ This should be set to the name of a bean in the current or
+ ancestor factories that contains the relevant factory method.
+ This allows the factory itself to be configured using Dependency
+ Injection, and an instance (rather than static) method to be used.
+-->
+<!ATTLIST bean factory-bean CDATA #IMPLIED>
+
+<!--
+ Bean definitions can specify zero or more constructor arguments.
+ This is an alternative to "autowire constructor".
+ Arguments correspond to either a specific index of the constructor argument
+ list or are supposed to be matched generically by type.
+
+ Note: A single generic argument value will just be used once, rather than
+ potentially matched multiple times (as of Spring 1.1).
+
+ constructor-arg elements are also used in conjunction with the factory-method
+ element to construct beans using static or instance factory methods.
+-->
+<!ELEMENT constructor-arg (
+ description?,
+ (bean | ref | idref | value | null | list | set | map | props)?
+)>
+
+<!--
+ The constructor-arg tag can have an optional index attribute,
+ to specify the exact index in the constructor argument list. Only needed
+ to avoid ambiguities, e.g. in case of 2 arguments of the same type.
+-->
+<!ATTLIST constructor-arg index CDATA #IMPLIED>
+
+<!--
+ The constructor-arg tag can have an optional type attribute,
+ to specify the exact type of the constructor argument. Only needed
+ to avoid ambiguities, e.g. in case of 2 single argument constructors
+ that can both be converted from a String.
+-->
+<!ATTLIST constructor-arg type CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a child element "ref bean=".
+-->
+<!ATTLIST constructor-arg ref CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a child element "value".
+-->
+<!ATTLIST constructor-arg value CDATA #IMPLIED>
+
+
+<!--
+ Bean definitions can have zero or more properties.
+ Property elements correspond to JavaBean setter methods exposed
+ by the bean classes. Spring supports primitives, references to other
+ beans in the same or related factories, lists, maps and properties.
+-->
+<!ELEMENT property (
+ description?, meta*,
+ (bean | ref | idref | value | null | list | set | map | props)?
+)>
+
+<!--
+ The property name attribute is the name of the JavaBean property.
+ This follows JavaBean conventions: a name of "age" would correspond
+ to setAge()/optional getAge() methods.
+-->
+<!ATTLIST property name CDATA #REQUIRED>
+
+<!--
+ A short-cut alternative to a child element "ref bean=".
+-->
+<!ATTLIST property ref CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a child element "value".
+-->
+<!ATTLIST property value CDATA #IMPLIED>
+
+
+<!--
+ A lookup method causes the IoC container to override the given method and return
+ the bean with the name given in the bean attribute. This is a form of Method Injection.
+ It's particularly useful as an alternative to implementing the BeanFactoryAware
+ interface, in order to be able to make getBean() calls for non-singleton instances
+ at runtime. In this case, Method Injection is a less invasive alternative.
+-->
+<!ELEMENT lookup-method EMPTY>
+
+<!--
+ Name of a lookup method. This method should take no arguments.
+-->
+<!ATTLIST lookup-method name CDATA #IMPLIED>
+
+<!--
+ Name of the bean in the current or ancestor factories that the lookup method
+ should resolve to. Often this bean will be a prototype, in which case the
+ lookup method will return a distinct instance on every invocation. This
+ is useful for single-threaded objects.
+-->
+<!ATTLIST lookup-method bean CDATA #IMPLIED>
+
+
+<!--
+ Similar to the lookup method mechanism, the replaced-method element is used to control
+ IoC container method overriding: Method Injection. This mechanism allows the overriding
+ of a method with arbitrary code.
+-->
+<!ELEMENT replaced-method (
+ (arg-type)*
+)>
+
+<!--
+ Name of the method whose implementation should be replaced by the IoC container.
+ If this method is not overloaded, there's no need to use arg-type subelements.
+ If this method is overloaded, arg-type subelements must be used for all
+ override definitions for the method.
+-->
+<!ATTLIST replaced-method name CDATA #IMPLIED>
+
+<!--
+ Bean name of an implementation of the MethodReplacer interface in the current
+ or ancestor factories. This may be a singleton or prototype bean. If it's
+ a prototype, a new instance will be used for each method replacement.
+ Singleton usage is the norm.
+-->
+<!ATTLIST replaced-method replacer CDATA #IMPLIED>
+
+<!--
+ Subelement of replaced-method identifying an argument for a replaced method
+ in the event of method overloading.
+-->
+<!ELEMENT arg-type (#PCDATA)>
+
+<!--
+ Specification of the type of an overloaded method argument as a String.
+ For convenience, this may be a substring of the FQN. E.g. all the
+ following would match "java.lang.String":
+ - java.lang.String
+ - String
+ - Str
+
+ As the number of arguments will be checked also, this convenience can often
+ be used to save typing.
+-->
+<!ATTLIST arg-type match CDATA #IMPLIED>
+
+
+<!--
+ Defines a reference to another bean in this factory or an external
+ factory (parent or included factory).
+-->
+<!ELEMENT ref EMPTY>
+
+<!--
+ References must specify a name of the target bean.
+ The "bean" attribute can reference any name from any bean in the context,
+ to be checked at runtime.
+ Local references, using the "local" attribute, have to use bean ids;
+ they can be checked by this DTD, thus should be preferred for references
+ within the same bean factory XML file.
+-->
+<!ATTLIST ref bean CDATA #IMPLIED>
+<!ATTLIST ref local IDREF #IMPLIED>
+<!ATTLIST ref parent CDATA #IMPLIED>
+
+
+<!--
+ Defines a string property value, which must also be the id of another
+ bean in this factory or an external factory (parent or included factory).
+ While a regular 'value' element could instead be used for the same effect,
+ using idref in this case allows validation of local bean ids by the XML
+ parser, and name completion by supporting tools.
+-->
+<!ELEMENT idref EMPTY>
+
+<!--
+ ID refs must specify a name of the target bean.
+ The "bean" attribute can reference any name from any bean in the context,
+ potentially to be checked at runtime by bean factory implementations.
+ Local references, using the "local" attribute, have to use bean ids;
+ they can be checked by this DTD, thus should be preferred for references
+ within the same bean factory XML file.
+-->
+<!ATTLIST idref bean CDATA #IMPLIED>
+<!ATTLIST idref local IDREF #IMPLIED>
+
+
+<!--
+ Contains a string representation of a property value.
+ The property may be a string, or may be converted to the required
+ type using the JavaBeans PropertyEditor machinery. This makes it
+ possible for application developers to write custom PropertyEditor
+ implementations that can convert strings to arbitrary target objects.
+
+ Note that this is recommended for simple objects only.
+ Configure more complex objects by populating JavaBean
+ properties with references to other beans.
+-->
+<!ELEMENT value (#PCDATA)>
+
+<!--
+ The value tag can have an optional type attribute, to specify the
+ exact type that the value should be converted to. Only needed
+ if the type of the target property or constructor argument is
+ too generic: for example, in case of a collection element.
+-->
+<!ATTLIST value type CDATA #IMPLIED>
+
+<!--
+ Denotes a Java null value. Necessary because an empty "value" tag
+ will resolve to an empty String, which will not be resolved to a
+ null value unless a special PropertyEditor does so.
+-->
+<!ELEMENT null (#PCDATA)>
+
+
+<!--
+ A list can contain multiple inner bean, ref, collection, or value elements.
+ Java lists are untyped, pending generics support in Java 1.5,
+ although references will be strongly typed.
+ A list can also map to an array type. The necessary conversion
+ is automatically performed by the BeanFactory.
+-->
+<!ELEMENT list (
+ (bean | ref | idref | value | null | list | set | map | props)*
+)>
+
+<!--
+ Enable/disable merging for collections when using parent/child beans.
+-->
+<!ATTLIST list merge (true | false | default) "default">
+
+<!--
+ Specify the default Java type for nested values.
+-->
+<!ATTLIST list value-type CDATA #IMPLIED>
+
+
+<!--
+ A set can contain multiple inner bean, ref, collection, or value elements.
+ Java sets are untyped, pending generics support in Java 1.5,
+ although references will be strongly typed.
+-->
+<!ELEMENT set (
+ (bean | ref | idref | value | null | list | set | map | props)*
+)>
+
+<!--
+ Enable/disable merging for collections when using parent/child beans.
+-->
+<!ATTLIST set merge (true | false | default) "default">
+
+<!--
+ Specify the default Java type for nested values.
+-->
+<!ATTLIST set value-type CDATA #IMPLIED>
+
+
+<!--
+ A Spring map is a mapping from a string key to object.
+ Maps may be empty.
+-->
+<!ELEMENT map (
+ (entry)*
+)>
+
+<!--
+ Enable/disable merging for collections when using parent/child beans.
+-->
+<!ATTLIST map merge (true | false | default) "default">
+
+<!--
+ Specify the default Java type for nested entry keys.
+-->
+<!ATTLIST map key-type CDATA #IMPLIED>
+
+<!--
+ Specify the default Java type for nested entry values.
+-->
+<!ATTLIST map value-type CDATA #IMPLIED>
+
+<!--
+ A map entry can be an inner bean, ref, value, or collection.
+ The key of the entry is given by the "key" attribute or child element.
+-->
+<!ELEMENT entry (
+ key?,
+ (bean | ref | idref | value | null | list | set | map | props)?
+)>
+
+<!--
+ Each map element must specify its key as attribute or as child element.
+ A key attribute is always a String value.
+-->
+<!ATTLIST entry key CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a "key" element with a "ref bean=" child element.
+-->
+<!ATTLIST entry key-ref CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a child element "value".
+-->
+<!ATTLIST entry value CDATA #IMPLIED>
+
+<!--
+ A short-cut alternative to a child element "ref bean=".
+-->
+<!ATTLIST entry value-ref CDATA #IMPLIED>
+
+<!--
+ A key element can contain an inner bean, ref, value, or collection.
+-->
+<!ELEMENT key (
+ (bean | ref | idref | value | null | list | set | map | props)
+)>
+
+
+<!--
+ Props elements differ from map elements in that values must be strings.
+ Props may be empty.
+-->
+<!ELEMENT props (
+ (prop)*
+)>
+
+<!--
+ Enable/disable merging for collections when using parent/child beans.
+-->
+<!ATTLIST props merge (true | false | default) "default">
+
+<!--
+ Element content is the string value of the property.
+ Note that whitespace is trimmed off to avoid unwanted whitespace
+ caused by typical XML formatting.
+-->
+<!ELEMENT prop (#PCDATA)>
+
+<!--
+ Each property element must specify its key.
+-->
+<!ATTLIST prop key CDATA #REQUIRED>
+
diff --git a/spring-framework-reference/src/dynamic-languages.xml b/spring-framework-reference/src/dynamic-languages.xml
new file mode 100644
index 00000000000..e03c62bca3b
--- /dev/null
+++ b/spring-framework-reference/src/dynamic-languages.xml
@@ -0,0 +1,1090 @@
+
+
+ Dynamic language support
+
+
+ Introduction
+
+ Why only these languages?
+
+ The supported languages were chosen because a) the languages
+ have a lot of traction in the Java enterprise community, b) no requests were made
+ for other languages within the Spring 2.0 development timeframe, and
+ c) the Spring developers were most familiar with them.
+
+
+ There is nothing stopping the inclusion of further languages though. If you want
+ to see support for <insert your favourite dynamic language here>,
+ you can always raise an issue on Spring's
+ JIRA
+ page (or implement such support yourself).
+
+
+ Spring 2.0 introduces comprehensive support for using classes and objects that have
+ been defined using a dynamic language (such as JRuby) with Spring.
+ This support allows you to write any number of classes in a supported dynamic language,
+ and have the Spring container transparently instantiate, configure and dependency inject the
+ resulting objects.
+ The dynamic languages currently supported are:
+
+
+ JRuby 0.9 / 1.0
+
+
+ Groovy 1.0 / 1.5
+
+
+ BeanShell 2.0
+
+
+
+ Fully working examples of where this dynamic language support can be immediately useful
+ are described in the section entitled .
+
+
+ Note: Only the specific versions as listed above are supported
+ in Spring 2.5. In particular, JRuby 1.1 (which introduced many incompatible API
+ changes) is not supported at this point of time.
+
+
+
+
+ A first example
+
+ This bulk of this chapter is concerned with describing the dynamic language support
+ in detail. Before diving into all of the ins and outs of the dynamic language support,
+ let's look at a quick example of a bean defined in a dynamic language.
+ The dynamic language for this first bean is Groovy (the basis of this example
+ was taken from the Spring test suite, so if you want to see equivalent examples
+ in any of the other supported languages, take a look at the source code).
+
+
+ Find below the Messenger interface that the
+ Groovy bean is going to be implementing, and note that this interface is defined
+ in plain Java. Dependent objects that are injected with a reference to the
+ Messenger won't know that the underlying
+ implementation is a Groovy script.
+
+
+
+ Here is the definition of a class that has a dependency on the
+ Messenger interface.
+
+
+ Here is an implementation of the Messenger interface
+ in Groovy.
+
+
+ Finally, here are the bean definitions that will effect the injection of the
+ Groovy-defined Messenger implementation into
+ an instance of the DefaultBookingService class.
+
+
+
+ To use the custom dynamic language tags to define dynamic-language-backed beans,
+ you need to have the XML Schema preamble at the top of your Spring XML
+ configuration file. You also need to be using a Spring
+ ApplicationContext implementation as your
+ IoC container. Using the dynamic-language-backed beans with a plain
+ BeanFactory implementation is supported,
+ but you have to manage the plumbing of the Spring internals to do so.
+
+ For more information on schema-based configuration, see .
+
+
+
+
+ ]]><!-- this is the bean definition for the Groovy-backed Messenger implementation -->
+
+
+
+ ]]><!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger -->
+
+
+
+]]>
+
+ The bookingService bean (a
+ DefaultBookingService) can now use its private
+ messenger member variable as normal because the
+ Messenger instance that was injected
+ into it is a Messenger
+ instance. There is nothing special going on here, just plain Java and
+ plain Groovy.
+
+
+ Hopefully the above XML snippet is self-explanatory, but don't worry
+ unduly if it isn't. Keep reading for the in-depth detail on the whys
+ and wherefores of the above configuration.
+
+
+
+
+ Defining beans that are backed by dynamic languages
+
+ This section describes exactly how you define Spring managed beans in
+ any of the supported dynamic languages.
+
+
+ Please note that this chapter does not attempt to explain the syntax and
+ idioms of the supported dynamic languages. For example, if you want to
+ use Groovy to write certain of the classes in your application, then the
+ assumption is that you already know Groovy. If you need further details
+ about the dynamic languages themselves, please consult the section
+ entitled at the end of this chapter.
+
+
+
+ Common concepts
+ The steps involved in using dynamic-language-backed beans are as follows:
+
+
+ Write the test for the dynamic language source code (naturally)
+
+
+ Then write the dynamic language source code itself :)
+
+
+
+ Define your dynamic-language-backed beans using the appropriate
+ <lang:language/> element in the XML
+ configuration (you can of course define such beans programmatically
+ using the Spring API - although you will have to consult the source
+ code for directions on how to do this as this type of advanced
+ configuration is not covered in this chapter). Note this is an iterative
+ step. You will need at least one bean definition per dynamic
+ language source file (although the same dynamic language source
+ file can of course be referenced by multiple bean definitions).
+
+
+
+
+ The first two steps (testing and writing your dynamic language source files)
+ are beyond the scope of this chapter. Refer to the language specification
+ and / or reference manual for your chosen dynamic language and crack on with
+ developing your dynamic language source files. You will
+ first want to read the rest of this chapter though, as Spring's dynamic language
+ support does make some (small) assumptions about the contents of your dynamic
+ language source files.
+
+
+
+ The <lang:language/> element
+
+ XML Schema
+
+ All of the configuration examples in this chapter make use of the
+ new XML Schema support that was added in Spring 2.0.
+
+ It is possible to forego the use of XML Schema and stick with the old-style
+ DTD based validation of your Spring XML files, but then you lose out
+ on the convenience offered by the <lang:language/>
+ element. See the Spring test suite for examples of the older style
+ configuration that doesn't require XML Schema-based validation
+ (it is quite verbose and doesn't hide any of the underlying Spring
+ implementation from you).
+
+
+ The final step involves defining dynamic-language-backed bean definitions,
+ one for each bean that you want to configure (this is no different to
+ normal Java bean configuration). However, instead of specifying the
+ fully qualified classname of the class that is to be instantiated and
+ configured by the container, you use the <lang:language/>
+ element to define the dynamic language-backed bean.
+
+
+ Each of the supported languages has a corresponding
+ <lang:language/> element:
+
+
+
+ <lang:jruby/> (JRuby)
+
+
+ <lang:groovy/> (Groovy)
+
+
+ <lang:bsh/> (BeanShell)
+
+
+
+ The exact attributes and child elements that are available for
+ configuration depends on exactly which language the bean has been
+ defined in (the language-specific sections below provide the full
+ lowdown on this).
+
+
+
+
+ Refreshable beans
+
+ One of the (if not the) most compelling value adds
+ of the dynamic language support in Spring is the
+ 'refreshable bean' feature.
+
+
+ A refreshable bean is a dynamic-language-backed bean that with a small
+ amount of configuration, a dynamic-language-backed bean can monitor
+ changes in its underlying source file resource, and then reload itself
+ when the dynamic language source file is changed (for example when a
+ developer edits and saves changes to the file on the filesystem).
+
+
+ This allows a developer to deploy any number of dynamic language source
+ files as part of an application, configure the Spring container to create
+ beans backed by dynamic language source files (using the mechanisms
+ described in this chapter), and then later, as requirements change or
+ some other external factor comes into play, simply edit a dynamic language
+ source file and have any change they make reflected in the bean that is
+ backed by the changed dynamic language source file. There is no need to
+ shut down a running application (or redeploy in the case of a web application).
+ The dynamic-language-backed bean so amended will pick up the new state
+ and logic from the changed dynamic language source file.
+
+
+ Please note that this feature is off by default.
+
+
+ Let's take a look at an example to see just how easy it is to start using
+ refreshable beans. To turn on the refreshable beans
+ feature, you simply have to specify exactly one
+ additional attribute on the <lang:language/> element
+ of your bean definition. So if we stick with
+ the example from earlier
+ in this chapter, here's what we would change in the Spring XML configuration
+ to effect refreshable beans:
+
+
+
+ ]]><!-- this bean is now 'refreshable' due to the presence of the 'refresh-check-delay' attribute --><!-- switches refreshing on with 5 seconds between checks -->
+
+
+
+
+
+
+
+]]>
+
+ That really is all you have to do. The 'refresh-check-delay'
+ attribute defined on the 'messenger' bean definition
+ is the number of milliseconds after which the bean will be refreshed with
+ any changes made to the underlying dynamic language source file.
+ You can turn off the refresh behavior by assigning a negative value
+ to the 'refresh-check-delay' attribute.
+ Remember that, by default, the refresh behavior is disabled. If you don't
+ want the refresh behavior, then simply don't define the attribute.
+
+
+ If we then run the following application we can exercise the refreshable feature;
+ please do excuse the 'jumping-through-hoops-to-pause-the-execution'
+ shenanigans in this next slice of code. The System.in.read()
+ call is only there so that the execution of the program pauses while I (the author)
+ go off and edit the underlying dynamic language source file so that the refresh will
+ trigger on the dynamic-language-backed bean when the program resumes execution.
+
+
+ Let's assume then, for the purposes of this example, that all
+ calls to the getMessage() method of
+ Messenger implementations have to be
+ changed such that the message is surrounded by quotes.
+ Below are the changes that I (the author) make to the
+ Messenger.groovy source file when the execution of
+ the program is paused.
+
+
+
+ When the program executes, the output before the input pause will be
+ I Can Do The Frug. After the change
+ to the source file is made and saved, and the program resumes execution,
+ the result of calling the getMessage() method on the
+ dynamic-language-backed Messenger implementation
+ will be 'I Can Do The Frug' (notice
+ the inclusion of the additional quotes).
+
+
+ It is important to understand that changes to a script will
+ not trigger a refresh if the changes occur
+ within the window of the 'refresh-check-delay' value.
+ It is equally important to understand that changes to the script are
+ not actually 'picked up' until a method is called
+ on the dynamic-language-backed bean. It is only when a method is called on a
+ dynamic-language-backed bean that it checks to see if its underlying script
+ source has changed. Any exceptions relating to refreshing the script
+ (such as encountering a compilation error, or finding that the script
+ file has been deleted) will result in a fatal
+ exception being propagated to the calling code.
+
+
+ The refreshable bean behavior described above does
+ not apply to dynamic language source files
+ defined using the <lang:inline-script/> element
+ notation (see the section entitled ).
+ Additionally, it only applies to beans where
+ changes to the underlying source file can actually be detected;
+ for example, by code that checks the last modified date of a
+ dynamic language source file that exists on the filesystem.
+
+
+
+
+ Inline dynamic language source files
+
+ The dynamic language support can also cater for dynamic language
+ source files that are embedded directly in Spring bean definitions.
+ More specifically, the <lang:inline-script/>
+ element allows you to define dynamic language source immediately
+ inside a Spring configuration file. An example will perhaps make the
+ inline script feature crystal clear:
+
+
+
+package org.springframework.scripting.groovy;
+
+import org.springframework.scripting.Messenger
+
+class GroovyMessenger implements Messenger {
+
+ String message
+}
+
+
+]]>
+
+ If we put to one side the issues surrounding whether it is good practice
+ to define dynamic language source inside a Spring configuration file, the
+ <lang:inline-script/> element can be useful in
+ some scenarios. For instance, we might want to quickly add a Spring
+ Validator implementation to a Spring MVC
+ Controller. This is but a moment's work
+ using inline source. (See the section entitled
+ for such an example.)
+
+
+ Find below an example of defining the source for a JRuby-based bean
+ directly in a Spring XML configuration file using the
+ inline: notation. (Notice the use of the
+ characters to denote a '<' character. In such a case
+ surrounding the inline source in a <![CDATA[]]> region might be better.)
+
+
+
+require 'java'
+
+include_class 'org.springframework.scripting.Messenger'
+
+class RubyMessenger < Messenger
+
+ def setMessage(message)
+ @@message = message
+ end
+
+ def getMessage
+ @@message
+ end
+
+end
+
+
+]]>
+
+
+
+ Understanding Constructor Injection in the context of dynamic-language-backed beans
+
+ There is one very important thing to be aware of
+ with regard to Spring's dynamic language support. Namely, it is not (currently)
+ possible to supply constructor arguments to dynamic-language-backed beans (and hence
+ constructor-injection is not available for dynamic-language-backed beans).
+ In the interests of making this special handling of constructors and
+ properties 100% clear, the following mixture of code and configuration
+ will not work.
+
+
+
+]]>
+ <!-- this next constructor argument will *not* be injected into the GroovyMessenger -->
+ <!-- in fact, this isn't even allowed according to the schema -->This will *not* work]]>
+
+ <!-- only property values are injected into the dynamic-language-backed object -->
+
+]]>
+
+ In practice this limitation is not as significant as it first appears since
+ setter injection is the injection style favored by the overwhelming majority
+ of developers anyway (let's leave the discussion as to whether that is a good
+ thing to another day).
+
+
+
+
+
+ JRuby beans
+
+
+ The JRuby library dependencies
+
+ The JRuby scripting support in Spring requires the following
+ libraries to be on the classpath of your application.
+ (The versions listed just happen to be the versions that the
+ Spring team used in the development of the JRuby scripting support;
+ you may well be able to use another version of a specific library.)
+
+
+
+ jruby.jar
+
+
+ cglib-nodep-2.1_3.jar
+
+
+
+ From the JRuby homepage...
+
+ JRuby is an 100% pure-Java implementation of the Ruby programming language.
+
+
+ In keeping with the Spring philosophy of offering choice, Spring's
+ dynamic language support also supports beans defined in the JRuby
+ language. The JRuby language is based on the quite intuitive
+ Ruby language, and has support for inline regular expressions, blocks
+ (closures), and a whole host of other features that do make solutions
+ for some domain problems a whole lot easier to develop.
+
+
+ The implementation of the JRuby dynamic language support in Spring is
+ interesting in that what happens is this: Spring creates a JDK dynamic
+ proxy implementing all of the interfaces that are specified in the
+ 'script-interfaces' attribute value of the
+ <lang:ruby> element (this is why
+ you must supply at least one interface in the value
+ of the attribute, and (accordingly) program to interfaces when using
+ JRuby-backed beans).
+
+
+ Let us look at a fully working example of using a JRuby-based bean. Here is
+ the JRuby implementation of the Messenger
+ interface that was defined earlier in this chapter (for your convenience it
+ is repeated below).
+
+
+
+
+ And here is the Spring XML that defines an instance of the
+ RubyMessenger JRuby bean.
+
+
+
+
+
+]]>
+
+ Take note of the last line of that JRuby source ('RubyMessenger.new').
+ When using JRuby in the context of Spring's dynamic language support, you are encouraged
+ to instantiate and return a new instance of the JRuby class that you want to use as a
+ dynamic-language-backed bean as the result of the execution of your JRuby source. You
+ can achieve this by simply instantiating a new instance of your JRuby class on the last
+ line of the source file like so:
+
+
+
+ If you forget to do this, it is not the end of the world; this will however result in
+ Spring having to trawl (reflectively) through the type representation of your JRuby class
+ looking for a class to instantiate. In the grand scheme of things this will be so fast
+ that you'll never notice it, but it is something that can be avoided by simply
+ having a line such as the one above as the last line of your JRuby script. If you don't
+ supply such a line, or if Spring cannot find a JRuby class in your script to instantiate
+ then an opaque ScriptCompilationException
+ will be thrown immediately after the source is executed by the JRuby
+ interpreter. The key text that identifies this as the root cause of an
+ exception can be found immediately below (so if your Spring container
+ throws the following exception when creating your dynamic-language-backed bean
+ and the following text is there in the corresponding stacktrace, this will hopefully
+ allow you to identify and then easily rectify the issue):
+
+
+
+ To rectify this, simply instantiate a new instance of whichever class
+ you want to expose as a JRuby-dynamic-language-backed bean (as shown above). Please
+ also note that you can actually define as many classes and objects
+ as you want in your JRuby script; what is important is that the
+ source file as a whole must return an object (for Spring to configure).
+
+
+ See the section entitled for some
+ scenarios where you might want to use JRuby-based beans.
+
+
+
+
+ Groovy beans
+
+ The Groovy library dependencies
+
+ The Groovy scripting support in Spring requires the following
+ libraries to be on the classpath of your application.
+
+
+
+ groovy-1.5.5.jar
+
+
+ asm-2.2.2.jar
+
+
+ antlr-2.7.6.jar
+
+
+
+ From the Groovy homepage...
+
+ Groovy is an agile dynamic language for the Java 2 Platform that has
+ many of the features that people like so much in languages like Python, Ruby
+ and Smalltalk, making them available to Java developers using a Java-like syntax.
+
+
+
+ If you have read this chapter straight from the top, you will already have
+ seen an example of a
+ Groovy-dynamic-language-backed bean. Let's look at another example (again
+ using an example from the Spring test suite).
+
+
+
+ Here is an implementation of the Calculator
+ interface in Groovy.
+
+ // from the file 'calculator.groovy'
+ <-- from the file 'beans.xml' -->
+
+]]>
+
+ Lastly, here is a small application to exercise the above configuration.
+
+
+
+ The resulting output from running the above program will be
+ (unsurprisingly) 10.
+ (Exciting example, huh? Remember that the intent is to illustrate the
+ concept. Please consult the dynamic language showcase project for a
+ more complex example, or indeed the section entitled
+ later in this chapter).
+
+
+ It is important that you do not define more than one
+ class per Groovy source file. While this is perfectly legal in Groovy, it
+ is (arguably) a bad practice: in the interests of a consistent approach,
+ you should (in the opinion of this author) respect the standard Java
+ conventions of one (public) class per source file.
+
+
+
+ Customising Groovy objects via a callback
+
+ The GroovyObjectCustomizer
+ interface is a callback that allows you to hook additional
+ creation logic into the process of creating a Groovy-backed bean.
+ For example, implementations of this interface could invoke
+ any required initialization method(s), or set some default property
+ values, or specify a custom MetaClass.
+
+
+
+ The Spring Framework will instantiate an instance of your Groovy-backed
+ bean, and will then pass the created GroovyObject
+ to the specified GroovyObjectCustomizer
+ if one has been defined. You can do whatever you like with the supplied
+ GroovyObject reference: it is expected
+ that the setting of a custom MetaClass is what most
+ folks will want to do with this callback, and you can see an example
+ of doing that below.
+
+
+
+ A full discussion of meta-programming in Groovy is beyond the scope of the
+ Spring reference manual. Consult the relevant section of the Groovy
+ reference manual, or do a search online: there are plenty of articles
+ concerning this topic.
+ Actually making use of a GroovyObjectCustomizer
+ is easy if you are using the Spring 2.0 namespace support.
+
+ <!-- define the GroovyObjectCustomizer just like any other bean -->
+
+
+ ]]><!-- ... and plug it into the desired Groovy bean via the 'customizer-ref' attribute -->]]>
+
+ If you are not using the Spring 2.0 namespace support, you can still
+ use the GroovyObjectCustomizer functionality.
+
+
+
+ ]]><!-- define the GroovyObjectCustomizer (as an inner bean) -->
+
+
+
+
+]]>
+
+
+
+
+ BeanShell beans
+
+ The BeanShell library dependencies
+
+ The BeanShell scripting support in Spring requires the following
+ libraries to be on the classpath of your application.
+
+
+
+ bsh-2.0b4.jar
+
+
+ cglib-nodep-2.1_3.jar
+
+
+
+ All of these libraries are available in the Spring-with-dependencies
+ distribution of Spring (in addition to also being freely available
+ on the web).
+
+
+ From the BeanShell homepage...
+
+ BeanShell is a small, free, embeddable Java source interpreter
+ with dynamic language features, written in Java. BeanShell dynamically
+ executes standard Java syntax and extends it with common scripting
+ conveniences such as loose types, commands, and method closures like those
+ in Perl and JavaScript.
+
+
+ In contrast to Groovy, BeanShell-backed bean definitions require some (small)
+ additional configuration. The implementation of the BeanShell dynamic language
+ support in Spring is interesting in that what happens is this: Spring creates
+ a JDK dynamic proxy implementing all of the interfaces that are specified in the
+ 'script-interfaces' attribute value of the
+ <lang:bsh> element (this is why
+ you must supply at least one interface in the value
+ of the attribute, and (accordingly) program to interfaces when using
+ BeanShell-backed beans). This means that every method call on a BeanShell-backed
+ object is going through the JDK dynamic proxy invocation mechanism.
+
+
+ Let's look at a fully working example of using a BeanShell-based bean
+ that implements the Messenger interface
+ that was defined earlier in this chapter (repeated below for your
+ convenience).
+
+
+ Here is the BeanShell 'implementation' (the term is used loosely here) of the
+ Messenger interface.
+
+
+ And here is the Spring XML that defines an 'instance' of the above 'class'
+ (again, the term is used very loosely here).
+
+
+
+
+]]>
+ See the section entitled for some
+ scenarios where you might want to use BeanShell-based beans.
+
+
+
+
+ Scenarios
+
+ The possible scenarios where defining Spring managed beans in a scripting
+ language would be beneficial are, of course, many and varied. This section
+ describes two possible use cases for the dynamic language support in Spring.
+
+
+
+ Scripted Spring MVC Controllers
+
+ One group of classes that may benefit from using dynamic-language-backed
+ beans is that of Spring MVC controllers. In pure Spring MVC applications,
+ the navigational flow through a web application is to a large extent
+ determined by code encapsulated within your Spring MVC controllers.
+ As the navigational flow and other presentation layer logic of a web
+ application needs to be updated to respond to support issues or changing
+ business requirements, it may well be easier to effect any such required
+ changes by editing one or more dynamic language source files and seeing
+ those changes being immediately reflected in the state of a running
+ application.
+
+
+ Remember that in the lightweight architectural model espoused by projects
+ such as Spring, you are typically aiming to have a really
+ thin presentation layer, with all the meaty business
+ logic of an application being contained in the domain and service layer
+ classes. Developing Spring MVC controllers as dynamic-language-backed beans
+ allows you to change presentation layer logic by simply editing and saving
+ text files; any changes to such dynamic language source files will (depending
+ on the configuration) automatically be reflected in the beans that are backed
+ by dynamic language source files.
+
+
+
+ In order to effect this automatic 'pickup' of any changes
+ to dynamic-language-backed beans, you will have had to enable the
+ 'refreshable beans' functionality. See the section entitle
+ for a full treatment
+ of this feature.
+
+
+
+ Find below an example of an
+ org.springframework.web.servlet.mvc.Controller
+ implemented using the Groovy dynamic language.
+
+
+
+
+
+]]>
+
+
+
+ Scripted Validators
+
+ Another area of application development with Spring that may benefit
+ from the flexibility afforded by dynamic-language-backed beans is that of
+ validation. It may be easier to express complex validation
+ logic using a loosely typed dynamic language (that may also have support
+ for inline regular expressions) as opposed to regular Java.
+
+
+ Again, developing validators as dynamic-language-backed beans allows you to change
+ validation logic by simply editing and saving a simple text file; any such
+ changes will (depending on the configuration) automatically be reflected
+ in the execution of a running application and would not require the restart
+ of an application.
+
+
+
+ Please note that in order to effect the automatic 'pickup' of any changes
+ to dynamic-language-backed beans, you will have had to enable the
+ 'refreshable beans' feature. See the section entitled
+ for a full and
+ detailed treatment of this feature.
+
+
+
+ Find below an example of a Spring
+ org.springframework.validation.Validator
+ implemented using the Groovy dynamic language. (See the section entitled
+ for a discussion of the
+ Validator interface.)
+
+ 0) {
+ return
+ }
+ errors.reject("whitespace", "Cannot be composed wholly of whitespace.")
+ }
+}]]>
+
+
+
+
+ Bits and bobs
+
+ This last section contains some bits and bobs related to the dynamic language
+ support.
+
+
+
+ AOP - advising scripted beans
+
+ It is possible to use the Spring AOP framework to advise scripted beans.
+ The Spring AOP framework actually is unaware that a bean that is being
+ advised might be a scripted bean, so all of the AOP use cases and functionality
+ that you may be using or aim to use will work with scripted beans. There is
+ just one (small) thing that you need to be aware of when advising scripted
+ beans... you cannot use class-based proxies, you must use
+ interface-based proxies.
+
+
+ You are of course not just limited to advising scripted beans... you can
+ also write aspects themselves in a supported dynamic language and use such
+ beans to advise other Spring beans. This really would be an advanced use of
+ the dynamic language support though.
+
+
+
+
+ Scoping
+
+ In case it is not immediately obvious, scripted beans can of course be scoped
+ just like any other bean. The scope attribute on the
+ various <lang:language/> elements allows you to
+ control the scope of the underlying scripted bean, just as it does with a
+ regular bean. (The default scope is
+ singleton, just as it
+ is with 'regular' beans.)
+
+
+ Find below an example of using the scope attribute
+ to define a Groovy bean scoped as a
+ prototype.
+
+
+
+
+ scope="prototype"
+
+
+
+
+
+
+
+]]>
+
+ See the section entitled in
+ for a fuller discussion of the scoping support in the Spring Framework.
+
+
+
+
+
+ Further Resources
+
+ Find below links to further resources about the various dynamic languages described
+ in this chapter.
+
+
+
+ The JRuby homepage
+
+
+ The Groovy homepage
+
+
+ The BeanShell homepage
+
+
+
+ Some of the more active members of the Spring community have also added support for
+ a number of additional dynamic languages above and beyond the ones covered in this
+ chapter. While it is possible that such third party contributions may be added to the
+ list of languages supported by the main Spring distribution, your best bet for seeing
+ if your favourite scripting language is supported is the
+ Spring Modules project.
+
+
+
+
diff --git a/spring-framework-reference/src/ejb.xml b/spring-framework-reference/src/ejb.xml
new file mode 100644
index 00000000000..0a3d7244829
--- /dev/null
+++ b/spring-framework-reference/src/ejb.xml
@@ -0,0 +1,432 @@
+
+
+ Enterprise Java Beans (EJB) integration
+
+
+ Introduction
+
+ 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.
+
+
+ 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.
+
+
+ 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.
+
+
+
+
+ Accessing EJBs
+
+
+ Concepts
+
+ 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.
+
+
+ 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:
+
+
+
+
+ Typically code using EJBs depends on Service Locator or
+ Business Delegate singletons, making it hard to test.
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+ Accessing local SLSBs
+
+ Assume that we have a web controller that needs to use a local
+ EJB. We’ll follow best practice and use the EJB Business Methods
+ Interface pattern, so that the EJB’s local interface extends a non
+ EJB-specific business methods interface. Let’s call this business
+ methods interface MyComponent.
+
+
+
+ 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 we’ll also need to implement the local home interface and
+ provide an implementation class that implements SessionBean
+ and the MyComponent business methods interface. Now the
+ only Java coding we’ll need to do to hook up our web tier controller to the
+ EJB implementation is to expose a setter method of type MyComponent
+ on the controller. This will save the reference as an instance variable in the
+ controller:
+
+
+
+ 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
+ LocalStatelessSessionProxyFactoryBean instance, which
+ will be the EJB proxy object. The configuration of the proxy, and setting of
+ the myComponent property of the controller is done
+ with a configuration entry such as:
+
+
+
+
+
+
+
+
+]]>
+
+ There’s a lot of work happening behind the scenes, courtesy of
+ the Spring AOP framework, although you aren’t forced to work with AOP
+ concepts to enjoy the results. The myComponent bean
+ definition creates a proxy for the EJB, which implements the business
+ method interface. The EJB local home is cached on startup, so there’s
+ only a single JNDI lookup. Each time the EJB is invoked, the proxy
+ invokes the classname method on the local EJB and
+ invokes the corresponding business method on the EJB.
+
+
+ The myController bean definition sets the
+ myComponent property of the controller class to the
+ EJB proxy.
+
+
+ Alternatively (and preferably in case of many such proxy definitions),
+ consider using the <jee:local-slsb>
+ configuration element in Spring's "jee" namespace:
+
+
+
+
+
+]]>
+
+ 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 myComponent bean definition without changing a
+ line of Java code. Additionally, we haven’t had to write a single line of
+ JNDI lookup or other EJB plumbing code as part of our application.
+
+
+ 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 don’t want to make fine-grained calls
+ to EJBs anyway, as there’s a cost associated with the EJB infrastructure
+ in the application server.
+
+
+ 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
+ ApplicationContext 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 init() 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 lazy-init attribute.
+
+
+ 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
+ LocalSlsbInvokerInterceptor.
+
+
+
+
+ Accessing remote SLSBs
+
+ Accessing remote EJBs is essentially identical to accessing local
+ EJBs, except that the
+ SimpleRemoteStatelessSessionProxyFactoryBean or
+ <jee:remote-slsb> 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.
+
+
+ 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 RemoteException, 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
+ RemoteException in your Business Method Interface and
+ implementing EJB code, have a remote interface which is identical except
+ that it does throw RemoteException, 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
+ RemoteException class. Any actual
+ RemoteException that is thrown during the EJB
+ invocation will be re-thrown as the non-checked
+ RemoteAccessException class, which is a subclass of
+ RuntimeException. 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
+ RemoteExceptions in your business interface.
+
+
+
+
+ Accessing EJB 2.x SLSBs versus EJB 3 SLSBs
+
+ Accessing EJB 2.x Session Beans and EJB 3 Session Beans via Spring
+ is largely transparent. Spring's EJB accessors, including the
+ <jee:local-slsb> and <jee:remote-slsb>
+ 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).
+
+
+ Note: For EJB 3 Session Beans, you could effectively use a
+ JndiObjectFactoryBean / <jee:jndi-lookup>
+ as well, since fully usable component references are exposed for plain
+ JNDI lookups there. Defining explicit <jee:local-slsb>
+ / <jee:remote-slsb> lookups simply provides
+ consistent and more explicit EJB access configuration.
+
+
+
+
+
+ Using Spring's EJB implementation support classes
+
+
+ EJB 2.x base classes
+
+ Spring provides convenience classes to help you implement EJBs.
+ These are designed to encourage the good practice of putting business
+ logic behind EJBs in POJOs, leaving EJBs responsible for transaction
+ demarcation and (optionally) remoting.
+
+
+ To implement a Stateless or Stateful session bean, or a Message Driven
+ bean, you need only derive your implementation class from
+ AbstractStatelessSessionBean,
+ AbstractStatefulSessionBean, and
+ AbstractMessageDrivenBean/AbstractJmsMessageDrivenBean,
+ respectively.
+
+
+ Consider an example Stateless Session bean which actually delegates
+ the implementation to a plain java service object. We have the business interface:
+
+
+ We also have the plain Java implementation object:
+
+ And finally the Stateless Session Bean itself:
+
+
+ The Spring EJB support base classes will by default create and load
+ a Spring IoC container as part of their lifecycle, which is then available
+ to the EJB (for example, as used in the code above to obtain the POJO
+ service object). The loading is done via a strategy object which is a subclass of
+ BeanFactoryLocator. The actual implementation of
+ BeanFactoryLocator used by default is
+ ContextJndiBeanFactoryLocator, which creates the
+ ApplicationContext from a resource locations specified as a JNDI
+ environment variable (in the case of the EJB classes, at
+ java:comp/env/ejb/BeanFactoryPath). If there is a need
+ to change the BeanFactory/ApplicationContext loading strategy, the default
+ BeanFactoryLocator implementation used may be overridden
+ by calling the setBeanFactoryLocator() method, either
+ in setSessionContext(), or in the actual constructor of
+ the EJB. Please see the Javadocs for more details.
+
+
+ As described in the Javadocs, Stateful Session beans expecting to be
+ passivated and reactivated as part of their lifecycle, and which use a
+ non-serializable container instance (which is the normal case) will have
+ to manually call unloadBeanFactory() and
+ loadBeanFactory from ejbPassivate
+ and ejbActivate, respectively, to unload and reload the
+ BeanFactory on passivation and activation, since it can not be saved by
+ the EJB container.
+
+
+ The default behavior of the ContextJndiBeanFactoryLocator
+ classes which is to load an ApplicationContext for the
+ use of the EJB is adequate for some situations. However, it is problematic when
+ the ApplicationContext is loading a number
+ of beans, or the initialization of those beans is time consuming or memory
+ intensive (such as a Hibernate SessionFactory initialization, for
+ example), since every EJB will have their own copy. In this case, the user
+ may want to override the default ContextJndiBeanFactoryLocator
+ usage and use another BeanFactoryLocator variant, such as the
+ ContextSingletonBeanFactoryLocator which can load and use a
+ shared container to be used by multiple EJBs or other clients. Doing this is relatively
+ simple, by adding code similar to this to the EJB:
+
+
+
+ You would then need to create a bean definition file named beanRefContext.xml.
+ This file defines all bean factories (usually in the form of application contexts) that may be used
+ in the EJB. In many cases, this file will only contain a single bean definition such as this (where
+ businessApplicationContext.xml contains the bean definitions for all business
+ service POJOs):
+
+
+
+
+
+]]>
+
+ In the above example, the ServicesConstants.PRIMARY_CONTEXT_ID constant
+ would be defined as follows:
+
+
+
+ Please see the respective Javadocs for the BeanFactoryLocator and
+ ContextSingletonBeanFactoryLocator classes for more information on
+ their usage.
+
+
+
+
+ EJB 3 injection interceptor
+
+ For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient
+ interceptor that resolves Spring 2.5's @Autowired annotation
+ in the EJB component class:
+ org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.
+ This interceptor can be applied through an @Interceptors annotation
+ in the EJB component class, or through an interceptor-binding
+ XML element in the EJB deployment descriptor.
+
+
+
+ SpringBeanAutowiringInterceptor by default obtains target
+ beans from a ContextSingletonBeanFactoryLocator, with the
+ context defined in a bean definition file named beanRefContext.xml.
+ 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 beanRefContext.xml) can be explicitly specified
+ either through overriding the getBeanFactoryLocatorKey method
+ in a custom SpringBeanAutowiringInterceptor subclass.
+
+
+ Alternatively, consider overriding SpringBeanAutowiringInterceptor's
+ getBeanFactory method, e.g. obtaining a shared
+ ApplicationContext from a custom holder class.
+
+
+
+
+
+
diff --git a/spring-framework-reference/src/jdbc.xml b/spring-framework-reference/src/jdbc.xml
new file mode 100644
index 00000000000..8625254c52d
--- /dev/null
+++ b/spring-framework-reference/src/jdbc.xml
@@ -0,0 +1,2511 @@
+
+
+ Data access using JDBC
+
+
+ Introduction
+
+ The value-add provided by the Spring Framework's JDBC abstraction
+ framework is perhaps best shown by the following list (note that only the
+ italicized lines need to be coded by an application developer):
+
+
+
+ Define connection parameters
+
+
+
+ Open the connection
+
+
+
+ Specify the statement
+
+
+
+ Prepare and execute the statement
+
+
+
+ Set up the loop to iterate through the results (if any)
+
+
+
+ Do the work for each iteration
+
+
+
+ Process any exception
+
+
+
+ Handle transactions
+
+
+
+ Close the connection
+
+
+
+ The Spring Framework takes care of all the grungy, low-level details
+ that can make JDBC such a tedious API to develop with.
+
+
+ Choosing a style
+
+ There are a number of options for selecting an approach to form
+ the basis for your JDBC database access. There are three flavors of the
+ JdbcTemplate, a new "SimpleJdbc" approach taking advantage of database
+ metadata, and there is also the "RDBMS Object" style for a more object
+ oriented approach similar in style to the JDO Query design. We'll
+ briefly list the primary reasons why you would pick one of these
+ approaches. Keep in mind that even if you start using one of these
+ approaches, you can still mix and match if there is a feature in a
+ different approach that you would like to take advantage of. All
+ approaches requires a JDBC 2.0 compliant driver and some advanced
+ features require a JDBC 3.0 driver.
+
+
+
+ JdbcTemplate - this is the
+ classic Spring JDBC approach and the most widely used. This is the
+ "lowest level" approach and all other approaches use a JdbcTemplate
+ under the covers. Works well in a JDK 1.4 and higher
+ environment.
+
+
+
+ NamedParameterJdbcTemplate -
+ wraps a JdbcTemplate to provide more convenient usage with named
+ parameters instead of the traditional JDBC "?" place holders. This
+ provides better documentation and ease of use when you have multiple
+ parameters for an SQL statement. Works with JDK 1.4 and up.
+
+
+
+ SimpleJdbcTemplate - this
+ class combines the most frequently used features of both
+ JdbcTemplate and NamedParameterJdbcTemplate plus it adds additional
+ convenience by taking advantage of some Java 5 features like
+ varargs, autoboxing and generics to provide an easier to use API.
+ Requires JDK 5 or higher.
+
+
+
+ SimpleJdbcInsert and
+ SimpleJdbcCall - designed to take advantage of database
+ metadata to limit the amount of configuration needed. This will
+ simplify the coding to a point where you only need to provide the
+ name of the table or procedure and provide a Map of parameters
+ matching the column names. Designed to work together with the
+ SimpleJdbcTemplate. Requires JDK 5 or higher and a database that
+ provides adequate metadata.
+
+
+
+ RDBMS Objects including MappingSqlQuery,
+ SqlUpdate and StoredProcedure - an approach where you
+ create reusable and thread safe objects during initialization of
+ your data access layer. This approach is modeled after JDO Query
+ where you define your query string, declare parameters and compile
+ the query. Once that is done any execute methods can be called
+ multiple times with various parameter values passed in. Works with
+ JDK 1.4 and higher.
+
+
+
+
+
+ The package hierarchy
+
+ The Spring Framework's JDBC abstraction framework consists of four
+ different packages, namely core,
+ datasource, object, and
+ support.
+
+ The org.springframework.jdbc.core package
+ contains the JdbcTemplate class and its various
+ callback interfaces, plus a variety of related classes. A sub-package
+ named org.springframework.jdbc.core.simple contains
+ the SimpleJdbcTemplate class and the related
+ SimpleJdbcInsert and
+ SimpleJdbcCall classes. Another sub-package named
+ org.springframework.jdbc.core.namedparam contains the
+ NamedParameterJdbcTemplate class and the related
+ support classes.
+
+ The org.springframework.jdbc.datasource package
+ contains a utility class for easy
+ DataSource access, and various simple
+ DataSource implementations that can be
+ used for testing and running unmodified JDBC code outside of a J2EE
+ container. The utility class provides static methods to obtain
+ connections from JNDI and to close connections if necessary. It has
+ support for thread-bound connections, e.g. for use with
+ DataSourceTransactionManager.
+
+ Next, the org.springframework.jdbc.object
+ package contains classes that represent RDBMS queries, updates, and
+ stored procedures as thread safe, reusable objects. This approach is
+ modeled by JDO, although of course objects returned by queries are
+ disconnected from the database. This higher level of JDBC
+ abstraction depends on the lower-level abstraction in the
+ org.springframework.jdbc.core package.
+
+ Finally the org.springframework.jdbc.support
+ package is where you find the SQLException
+ translation functionality and some utility classes.
+
+ Exceptions thrown during JDBC processing are translated to
+ exceptions defined in the org.springframework.dao
+ package. This means that code using the Spring JDBC abstraction layer
+ does not need to implement JDBC or RDBMS-specific error handling. All
+ translated exceptions are unchecked giving you the option of catching
+ the exceptions that you can recover from while allowing other exceptions
+ to be propagated to the caller.
+
+
+
+
+ Using the JDBC Core classes to control basic JDBC processing and
+ error handling
+
+
+ JdbcTemplate
+
+ The JdbcTemplate class is the central class
+ in the JDBC core package. It simplifies the use of JDBC since it handles
+ the creation and release of resources. This helps to avoid common errors
+ such as forgetting to always close the connection. It executes the core
+ JDBC workflow like statement creation and execution, leaving application
+ code to provide SQL and extract results. This class executes SQL
+ queries, update statements or stored procedure calls, imitating
+ iteration over ResultSets and extraction
+ of returned parameter values. It also catches JDBC exceptions and
+ translates them to the generic, more informative, exception hierarchy
+ defined in the org.springframework.dao
+ package.
+
+ Code using the JdbcTemplate only need to
+ implement callback interfaces, giving them a clearly defined contract.
+ The PreparedStatementCreator callback
+ interface creates a prepared statement given a
+ Connection provided by this class,
+ providing SQL and any necessary parameters. The same is true for the
+ CallableStatementCreator interface which
+ creates callable statement. The
+ RowCallbackHandler interface extracts
+ values from each row of a
+ ResultSet.
+
+ The JdbcTemplate can be used within a DAO
+ implementation via direct instantiation with a
+ DataSource reference, or be configured in
+ a Spring IOC container and given to DAOs as a bean reference. Note: the
+ DataSource should always be configured as
+ a bean in the Spring IoC container, in the first case given to the
+ service directly, in the second case to the prepared template.
+
+ Finally, all of the SQL issued by this class is logged at the
+ 'DEBUG' level under the category corresponding to the
+ fully qualified class name of the template instance (typically
+ JdbcTemplate, but it may be different if a custom
+ subclass of the JdbcTemplate class is being
+ used).
+
+
+ Examples
+
+ Find below some examples of using the
+ JdbcTemplate class. (These examples are not an
+ exhaustive list of all of the functionality exposed by the
+ JdbcTemplate; see the attendant Javadocs for
+ that).
+
+
+ Querying (SELECT)
+
+ A simple query for getting the number of rows in a
+ relation.
+
+ int rowCount = this.jdbcTemplate.queryForInt("select count(0) from t_accrual");
+
+ A simple query using a bind variable.
+
+ int countOfActorsNamedJoe = this.jdbcTemplate.queryForInt(
+ "select count(0) from t_actors where first_name = ?", new Object[]{"Joe"});
+
+ Querying for a String.
+
+ String surname = (String) this.jdbcTemplate.queryForObject(
+ "select surname from t_actor where id = ?",
+ new Object[]{new Long(1212)}, String.class);
+
+ Querying and populating a single domain
+ object.
+
+ Actor actor = (Actor) this.jdbcTemplate.queryForObject(
+ "select first_name, surname from t_actor where id = ?",
+ new Object[]{new Long(1212)},
+ new RowMapper() {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Actor actor = new Actor();
+ actor.setFirstName(rs.getString("first_name"));
+ actor.setSurname(rs.getString("surname"));
+ return actor;
+ }
+ });
+
+ Querying and populating a number of domain objects.
+
+ Collection actors = this.jdbcTemplate.query(
+ "select first_name, surname from t_actor",
+ new RowMapper() {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Actor actor = new Actor();
+ actor.setFirstName(rs.getString("first_name"));
+ actor.setSurname(rs.getString("surname"));
+ return actor;
+ }
+ });
+
+ If the last two snippets of code actually existed in the same
+ application, it would make sense to remove the duplication present
+ in the two RowMapper anonymous inner
+ classes, and extract them out into a single class (typically a
+ static inner class) that can then be referenced
+ by DAO methods as needed. For example, the last code snippet might
+ be better off written like so:
+
+ public Collection findAllActors() {
+ return this.jdbcTemplate.query( "select first_name, surname from t_actor", new ActorMapper());
+}
+
+private static final class ActorMapper implements RowMapper {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Actor actor = new Actor();
+ actor.setFirstName(rs.getString("first_name"));
+ actor.setSurname(rs.getString("surname"));
+ return actor;
+ }
+}
+
+
+
+ Updating (INSERT/UPDATE/DELETE)
+
+ this.jdbcTemplate.update(
+ "insert into t_actor (first_name, surname) values (?, ?)",
+ new Object[] {"Leonor", "Watling"});
+
+ this.jdbcTemplate.update(
+ "update t_actor set weapon = ? where id = ?",
+ new Object[] {"Banjo", new Long(5276)});
+
+ this.jdbcTemplate.update(
+ "delete from actor where id = ?",
+ new Object[] {new Long.valueOf(actorId)});
+
+
+
+ Other operations
+
+ The execute(..) method can be used to
+ execute any arbitrary SQL, and as such is often used for DDL
+ statements. It is heavily overloaded with variants taking callback
+ interfaces, binding variable arrays, and suchlike.
+
+ this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
+
+ Invoking a simple stored procedure (more sophisticated stored
+ procedure support is covered
+ later).
+
+ this.jdbcTemplate.update(
+ "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)",
+ new Object[]{Long.valueOf(unionId)});
+
+
+
+
+ JdbcTemplate idioms (best
+ practices)
+
+ Instances of the JdbcTemplate class are
+ threadsafe once configured. This is important
+ because it means that you can configure a single instance of a
+ JdbcTemplate and then safely inject this
+ shared reference into multiple DAOs (or
+ repositories). To be clear, the JdbcTemplate is
+ stateful, in that it maintains a reference to a
+ DataSource, but this state is
+ not conversational state.
+
+ A common idiom when using the
+ JdbcTemplate class (and the associated SimpleJdbcTemplate
+ and NamedParameterJdbcTemplate
+ classes) is to configure a DataSource
+ in your Spring configuration file, and then dependency inject that
+ shared DataSource bean into your DAO
+ classes; the JdbcTemplate is created in the
+ setter for the DataSource. This leads
+ to DAOs that look in part like this:
+
+ public class JdbcCorporateEventDao implements CorporateEventDao {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ // JDBC-backed implementations of the methods on the CorporateEventDao follow...
+}
+
+ The attendant configuration might look like this.
+
+ <?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-2.5.xsd">
+
+ <bean id="corporateEventDao" class="com.example.JdbcCorporateEventDao">
+ <property name="dataSource" ref="dataSource"/>
+ </bean>
+
+ <!-- the DataSource (parameterized for configuration via a PropertyPlaceHolderConfigurer) -->
+ <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
+ <property name="driverClassName" value="${jdbc.driverClassName}"/>
+ <property name="url" value="${jdbc.url}"/>
+ <property name="username" value="${jdbc.username}"/>
+ <property name="password" value="${jdbc.password}"/>
+ </bean>
+
+</beans>
+
+ If you are using Spring's JdbcDaoSupport
+ class, and your various JDBC-backed DAO classes extend from it, then
+ you inherit a setDataSource(..) method for
+ free from said superclass. It is totally up to you as to whether or
+ not you inherit from said class, you certainly are not forced to. If
+ you look at the source for the JdbcDaoSupport
+ class you will see that there is not a whole lot to it... it is
+ provided as a convenience only.
+
+ Regardless of which of the above template initialization styles
+ you choose to use (or not), there is (almost) certainly no need to
+ create a brand new instance of a JdbcTemplate
+ class each and every time you wish to execute some SQL... remember,
+ once configured, a JdbcTemplate instance is
+ threadsafe. A reason for wanting multiple
+ JdbcTemplate instances would be when you have
+ an application that accesses multiple databases, which requires
+ multiple DataSources, and subsequently
+ multiple differently configured
+ JdbcTemplates.
+
+
+
+
+ NamedParameterJdbcTemplate
+
+ The NamedParameterJdbcTemplate class adds
+ support for programming JDBC statements using named parameters (as
+ opposed to programming JDBC statements using only classic placeholder
+ ('?') arguments. The
+ NamedParameterJdbcTemplate class wraps a
+ JdbcTemplate, and delegates to the wrapped
+ JdbcTemplate to do much of its work. This section
+ will describe only those areas of the
+ NamedParameterJdbcTemplate class that differ from
+ the JdbcTemplate itself; namely, programming JDBC
+ statements using named parameters.
+
+ // some JDBC-backed DAO class...
+private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
+}
+
+public int countOfActorsByFirstName(String firstName) {
+
+ String sql = "select count(0) from T_ACTOR where first_name = :first_name";
+
+ SqlParameterSource namedParameters = new MapSqlParameterSource("first_name", firstName);
+
+ return namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
+}
+
+ Notice the use of the named parameter notation in the value
+ assigned to the 'sql' variable, and the corresponding
+ value that is plugged into the 'namedParameters'
+ variable (of type MapSqlParameterSource).
+
+ If you like, you can also pass along named parameters (and their
+ corresponding values) to a
+ NamedParameterJdbcTemplate instance using the
+ (perhaps more familiar) Map-based style.
+ (The rest of the methods exposed by the
+ NamedParameterJdbcOperations - and
+ implemented by the NamedParameterJdbcTemplate
+ class) follow a similar pattern and will not be covered here.)
+
+ // some JDBC-backed DAO class...
+private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
+}
+
+public int countOfActorsByFirstName(String firstName) {
+
+ String sql = "select count(0) from T_ACTOR where first_name = :first_name";
+
+ Map namedParameters = Collections.singletonMap("first_name", firstName);
+
+ return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
+}
+
+ Another nice feature related to the
+ NamedParameterJdbcTemplate (and existing in the
+ same Java package) is the
+ SqlParameterSource interface. You have
+ already seen an example of an implementation of this interface in one of
+ the preceding code snippets (the
+ MapSqlParameterSource class). The entire point of
+ the SqlParameterSource is to serve as a
+ source of named parameter values to a
+ NamedParameterJdbcTemplate. The
+ MapSqlParameterSource class is a very simple
+ implementation, that is simply an adapter around a
+ java.util.Map, where the keys are the
+ parameter names and the values are the parameter values.
+
+ Another SqlParameterSource
+ implementation is the
+ BeanPropertySqlParameterSource class. This class
+ wraps an arbitrary JavaBean (that is, an instance of a class that
+ adheres to the JavaBean
+ conventions), and uses the properties of the wrapped JavaBean as
+ the source of named parameter values.
+
+ public class Actor {
+
+ private Long id;
+ private String firstName;
+ private String lastName;
+
+ public String getFirstName() {
+ return this.firstName;
+ }
+
+ public String getLastName() {
+ return this.lastName;
+ }
+
+ public Long getId() {
+ return this.id;
+ }
+
+ // setters omitted...
+
+}
+
+ // some JDBC-backed DAO class...
+private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
+}
+
+public int countOfActors(Actor exampleActor) {
+
+ // notice how the named parameters match the properties of the above 'Actor' class
+ String sql = "select count(0) from T_ACTOR where first_name = :firstName and last_name = :lastName";
+
+ SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(exampleActor);
+
+ return this.namedParameterJdbcTemplate.queryForInt(sql, namedParameters);
+}
+
+ Remember that the
+ NamedParameterJdbcTemplate class
+ wraps a classic JdbcTemplate
+ template; if you need access to the wrapped
+ JdbcTemplate instance (to access some of the
+ functionality only present in the JdbcTemplate
+ class), then you can use the
+ getJdbcOperations() method to access the
+ wrapped JdbcTemplatevia the
+ JdbcOperations
+ interface.
+
+ See also the section entitled for some advice on how to best use
+ the NamedParameterJdbcTemplate class in the
+ context of an application.
+
+
+
+ SimpleJdbcTemplate
+
+
+ The functionality offered by the
+ SimpleJdbcTemplate is only available to you if
+ you are using Java 5 or later.
+
+
+ The SimpleJdbcTemplate class is a wrapper
+ around the classic JdbcTemplate that takes
+ advantage of Java 5 language features such as varargs and autoboxing.
+ The SimpleJdbcTemplate class is somewhat of a sop
+ to the syntactic-sugar-like features of Java 5, but as anyone who has
+ developed on Java 5 and then had to move back to developing on a
+ previous version of the JDK will know, those syntactic-sugar-like
+ features sure are nice.
+
+ The value-add of the SimpleJdbcTemplate
+ class in the area of syntactic-sugar is best illustrated with a
+ 'before and after' example. The following code
+ snippet shows first some data access code using the classic
+ JdbcTemplate, followed immediately thereafter by
+ a code snippet that does the same job, only this time using the
+ SimpleJdbcTemplate.
+
+ // classic JdbcTemplate-style...
+private JdbcTemplate jdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+}
+
+public Actor findActor(long id) {
+ String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
+
+ RowMapper mapper = new RowMapper() {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Actor actor = new Actor();
+ actor.setId(rs.getLong("id"));
+ actor.setFirstName(rs.getString("first_name"));
+ actor.setLastName(rs.getString("last_name"));
+ return actor;
+ }
+ };
+
+ // notice the cast, the wrapping up of the 'id' argument
+ // in an array, and the boxing of the 'id' argument as a reference type
+ return (Actor) jdbcTemplate.queryForObject(sql, mapper, new Object[] {Long.valueOf(id)});
+}
+
+ Here is the same method, only this time using the
+ SimpleJdbcTemplate; notice how much 'cleaner' the
+ code is.
+
+ // SimpleJdbcTemplate-style...
+private SimpleJdbcTemplate simpleJdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+}
+
+public Actor findActor(long id) {
+ String sql = "select id, first_name, last_name from T_ACTOR where id = ?";
+
+ ParameterizedRowMapper<Actor> mapper = new ParameterizedRowMapper<Actor>() {
+
+ // notice the return type with respect to Java 5 covariant return types
+ public Actor mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Actor actor = new Actor();
+ actor.setId(rs.getLong("id"));
+ actor.setFirstName(rs.getString("first_name"));
+ actor.setLastName(rs.getString("last_name"));
+ return actor;
+ }
+ };
+
+ return this.simpleJdbcTemplate.queryForObject(sql, mapper, id);
+}
+
+ See also the section entitled for some advice on how to best use
+ the SimpleJdbcTemplate class in the context of an
+ application.
+
+
+ The SimpleJdbcTemplate class only offers
+ a subset of the methods exposed on the
+ JdbcTemplate class. If you need to use a method
+ from the JdbcTemplate that is not defined on
+ the SimpleJdbcTemplate, you can always access
+ the underlying JdbcTemplate by calling the
+ getJdbcOperations() method on the
+ SimpleJdbcTemplate, which will then allow you
+ to invoke the method that you want. The only downside is that the
+ methods on the JdbcOperations interface
+ are not generified, so you are back to casting and such again.
+
+
+
+
+ DataSource
+
+ In order to work with data from a database, one needs to obtain a
+ connection to the database. The way Spring does this is through a
+ DataSource. A
+ DataSource is part of the JDBC
+ specification and can be seen as a generalized connection factory. It
+ allows a container or a framework to hide connection pooling and
+ transaction management issues from the application code. As a developer,
+ you don not need to know any details about how to connect to the
+ database, that is the responsibility for the administrator that sets up
+ the datasource. You will most likely have to fulfill both roles while
+ you are developing and testing you code though, but you will not
+ necessarily have to know how the production data source is
+ configured.
+
+ When using Spring's JDBC layer, you can either obtain a data
+ source from JNDI or you can configure your own, using an implementation
+ that is provided in the Spring distribution. The latter comes in handy
+ for unit testing outside of a web container. We will use the
+ DriverManagerDataSource implementation for this
+ section but there are several additional implementations that will be
+ covered later on. The DriverManagerDataSource
+ works the same way that you probably are used to work when you obtain a
+ JDBC connection. You have to specify the fully qualified class name of
+ the JDBC driver that you are using so that the
+ DriverManager can load the driver class. Then you
+ have to provide a URL that varies between JDBC drivers. You have to
+ consult the documentation for your driver for the correct value to use
+ here. Finally you must provide a username and a password that will be
+ used to connect to the database. Here is an example of how to configure
+ a DriverManagerDataSource:
+
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
+dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
+dataSource.setUsername("sa");
+dataSource.setPassword("");
+
+
+
+ SQLExceptionTranslator
+
+ SQLExceptionTranslator is an
+ interface to be implemented by classes that can translate between
+ SQLExceptions and Spring's own
+ data-access-strategy-agnostic
+ org.springframework.dao.DataAccessException.
+ Implementations can be generic (for example, using SQLState codes for
+ JDBC) or proprietary (for example, using Oracle error codes) for greater
+ precision.
+
+ SQLErrorCodeSQLExceptionTranslator is the
+ implementation of SQLExceptionTranslator
+ that is used by default. This implementation uses specific vendor codes.
+ More precise than SQLState implementation, but vendor
+ specific. The error code translations are based on codes held in a
+ JavaBean type class named SQLErrorCodes. This
+ class is created and populated by an
+ SQLErrorCodesFactory which as the name suggests
+ is a factory for creating SQLErrorCodes based on
+ the contents of a configuration file named 'sql-error-codes.xml'. This file is
+ populated with vendor codes and based on the DatabaseProductName taken
+ from the DatabaseMetaData, the codes for
+ the current database are used.
+
+ The SQLErrorCodeSQLExceptionTranslator
+ applies the following matching rules:
+
+ Try custom translation implemented by any subclass. Note
+ that this class is concrete and is typically used itself, in which
+ case this rule does not apply.
+
+
+
+ Apply error code matching. Error codes are obtained from the
+ SQLErrorCodesFactory by default. This looks
+ up error codes from the classpath and keys into them from the
+ database name from the database metadata.
+
+
+
+ Use the fallback translator.
+ SQLStateSQLExceptionTranslator is the
+ default fallback translator.
+
+
+
+ SQLErrorCodeSQLExceptionTranslator can be
+ extended the following way:
+
+ public class MySQLErrorCodesTranslator extends SQLErrorCodeSQLExceptionTranslator {
+
+ protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
+ if (sqlex.getErrorCode() == -12345) {
+ return new DeadlockLoserDataAccessException(task, sqlex);
+ }
+ return null;
+ }
+}
+
+ In this example the specific error code
+ '-12345' is translated and any other errors are
+ simply left to be translated by the default translator implementation.
+ To use this custom translator, it is necessary to pass it to the
+ JdbcTemplate using the method
+ setExceptionTranslator and to use this
+ JdbcTemplate for all of the data access
+ processing where this translator is needed. Here is an example of how
+ this custom translator can be used:
+
+ // create a JdbcTemplate and set data source
+JdbcTemplate jt = new JdbcTemplate();
+jt.setDataSource(dataSource);
+// create a custom translator and set the DataSource for the default translation lookup
+MySQLErrorCodesTransalator tr = new MySQLErrorCodesTransalator();
+tr.setDataSource(dataSource);
+jt.setExceptionTranslator(tr);
+// use the JdbcTemplate for this SqlUpdate
+SqlUpdate su = new SqlUpdate();
+su.setJdbcTemplate(jt);
+su.setSql("update orders set shipping_charge = shipping_charge * 1.05");
+su.compile();
+su.update();
+
+ The custom translator is passed a data source because we still
+ want the default translation to look up the error codes in
+ sql-error-codes.xml.
+
+
+
+ Executing statements
+
+ To execute an SQL statement, there is very little code needed. All
+ you need is a DataSource and a
+ JdbcTemplate. Once you have that, you can use a
+ number of convenience methods that are provided with the
+ JdbcTemplate. Here is a short example showing
+ what you need to include for a minimal but fully functional class that
+ creates a new table.
+
+ import javax.sql.DataSource;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+public class ExecuteAStatement {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ public void doExecute() {
+ this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
+ }
+}
+
+
+
+ Running Queries
+
+ In addition to the execute methods, there is a large number of
+ query methods. Some of these methods are intended to be used for queries
+ that return a single value. Maybe you want to retrieve a count or a
+ specific value from one row. If that is the case then you can use
+ queryForInt(..),
+ queryForLong(..) or
+ queryForObject(..). The latter will convert the
+ returned JDBC Type to the Java class that is
+ passed in as an argument. If the type conversion is invalid, then an
+ InvalidDataAccessApiUsageException will
+ be thrown. Here is an example that contains two query methods, one for
+ an int and one that queries for a
+ String.
+
+ import javax.sql.DataSource;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+public class RunAQuery {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ public int getCount() {
+ return this.jdbcTemplate.queryForInt("select count(*) from mytable");
+ }
+
+ public String getName() {
+ return (String) this.jdbcTemplate.queryForObject("select name from mytable", String.class);
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+}
+
+ In addition to the single results query methods there are several
+ methods that return a List with an entry for each row that the query
+ returned. The most generic method is
+ queryForList(..) which returns a
+ List where each entry is a
+ Map with each entry in the map
+ representing the column value for that row. If we add a method to the
+ above example to retrieve a list of all the rows, it would look like
+ this:
+
+
+private JdbcTemplate jdbcTemplate;
+
+public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+}
+
+public List getList() {
+ return this.jdbcTemplate.queryForList("select * from mytable");
+}
+
+ The list returned would look something like this:
+
+ [{name=Bob, id=1}, {name=Mary, id=2}]
+
+
+
+ Updating the database
+
+ There are also a number of update methods that you can use. Find
+ below an example where a column is updated for a certain primary key. In
+ this example an SQL statement is used that has place holders for row
+ parameters. Note that the parameter values are passed in as an array of
+ objects (and thus primitives have to be wrapped in the primitive wrapper
+ classes).
+
+ import javax.sql.DataSource;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+public class ExecuteAnUpdate {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ public void setName(int id, String name) {
+ this.jdbcTemplate.update(
+ "update mytable set name = ? where id = ?",
+ new Object[] {name, new Integer(id)});
+ }
+}
+
+
+
+ Retrieving auto-generated keys
+
+ One of the update convenience methods
+ provides support for acquiring the primary keys generated by the
+ database (part of the JDBC 3.0 standard - see chapter 13.6 of the
+ specification for details). The method takes a
+ PreparedStatementCreator as its first argument,
+ and this is the way the required insert statement is specified. The
+ other argument is a KeyHolder, which will contain
+ the generated key on successful return from the update. There is not a
+ standard single way to create an appropriate
+ PreparedStatement (which explains why the method
+ signature is the way it is). An example that works on Oracle and may not
+ work on other platforms is:
+
+ final String INSERT_SQL = "insert into my_test (name) values(?)";
+final String name = "Rob";
+
+KeyHolder keyHolder = new GeneratedKeyHolder();
+jdbcTemplate.update(
+ new PreparedStatementCreator() {
+ public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
+ PreparedStatement ps =
+ connection.prepareStatement(INSERT_SQL, new String[] {"id"});
+ ps.setString(1, name);
+ return ps;
+ }
+ },
+ keyHolder);
+
+// keyHolder.getKey() now contains the generated key
+
+
+
+
+ Controlling database connections
+
+
+ DataSourceUtils
+
+ The DataSourceUtils class is a convenient
+ and powerful helper class that provides static
+ methods to obtain connections from JNDI and close connections if
+ necessary. It has support for thread-bound connections, for example for
+ use with DataSourceTransactionManager.
+
+
+
+ SmartDataSource
+
+ The SmartDataSource interface is to
+ be implemented by classes that can provide a connection to a relational
+ database. Extends the DataSource
+ interface to allow classes using it to query whether or not the
+ connection should be closed after a given operation. This can sometimes
+ be useful for efficiency, in the cases where one knows that one wants to
+ reuse a connection.
+
+
+
+ AbstractDataSource
+
+ This is an abstract base class for Spring's
+ DataSource implementations, that takes
+ care of the "uninteresting" glue. This is the class one would extend if
+ one was writing one's own DataSource
+ implementation.
+
+
+
+ SingleConnectionDataSource
+
+ The SingleConnectionDataSource class is an
+ implementation of the SmartDataSource
+ interface that wraps a single
+ Connection that is
+ not closed after use. Obviously, this is not
+ multi-threading capable.
+
+ If client code will call close in the assumption of a pooled
+ connection, like when using persistence tools, set
+ suppressClose to true. This will
+ return a close-suppressing proxy instead of the physical connection. Be
+ aware that you will not be able to cast this to a native Oracle
+ Connection or the like anymore.
+
+ This is primarily a test class. For example, it enables easy
+ testing of code outside an application server, in conjunction with a
+ simple JNDI environment. In contrast to
+ DriverManagerDataSource, it reuses the same
+ connection all the time, avoiding excessive creation of physical
+ connections.
+
+
+
+ DriverManagerDataSource
+
+ The DriverManagerDataSource class is an
+ implementation of the standard DataSource
+ interface that configures a plain old JDBC Driver via bean properties, and
+ returns a new Connection every time.
+
+ This is potentially useful for test or standalone environments
+ outside of a J2EE container, either as a
+ DataSource bean in a Spring IoC
+ container, or in conjunction with a simple JNDI environment.
+ Pool-assuming Connection.close() calls will simply
+ close the connection, so any
+ DataSource-aware persistence code should
+ work. However, using JavaBean style connection pools such as
+ commons-dbcp is so easy, even in a test environment, that it is almost
+ always preferable to use such a connection pool over
+ DriverManagerDataSource.
+
+
+
+ TransactionAwareDataSourceProxy
+
+ TransactionAwareDataSourceProxy is a proxy
+ for a target DataSource, which wraps that
+ target DataSource to add awareness of
+ Spring-managed transactions. In this respect it is similar to a
+ transactional JNDI DataSource as provided
+ by a J2EE server.
+
+
+ It should almost never be necessary or desirable to use this
+ class, except when existing code exists which must be called and
+ passed a standard JDBC DataSource
+ interface implementation. In this case, it's possible to still have
+ this code be usable, but participating in Spring managed transactions.
+ It is generally preferable to write your own new code using the higher
+ level abstractions for resource management, such as
+ JdbcTemplate or
+ DataSourceUtils.
+
+
+ (See the
+ TransactionAwareDataSourceProxy Javadocs for more
+ details.)
+
+
+
+ DataSourceTransactionManager
+
+ The DataSourceTransactionManager class is a
+ PlatformTransactionManager implementation
+ for single JDBC datasources. It binds a JDBC connection from the
+ specified data source to the currently executing thread, potentially
+ allowing for one thread connection per data source.
+
+ Application code is required to retrieve the JDBC connection via
+ DataSourceUtils.getConnection(DataSource) instead of
+ J2EE's standard DataSource.getConnection. This is
+ recommended anyway, as it throws unchecked
+ org.springframework.dao exceptions instead of checked
+ SQLExceptions. All framework classes like
+ JdbcTemplate use this strategy implicitly. If not
+ used with this transaction manager, the lookup strategy behaves exactly
+ like the common one - it can thus be used in any case.
+
+ The DataSourceTransactionManager class
+ supports custom isolation levels, and timeouts that get applied as
+ appropriate JDBC statement query timeouts. To support the latter,
+ application code must either use JdbcTemplate or
+ call DataSourceUtils.applyTransactionTimeout(..)
+ method for each created statement.
+
+ This implementation can be used instead of
+ JtaTransactionManager in the single resource
+ case, as it does not require the container to support JTA. Switching
+ between both is just a matter of configuration, if you stick to the
+ required connection lookup pattern. Note that JTA does not support
+ custom isolation levels!
+
+
+
+ NativeJdbcExtractor
+
+ There are times when we need to access vendor specific JDBC
+ methods that differ from the standard JDBC API. This can be problematic
+ if we are running in an application server or with a
+ DataSource that wraps the
+ Connection, Statement and
+ ResultSet objects with its own wrapper objects.
+ To gain access to the native objects you can configure your
+ JdbcTemplate or
+ OracleLobHandler with a
+ NativeJdbcExtractor.
+
+ The NativeJdbcExtractor comes in a variety of flavors to match
+ your execution environment:
+
+
+
+ SimpleNativeJdbcExtractor
+
+
+
+ C3P0NativeJdbcExtractor
+
+
+
+ CommonsDbcpNativeJdbcExtractor
+
+
+
+ JBossNativeJdbcExtractor
+
+
+
+ WebLogicNativeJdbcExtractor
+
+
+
+ WebSphereNativeJdbcExtractor
+
+
+
+ XAPoolNativeJdbcExtractor
+
+
+
+ Usually the SimpleNativeJdbcExtractor is
+ sufficient for unwrapping a Connection object in
+ most environments. See the Java Docs for more details.
+
+
+
+
+ JDBC batch operations
+
+ Most JDBC drivers provide improved performance if you batch multiple
+ calls to the same prepared statement. By grouping updates into batches you
+ limit the number of round trips to the database. This section will cover
+ batch processing using both the JdbcTemplate and the
+ SimpleJdbcTemplate.
+
+
+ Batch operations with the JdbcTemplate
+
+ Using the JdbcTemplate batch processing is accomplished by
+ implementing a special interface,
+ BatchPreparedStatementSetter, and passing that in
+ as the second parameter in your batchUpdate
+ method call. This interface has two methods you must implement. One is
+ named getBatchSize and here you provide the size
+ of the current batch. The other method is
+ setValues and it allows you to set the values for
+ the parameters of the prepared statement and. This method will get
+ called the number of times that you specified in the
+ getBatchSize call. Here is an example of this
+ where we update the actor table based on entries in a list. The entire
+ list is used as the batch in his example.
+
+ public class JdbcActorDao implements ActorDao {
+ private JdbcTemplate jdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ public int[] batchUpdate(final List actors) {
+ int[] updateCounts = jdbcTemplate.batchUpdate(
+ "update t_actor set first_name = ?, last_name = ? where id = ?",
+ new BatchPreparedStatementSetter() {
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
+ ps.setString(1, ((Actor)actors.get(i)).getFirstName());
+ ps.setString(2, ((Actor)actors.get(i)).getLastName());
+ ps.setLong(3, ((Actor)actors.get(i)).getId().longValue());
+ }
+
+ public int getBatchSize() {
+ return actors.size();
+ }
+ } );
+ return updateCounts;
+ }
+
+ // ... additional methods
+}If you are processing stream of updates or reading from a
+ file then you might have a preferred batch size, but the last batch
+ might not have that number of entries. In this case you can use the
+ InterruptibleBatchPreparedStatementSetter
+ interface which allows you to interrupt a batch once the input source is
+ exhausted. The isBatchExhausted method allows you
+ to signal the end of the batch.
+
+
+
+ Batch operations with the SimpleJdbcTemplate
+
+ The SimpleJdbcTemplate provides an
+ alternate way of providing the batch update. Instead of implementing a
+ special batch interface, you simply provide all parameter values in the
+ call and the framework will loop over these values and use an internal
+ prepared statement setter. The API varies depending on whether you use
+ named parameters or not. For the named parameters you provide an array
+ of SqlParameterSource, one entry for each member
+ of the batch. You can use the
+ SqlParameterSource.createBatch method to create
+ this array, passing in either an array of JavaBeans or an array of Maps
+ containing the parameter values.
+
+ This example shows a batch update using named parameters:
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ }
+
+ public int[] batchUpdate(final List<Actor> actors) {
+ SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());
+ int[] updateCounts = simpleJdbcTemplate.batchUpdate(
+ "update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
+ batch);
+ return updateCounts;
+ }
+
+ // ... additional methods
+}For an SQL statement using the classic "?" place holders you
+ pass in a List containing an object array with the update values. This
+ object array must have one entry for each placeholder in the SQL
+ statement and they must be in the same order as they are defined in the
+ SQL statement.
+
+ The same example using classic JDBC "?" place holders:
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ }
+
+ public int[] batchUpdate(final List<Actor> actors) {
+ List<Object[]> batch = new ArrayList<Object[]>();
+ for (Actor actor : actors) {
+ Object[] values = new Object[] {
+ actor.getFirstName(),
+ actor.getLastName(),
+ actor.getId()};
+ batch.add(values);
+ }
+ int[] updateCounts = simpleJdbcTemplate.batchUpdate(
+ "update t_actor set first_name = ?, last_name = ? where id = ?",
+ batch);
+ return updateCounts;
+ }
+
+ // ... additional methods
+}All batch update methods return an int array containing the
+ number of affected rows for each batch entry. This count is reported by
+ the JDBC driver and it's not always available in which case the JDBC
+ driver simply returns a -2 value.
+
+
+
+
+ Simplifying JDBC operations with the SimpleJdbc classes
+
+ The SimpleJdbcInsert and
+ SimpleJdbcCall classes provide simplified
+ configuration by taking advantage of database metadata that can be
+ retrieved via the JDBC driver. This means there is less to configure up
+ front, although you can override or turn off the metadata processing if
+ you prefer to provide all the details in your code.
+
+
+ Inserting data using SimpleJdbcInsert
+
+ Let's start by looking at the
+ SimpleJdbcInsert class first. We will use the
+ minimal amount of configuration options to start with. The
+ SimpleJdbcInsert should be instantiated in the
+ data access layer's initialization method. For this example, the
+ initializing method is the setDataSource method.
+ There is no need to subclass the SimpleJdbcInsert
+ class, just create a new instance and set the table name using the
+ withTableName method. Configuration methods for
+ this class follows the "fluid" style returning the instance of the
+ SimpleJdbcInsert which allows you to chain all
+ configuration methods. In this case there is only one configuration
+ method used but we will see examples of multiple ones soon.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcInsert insertActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.insertActor =
+ new SimpleJdbcInsert(dataSource).withTableName("t_actor");
+ }
+
+ public void add(Actor actor) {
+ Map<String, Object> parameters = new HashMap<String, Object>(3);
+ parameters.put("id", actor.getId());
+ parameters.put("first_name", actor.getFirstName());
+ parameters.put("last_name", actor.getLastName());
+ insertActor.execute(parameters);
+ }
+
+ // ... additional methods
+}
+
+ The execute method used here takes a plain
+ java.utils.Map as its only parameter. The
+ important thing to note here is that the keys used for the Map must
+ match the column names of the table as defined in the database. This is
+ because we read the metadata in order to construct the actual insert
+ statement.
+
+
+
+ Retrieving auto-generated keys using SimpleJdbcInsert
+
+ Next we'll look at the same insert, but instead of passing in the
+ id we will retrieve the auto-generated key and set it on the new Actor
+ object. When we create the SimpleJdbcInsert, in
+ addition to specifying the table name, we specify the name of the
+ generated key column using the
+ usingGeneratedKeyColumns method.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcInsert insertActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.insertActor =
+ new SimpleJdbcInsert(dataSource)
+ .withTableName("t_actor")
+ .usingGeneratedKeyColumns("id");
+ }
+
+ public void add(Actor actor) {
+ Map<String, Object> parameters = new HashMap<String, Object>(2);
+ parameters.put("first_name", actor.getFirstName());
+ parameters.put("last_name", actor.getLastName());
+ Number newId = insertActor.executeAndReturnKey(parameters);
+ actor.setId(newId.longValue());
+ }
+
+ // ... additional methods
+}Here we can see the main difference when executing the
+ insert is that we don't add the id to the Map and we call the
+ executeReturningKey method. This returns a
+ java.lang.Number object that we can use to create an
+ instance of the numerical type that is used in our domain class. It's
+ important to note that we can't rely on all databases to return a
+ specific Java class here, java.lang.Number is the
+ base class that we can rely on. If you have multiple auto-generated
+ columns or the generated values are non-numeric then you can use a
+ KeyHolder that is returned from the
+ executeReturningKeyHolder method.
+
+
+
+ Specifying the columns to use for a SimpleJdbcInsert
+
+ It's possible to limit the columns used for the insert by
+ specifying a list of column names to be used. This is accomplished using
+ the usingColumns method.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcInsert insertActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.insertActor =
+ new SimpleJdbcInsert(dataSource)
+ .withTableName("t_actor")
+ .usingColumns("first_name", "last_name")
+ .usingGeneratedKeyColumns("id");
+ }
+
+ public void add(Actor actor) {
+ Map<String, Object> parameters = new HashMap<String, Object>(2);
+ parameters.put("first_name", actor.getFirstName());
+ parameters.put("last_name", actor.getLastName());
+ Number newId = insertActor.executeAndReturnKey(parameters);
+ actor.setId(newId.longValue());
+ }
+
+ // ... additional methods
+}The execution of the insert is the same as if we had relied
+ on the metadata for determining what columns to use.
+
+
+
+ Using SqlParameterSource to provide parameter values
+
+ Using a Map to provide parameter values works fine, but it's not
+ the most convenient class to use. Spring provides a couple of
+ implementations of the SqlParameterSource
+ interface that can be used instead. The first one we'll look at is
+ BeanPropertySqlParameterSource which is a very
+ convenient class as long as you have a JavaBean compliant class that
+ contains your values. It will use the corresponding getter method to
+ extract the parameter values. Here is an example:
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcInsert insertActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.insertActor =
+ new SimpleJdbcInsert(dataSource)
+ .withTableName("t_actor")
+ .usingGeneratedKeyColumns("id");
+ }
+
+ public void add(Actor actor) {
+ SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor);
+ Number newId = insertActor.executeAndReturnKey(parameters);
+ actor.setId(newId.longValue());
+ }
+
+ // ... additional methods
+}Another option is the
+ MapSqlParameterSource that resembles a Map but
+ provides a more convenient addValue method that
+ can be chained.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcInsert insertActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.insertActor =
+ new SimpleJdbcInsert(dataSource)
+ .withTableName("t_actor")
+ .usingGeneratedKeyColumns("id");
+ }
+
+ public void add(Actor actor) {
+ SqlParameterSource parameters = new MapSqlParameterSource()
+ .addValue("first_name", actor.getFirstName())
+ .addValue("last_name", actor.getLastName());
+ Number newId = insertActor.executeAndReturnKey(parameters);
+ actor.setId(newId.longValue());
+ }
+
+ // ... additional methods
+}As you can see, the configuration is the same, it;s just the
+ executing code that has to change to use these alternative input
+ classes.
+
+
+
+ Calling a stored procedure using SimpleJdbcCall
+
+ Let's now turn our attention to calling stored procedures using
+ the SimpleJdbcCall class. This class is designed
+ to make it as simple as possible to call a stored procedure. It takes
+ advantage of metadata present in the database to look up names of in and
+ out parameters. This means that you don't have to explicitly declare
+ parameters. You can of course still declare them if you prefer to do
+ that or if you have parameters that don't have an automatic mapping to a
+ Java class like ARRAY or STRUCT parameters. In our first example we will
+ look at a plain vanilla procedure that only returns scalar values in
+ form of VARCHAR and DATE. I have added a birthDate property to the Actor
+ class to get some variety in terms of return values. The example
+ procedure reads a specified actor entry and returns first_name,
+ last_name, and birth_date columns in the form of out parameters. Here is
+ the source for the procedure as it would look when using MySQL as the
+ database:
+
+ CREATE PROCEDURE read_actor (
+ IN in_id INTEGER,
+ OUT out_first_name VARCHAR(100),
+ OUT out_last_name VARCHAR(100),
+ OUT out_birth_date DATE)
+BEGIN
+ SELECT first_name, last_name, birth_date
+ INTO out_first_name, out_last_name, out_birth_date
+ FROM t_actor where id = in_id;
+END;As you can see there are four parameters. One is an in
+ parameter "in_id" containing the id of the Actor we are looking up. The
+ remaining parameters are out parameters and they will be used to return
+ the data read from the table.
+
+ The SimpleJdbcCall is declared in a similar
+ manner to the SimpleJdbcInsert, no need to
+ subclass and we declare it in the initialization method. For this
+ example, all we need to specify is the name of the procedure.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcCall procReadActor;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ this.procReadActor =
+ new SimpleJdbcCall(dataSource)
+ .withProcedureName("read_actor");
+ }
+
+ public Actor readActor(Long id) {
+ SqlParameterSource in = new MapSqlParameterSource()
+ .addValue("in_id", id);
+ Map out = procReadActor.execute(in);
+ Actor actor = new Actor();
+ actor.setId(id);
+ actor.setFirstName((String) out.get("out_first_name"));
+ actor.setLastName((String) out.get("out_last_name"));
+ actor.setBirthDate((Date) out.get("out_birth_date"));
+ return actor;
+ }
+
+ // ... additional methods
+}The execution of the call involves creating an
+ SqlParameterSource containing the in parameter.
+ It's important to match the name of the parameter declared in the stored
+ procedure. The case doesn't have to match since we use metadata to
+ determine how database objects should be referred to - what you specify
+ in your source for the stored procedure is not necessarily the way it is
+ stored in the database, some databases transform names to all upper case
+ while others use lower case or the case as specified.
+
+ The execute method takes the in parameters
+ and returns a Map containing any out parameters keyed by the name as
+ specified in the stored procedure. In this case they are
+ out_first_name, out_last_name and
+ out_birth_date.
+
+ The last part of the execute method just
+ creates an Actor instance to use to return the data retrieved. Again,
+ it's important to match the names of the out parameters here. Also, the
+ case used for the names of the out parameters stored in the results map
+ are as they were defined in the database. You will either have to do a
+ case-insensitive lookup or instruct Spring to use a
+ CaseInsensitiveMap from the Jakarta Commons
+ project. The way you do that is by creating your own
+ JdbcTemplate and setting the
+ setResultsMapCaseInsensitive property to
+ true. Then you pass this customized
+ JdbcTemplate instance into the constructor of
+ your SimpleJdbcCall. You also have to include the
+ commons-collections.jar on your classpath for
+ this to work. Here is an example of this configuration:
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcCall procReadActor;
+
+ public void setDataSource(DataSource dataSource) {
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ jdbcTemplate.setResultsMapCaseInsensitive(true);
+ this.procReadActor =
+ new SimpleJdbcCall(jdbcTemplate)
+ .withProcedureName("read_actor");
+ }
+
+
+ // ... additional methods
+}By doing this, you don't have to worry about the case used
+ for the names of your returned out parameters.
+
+
+
+ Declaring parameters to use for a SimpleJdbcCall
+
+ We have seen how the parameters are deduced based on metadata, but
+ you can declare then explicitly if you wish. This is done when the
+ SimpleJdbcCall is created and configured using
+ the declareParameters method that takes a
+ variable number of SqlParameter objects as input.
+ See the next section for details on how to define an
+ SqlParameter.
+
+ We can opt to declare one, some or all of the parameters
+ explicitly. The parameter metadata is still being used. By calling the
+ method withoutProcedureColumnMetaDataAccess we
+ can specify that we would like to bypass any processing of the metadata
+ lookups for potential parameters and only use the declared ones. Another
+ situation that can arise is that one or more in parameters have default
+ values and we would like to leave them out of the call. To do that we
+ will just call the useInParameterNames to specify
+ the list of in parameter names to include.
+
+ This is what a fully declared procedure call declaration of our
+ earlier example would look like:
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcCall procReadActor;
+
+ public void setDataSource(DataSource dataSource) {
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ jdbcTemplate.setResultsMapCaseInsensitive(true);
+ this.procReadActor =
+ new SimpleJdbcCall(jdbcTemplate)
+ .withProcedureName("read_actor")
+ .withoutProcedureColumnMetaDataAccess()
+ .useInParameterNames("in_id")
+ .declareParameters(
+ new SqlParameter("in_id", Types.NUMERIC),
+ new SqlOutParameter("out_first_name", Types.VARCHAR),
+ new SqlOutParameter("out_last_name", Types.VARCHAR),
+ new SqlOutParameter("out_birth_date", Types.DATE)
+ );
+ }
+
+
+ // ... additional methods
+}The execution and end results are the same, we are just
+ specifying all the details explicitly rather than relying on metadata.
+ This will be necessary if the database we use is not part of the
+ supported databases. Currently we support metadata lookup of stored
+ procedure calls for the following databases: Apache Derby, DB2, MySQL,
+ Microsoft SQL Server, Oracle and Sybase. We also support metadata lookup
+ of stored functions for: MySQL, Microsoft SQL Server and Oracle.
+
+
+
+ How to define SqlParameters
+
+ To define a parameter to be used for the SimpleJdbc classes, and
+ also for the RDBMS operations classes covered in the following section,
+ you use an SqlParameter or one of its subclasses.
+ You typically specify the parameter name and SQL type in the
+ constructor. The SQL type is specified using the
+ java.sql.Types constants. We have already seen
+ declarations like:
+
+ new SqlParameter("in_id", Types.NUMERIC),
+ new SqlOutParameter("out_first_name", Types.VARCHAR),
+
+ The first line with the SqlParameter
+ declares an in parameter. In parameters can be used for both stored
+ procedure calls and for queries using the
+ SqlQuery and its subclasses covered in the
+ following section.
+
+ The second line with the SqlOutParameter
+ declares an out parameter to be used in a stored procedure call. There
+ is also an SqlInOutParameter for inout
+ parameters, parameters that provide an in value to the procedure and
+ that also return a value
+
+
+ Only parameters declared as SqlParameter
+ and SqlInOutParameter will be used to provide
+ input values. This is different from the
+ StoredProcedure class which for backwards
+ compatibility reasons allows input values to be provided for
+ parameters declared as SqlOutParameter.
+
+
+ In addition to the name and the SQL type you can specify
+ additional options. For in parameters you can specify a scale for
+ numeric data or a type name for custom database types. For out
+ parameters you can provide a RowMapper to handle
+ mapping of rows returned from a REF cursor. Another option is to specify
+ an SqlReturnType that provides and opportunity to
+ define customized handling of the return values.
+
+
+
+ Calling a stored function using SimpleJdbcCall
+
+ Calling a stored function is done almost exactly the same way as
+ calling a stored procedure. The only difference is that you need to
+ provide a function name rather than a procedure name. This is done by
+ using the withFunctionName method. Using this
+ method indicates that your call is to a function and the corresponding
+ call string for a function call will be generated. There is also a
+ specialized execute call executeFunction that
+ will return the function return value as an object of a specified type.
+ This way you don't have to retrieve the return value from the results
+ map. A similar convenience method named
+ executeObject is also available for stored
+ procedures that only have one out parameter. The following example is
+ based on a stored function named get_actor_name
+ that returns an actor's full name. Here is the MySQL source for this
+ function:
+
+ CREATE FUNCTION get_actor_name (in_id INTEGER)
+RETURNS VARCHAR(200) READS SQL DATA
+BEGIN
+ DECLARE out_name VARCHAR(200);
+ SELECT concat(first_name, ' ', last_name)
+ INTO out_name
+ FROM t_actor where id = in_id;
+ RETURN out_name;
+END;
+
+ To call this function we again create a
+ SimpleJdbcCall in the initialization
+ method.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcCall funcGetActorName;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ jdbcTemplate.setResultsMapCaseInsensitive(true);
+ this.funcGetActorName =
+ new SimpleJdbcCall(jdbcTemplate)
+ .withFunctionName("get_actor_name");
+ }
+
+ public String getActorName(Long id) {
+ SqlParameterSource in = new MapSqlParameterSource()
+ .addValue("in_id", id);
+ String name = funcGetActorName.executeFunction(String.class, in);
+ return name;
+ }
+
+ // ... additional methods
+}The execute method used returns a
+ String containing the return value from the
+ function call.
+
+
+
+ Returning ResultSet/REF Cursor from a SimpleJdbcCall
+
+ Calling a stored procedure or function that returns a result set
+ has always been a bit tricky. Some databases return result sets during
+ the JDBC results processing while others require an explicitly
+ registered out parameter of a specific type. Both approaches still needs
+ some additional processing to loop over the result set and process the
+ returned rows. With the SimpleJdbcCall you use
+ the returningResultSet method and declare a
+ RowMapper implementation to be used for a
+ specific parameter. In the case where the result set is returned during
+ the results processing, there are no names defined, so the returned
+ results will have to match the order you declare the
+ RowMapper implementations. The name specified
+ will still be used to store the processed list of results in the results
+ map returned from the execute statement.
+
+ For this example we will use a stored procedure that takes no in
+ parameters and returns all rows from the t_actor table. Here is the
+ MySQL source for this procedure:
+
+ CREATE PROCEDURE read_all_actors()
+BEGIN
+ SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a;
+END;In order to call this procedure we need to declare the
+ RowMapper to be used. Since the class we want to
+ map to follows the JavaBean rules, we can use a
+ ParameterizedBeanPropertyRowMapper that is
+ created by passing in the required class to map to in the
+ newInstance method.
+
+ public class JdbcActorDao implements ActorDao {
+ private SimpleJdbcTemplate simpleJdbcTemplate;
+ private SimpleJdbcCall procReadAllActors;
+
+ public void setDataSource(DataSource dataSource) {
+ this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ jdbcTemplate.setResultsMapCaseInsensitive(true);
+ this.procReadAllActors =
+ new SimpleJdbcCall(jdbcTemplate)
+ .withProcedureName("read_all_actors")
+ .returningResultSet("actors",
+ ParameterizedBeanPropertyRowMapper.newInstance(Actor.class));
+ }
+
+ public List getActorsList() {
+ Map m = procReadAllActors.execute(new HashMap<String, Object>(0));
+ return (List) m.get("actors");
+ }
+
+ // ... additional methods
+}The execute call passes in an empty Map since this call
+ doesn't take any parameters. The list of Actors is then retrieved from
+ the results map and returned to the caller.
+
+
+
+
+ Modeling JDBC operations as Java objects
+
+ The org.springframework.jdbc.object package
+ contains classes that allow one to access the database in a more
+ object-oriented manner. By way of an example, one can execute queries and
+ get the results back as a list containing business objects with the
+ relational column data mapped to the properties of the business object.
+ One can also execute stored procedures and run update, delete and insert
+ statements.
+
+
+ There is a view borne from experience acquired in the field
+ amongst some of the Spring developers that the various RDBMS operation
+ classes described below (with the exception of the StoredProcedure
+ class) can often be replaced with straight
+ JdbcTemplate calls... often it is simpler to use
+ and plain easier to read a DAO method that simply calls a method on a
+ JdbcTemplate direct (as opposed to encapsulating
+ a query as a full-blown class).
+
+ It must be stressed however that this is just a
+ view... if you feel that you are getting measurable
+ value from using the RDBMS operation classes, feel free to continue
+ using these classes.
+
+
+
+ SqlQuery
+
+ SqlQuery is a reusable, threadsafe class
+ that encapsulates an SQL query. Subclasses must implement the
+ newRowMapper(..) method to provide a
+ RowMapper instance that can create one
+ object per row obtained from iterating over the
+ ResultSet that is created during the
+ execution of the query. The SqlQuery class is
+ rarely used directly since the MappingSqlQuery
+ subclass provides a much more convenient implementation for mapping rows
+ to Java classes. Other implementations that extend
+ SqlQuery are
+ MappingSqlQueryWithParameters and
+ UpdatableSqlQuery.
+
+
+
+ MappingSqlQuery
+
+ MappingSqlQuery is a reusable query in
+ which concrete subclasses must implement the abstract
+ mapRow(..) method to convert each row of the
+ supplied ResultSet into an object. Find
+ below a brief example of a custom query that maps the data from the
+ customer relation to an instance of the Customer
+ class.
+
+ private class CustomerMappingQuery extends MappingSqlQuery {
+
+ public CustomerMappingQuery(DataSource ds) {
+ super(ds, "SELECT id, name FROM customer WHERE id = ?");
+ super.declareParameter(new SqlParameter("id", Types.INTEGER));
+ compile();
+ }
+
+ public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
+ Customer cust = new Customer();
+ cust.setId((Integer) rs.getObject("id"));
+ cust.setName(rs.getString("name"));
+ return cust;
+ }
+}
+
+ We provide a constructor for this customer query that takes the
+ DataSource as the only parameter. In this
+ constructor we call the constructor on the superclass with the
+ DataSource and the SQL that should be
+ executed to retrieve the rows for this query. This SQL will be used to
+ create a PreparedStatement so it may
+ contain place holders for any parameters to be passed in during
+ execution. Each parameter must be declared using the
+ declareParameter method passing in an
+ SqlParameter. The
+ SqlParameter takes a name and the JDBC type as
+ defined in java.sql.Types. After all parameters
+ have been defined we call the compile() method so the
+ statement can be prepared and later be executed.
+
+ public Customer getCustomer(Integer id) {
+ CustomerMappingQuery custQry = new CustomerMappingQuery(dataSource);
+ Object[] parms = new Object[1];
+ parms[0] = id;
+ List customers = custQry.execute(parms);
+ if (customers.size() > 0) {
+ return (Customer) customers.get(0);
+ }
+ else {
+ return null;
+ }
+}
+
+ The method in this example retrieves the customer with the id that
+ is passed in as the only parameter. After creating an instance of the
+ CustomerMappingQuery class we create an array of
+ objects that will contain all parameters that are passed in. In this
+ case there is only one parameter and it is passed in as an
+ Integer. Now we are ready to execute the query
+ using this array of parameters and we get a List that
+ contains a Customer object for each row that was
+ returned for our query. In this case it will only be one entry if there
+ was a match.
+
+
+
+ SqlUpdate
+
+ The SqlUpdate class encapsulates an SQL
+ update. Like a query, an update object is reusable, and like all
+ RdbmsOperation classes, an update can have
+ parameters and is defined in SQL. This class provides a number of
+ update(..) methods analogous to the
+ execute(..) methods of query objects. This
+ class is concrete. Although it can be subclassed (for example to add a
+ custom update method) it can easily be parameterized by setting SQL and
+ declaring parameters.
+
+ import java.sql.Types;
+
+import javax.sql.DataSource;
+
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.object.SqlUpdate;
+
+public class UpdateCreditRating extends SqlUpdate {
+
+ public UpdateCreditRating(DataSource ds) {
+ setDataSource(ds);
+ setSql("update customer set credit_rating = ? where id = ?");
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ declareParameter(new SqlParameter(Types.NUMERIC));
+ compile();
+ }
+
+ /**
+ * @param id for the Customer to be updated
+ * @param rating the new value for credit rating
+ * @return number of rows updated
+ */
+ public int run(int id, int rating) {
+ Object[] params =
+ new Object[] {
+ new Integer(rating),
+ new Integer(id)};
+ return update(params);
+ }
+}
+
+
+
+ StoredProcedure
+
+ The StoredProcedure class is a superclass
+ for object abstractions of RDBMS stored procedures. This class is
+ abstract, and its various
+ execute(..) methods have protected
+ access, preventing use other than through a subclass that offers tighter
+ typing.
+
+ The inherited sql property will be the name of
+ the stored procedure in the RDBMS.
+
+ To define a parameter to be used for the StoredProcedure classe,
+ you use an SqlParameter or one of its subclasses.
+ You must specify the parameter name and SQL type in the constructor. The
+ SQL type is specified using the java.sql.Types
+ constants. We have already seen declarations like:
+
+ new SqlParameter("in_id", Types.NUMERIC),
+ new SqlOutParameter("out_first_name", Types.VARCHAR),
+
+ The first line with the SqlParameter
+ declares an in parameter. In parameters can be used for both stored
+ procedure calls and for queries using the
+ SqlQuery and its subclasses covered in the
+ following section.
+
+ The second line with the SqlOutParameter
+ declares an out parameter to be used in the stored procedure call. There
+ is also an SqlInOutParameter for inout
+ parameters, parameters that provide an in value to the procedure and
+ that also return a value
+
+
+ Parameters declared as SqlParameter
+ and SqlInOutParameter will always be used to
+ provide input values. In addition to this any parameter declared as
+ SqlOutParameter where an non-null input value
+ is provided will also be used as an input paraneter.
+
+
+ In addition to the name and the SQL type you can specify
+ additional options. For in parameters you can specify a scale for
+ numeric data or a type name for custom database types. For out
+ parameters you can provide a RowMapper to handle
+ mapping of rows returned from a REF cursor. Another option is to specify
+ an SqlReturnType that provides and opportunity to
+ define customized handling of the return values.
+
+ Here is an example of a program that calls a function,
+ sysdate(), that comes with any Oracle database. To
+ use the stored procedure functionality one has to create a class that
+ extends StoredProcedure. There are no input
+ parameters, but there is an output parameter that is declared as a date
+ type using the class SqlOutParameter. The
+ execute() method returns a map with an entry for each
+ declared output parameter using the parameter name as the key.
+
+ import java.sql.Types;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.datasource.*;
+import org.springframework.jdbc.object.StoredProcedure;
+
+public class TestStoredProcedure {
+
+ public static void main(String[] args) {
+ TestStoredProcedure t = new TestStoredProcedure();
+ t.test();
+ System.out.println("Done!");
+ }
+
+ void test() {
+ DriverManagerDataSource ds = new DriverManagerDataSource();
+ ds.setDriverClassName("oracle.jdbc.OracleDriver");
+ ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");
+ ds.setUsername("scott");
+ ds.setPassword("tiger");
+
+ MyStoredProcedure sproc = new MyStoredProcedure(ds);
+ Map results = sproc.execute();
+ printMap(results);
+ }
+
+ private class MyStoredProcedure extends StoredProcedure {
+
+ private static final String SQL = "sysdate";
+
+ public MyStoredProcedure(DataSource ds) {
+ setDataSource(ds);
+ setFunction(true);
+ setSql(SQL);
+ declareParameter(new SqlOutParameter("date", Types.DATE));
+ compile();
+ }
+
+ public Map execute() {
+ // the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
+ return execute(new HashMap());
+ }
+ }
+
+ private static void printMap(Map results) {
+ for (Iterator it = results.entrySet().iterator(); it.hasNext(); ) {
+ System.out.println(it.next());
+ }
+ }
+}
+
+ Find below an example of a StoredProcedure
+ that has two output parameters (in this case Oracle REF cursors).
+
+ import oracle.jdbc.driver.OracleTypes;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.object.StoredProcedure;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TitlesAndGenresStoredProcedure extends StoredProcedure {
+
+ private static final String SPROC_NAME = "AllTitlesAndGenres";
+
+ public TitlesAndGenresStoredProcedure(DataSource dataSource) {
+ super(dataSource, SPROC_NAME);
+ declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper()));
+ declareParameter(new SqlOutParameter("genres", OracleTypes.CURSOR, new GenreMapper()));
+ compile();
+ }
+
+ public Map execute() {
+ // again, this sproc has no input parameters, so an empty Map is supplied...
+ return super.execute(new HashMap());
+ }
+}
+
+ Notice how the overloaded variants of the
+ declareParameter(..) method that have been used in
+ the TitlesAndGenresStoredProcedure constructor
+ are passed RowMapper implementation
+ instances; this is a very convenient and powerful way to reuse existing
+ functionality. (The code for the two
+ RowMapper implementations is provided
+ below in the interest of completeness.)
+
+ Firstly the TitleMapper class, which simply
+ maps a ResultSet to a
+ Title domain object for each row in the supplied
+ ResultSet.
+
+ import com.foo.sprocs.domain.Title;
+import org.springframework.jdbc.core.RowMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public final class TitleMapper implements RowMapper {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ Title title = new Title();
+ title.setId(rs.getLong("id"));
+ title.setName(rs.getString("name"));
+ return title;
+ }
+}
+
+ Secondly, the GenreMapper class, which
+ again simply maps a ResultSet to a
+ Genre domain object for each row in the supplied
+ ResultSet.
+
+ import org.springframework.jdbc.core.RowMapper;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import com.foo.domain.Genre;
+
+public final class GenreMapper implements RowMapper {
+
+ public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new Genre(rs.getString("name"));
+ }
+}
+
+ If one needs to pass parameters to a stored procedure (that is the
+ stored procedure has been declared as having one or more input
+ parameters in its definition in the RDBMS), one would code a strongly
+ typed execute(..) method which would delegate to the
+ superclass' (untyped) execute(Map parameters) (which
+ has protected access); for example:
+
+ import oracle.jdbc.driver.OracleTypes;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.object.StoredProcedure;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TitlesAfterDateStoredProcedure extends StoredProcedure {
+
+ private static final String SPROC_NAME = "TitlesAfterDate";
+ private static final String CUTOFF_DATE_PARAM = "cutoffDate";
+
+ public TitlesAfterDateStoredProcedure(DataSource dataSource) {
+ super(dataSource, SPROC_NAME);
+ declareParameter(new SqlParameter(CUTOFF_DATE_PARAM, Types.DATE);
+ declareParameter(new SqlOutParameter("titles", OracleTypes.CURSOR, new TitleMapper()));
+ compile();
+ }
+
+ public Map execute(Date cutoffDate) {
+ Map inputs = new HashMap();
+ inputs.put(CUTOFF_DATE_PARAM, cutoffDate);
+ return super.execute(inputs);
+ }
+}
+
+
+
+ SqlFunction
+
+ The SqlFunction RDBMS operation class
+ encapsulates an SQL "function" wrapper for a query that returns a single
+ row of results. The default behavior is to return an
+ int, but that can be overridden by using the methods
+ with an extra return type parameter. This is similar to using the
+ queryForXxx methods of the
+ JdbcTemplate. The advantage with
+ SqlFunction is that you don't have to create the
+ JdbcTemplate, it is done behind the
+ scenes.
+
+ This class is intended to use to call SQL functions that return a
+ single result using a query like "select user()" or "select sysdate from
+ dual". It is not intended for calling more complex stored functions or
+ for using a CallableStatement to invoke a stored
+ procedure or stored function. (Use the
+ StoredProcedure or SqlCall
+ classes for this type of processing).
+
+ SqlFunction is a concrete class, and there
+ is typically no need to subclass it. Code using this package can create
+ an object of this type, declaring SQL and parameters, and then invoke
+ the appropriate run method repeatedly to execute the function. Here is
+ an example of retrieving the count of rows from a table:
+
+ public int countRows() {
+ SqlFunction sf = new SqlFunction(dataSource, "select count(*) from mytable");
+ sf.compile();
+ return sf.run();
+}
+
+
+
+
+ Common issues with parameter and data value handling
+
+ There are some issues involving parameters and data values that are
+ common across all the different approaches provided by the Spring JDBC
+ Framework.
+
+
+ Providing SQL type information for parameters
+
+ Most of the time Spring will assume the SQL type of the parameters
+ based on the type of parameter passed in. It is possible to explicitly
+ provide the SQL type to be used when setting parameter values. This is
+ sometimes necessary to correctly set NULL values.
+
+ There are a few different ways this can be accomplished:
+
+
+
+ Many of the update and query methods of the
+ JdbcTemplate take an additional parameter in
+ the form of an int array. This array should contain the SQL type
+ using constant values from the java.sql.Types
+ class. There must be one entry for each parameter.
+
+
+
+
+
+ You can wrap the parameter value that needs this additional
+ information using the SqlParameterValue
+ class. Create a new instance for each value and pass in the SQL type
+ and parameter value in the constructor. You can also provide an
+ optional scale parameter for numeric values.
+
+
+
+
+
+ For methods working with named parameters, you can use the
+ SqlParameterSource classes
+ BeanPropertySqlParameterSource or
+ MapSqlParameterSource. They both have methods
+ for registering the SQL type for any of the named parameter
+ values.
+
+
+
+
+
+ Handling BLOB and CLOB objects
+
+ You can store images and other binary objects as well and large
+ chunks of text. These large object are called BLOB for binary data and
+ CLOB for character data. Spring lets you handle these large objects
+ using the JdbcTemplate directly and also when using the higher
+ abstractions provided by RDBMS Objects and the SimpleJdbc classes. All
+ of these approaches use an implementation of the
+ LobHandler interface for the actual management of
+ the LOB data. The LobHandler provides access to a
+ LobCreator, via the
+ getLobCreator method, for creating new LOB
+ objects to be inserted.
+
+ The LobCreator/LobHandler provides the
+ following support for LOB in- and output:
+
+
+
+ BLOB
+
+
+
+ byte[] – getBlobAsBytes and setBlobAsBytes
+
+
+
+ InputStream – getBlobAsBinaryStream and
+ setBlobAsBinaryStream
+
+
+
+
+
+ CLOB
+
+
+
+ String – getClobAsString and setClobAsString
+
+
+
+ InputStream – getClobAsAsciiStream and
+ setClobAsAsciiStream
+
+
+
+ Reader – getClobAsCharacterStream and
+ setClobAsCharacterStream
+
+
+
+
+
+ We will now show an example of how to create and insert a BLOB. We
+ will later see how to read it back from the database.
+
+ This example uses a JdbcTemplate and an implementation of the
+ AbstractLobCreatingPreparedStatementCallback. There is one method that
+ must be implemented and it is "setValues". In this method you will be
+ provided with a LobCreator that can be used to set the values for the
+ LOB columns in your SQL insert statement.
+
+ We are assuming that we have a variable named 'lobHandler' that
+ already is set to an instance of a
+ DefaultLobHandler. This is typically done using
+ dependency injection.
+
+
+
+
+
+
+
+
+
+
+ final File blobIn = new File("spring2004.jpg");
+final InputStream blobIs = new FileInputStream(blobIn);
+final File clobIn = new File("large.txt");
+final InputStream clobIs = new FileInputStream(clobIn);
+final InputStreamReader clobReader = new InputStreamReader(clobIs);
+jdbcTemplate.execute(
+ "INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)",
+ new AbstractLobCreatingPreparedStatementCallback(lobhandler) {
+ protected void setValues(PreparedStatement ps, LobCreator lobCreator)
+ throws SQLException {
+ ps.setLong(1, 1L);
+ lobCreator.setClobAsCharacterStream(ps, 2, clobReader, (int)clobIn.length());
+ lobCreator.setBlobAsBinaryStream(ps, 3, blobIs, (int)blobIn.length());
+ }
+ }
+);
+blobIs.close();
+clobReader.close();
+
+
+
+ Here we use the lobHandler that in this example is a plain
+ DefaultLobHandler
+
+
+
+ Using the method setClobAsCharacterStream
+ we pass in the contents of the CLOB
+
+
+
+ Using the method
+ setBlobAsBinartStream we pass in the
+ contents of the BLOB
+
+
+
+
+ Now it's time to read the LOB data from the database. Again, we
+ use a JdbcTempate and we have the same instance variable 'lobHandler'
+ with a reference to a DefaultLobHandler.
+
+
+
+
+
+
+
+
+ List l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table",
+ new RowMapper() {
+ public Object mapRow(ResultSet rs, int i) throws SQLException {
+ Map results = new HashMap();
+ String clobText = lobHandler.getClobAsString(rs, "a_clob");
+ results.put("CLOB", clobText);
+ byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "a_blob");
+ results.put("BLOB", blobBytes);
+ return results;
+ }
+ });
+
+
+
+
+ Using the method getClobAsString we
+ retrieve the contents of the CLOB
+
+
+
+ Using the method getBlobAsBytes we
+ retrieve the contents of the BLOB
+
+
+
+
+
+
+ Passing in lists of values for IN clause
+
+ The SQL standard allows for selecting rows based on an expression
+ that includes a variable list of values. A typical example would be
+ "select * from T_ACTOR where id in (1, 2, 3)". This variable list is not
+ directly supported for prepared statements by the JDBC standard - there
+ is no way of declaring a variable number of place holders. You would
+ have to either have a number of variations with the desired number of
+ place holders prepared or you would have to dynamically generate the SQL
+ string once you know how many place holders are required. The named
+ parameter support provided in the
+ NamedParameterJdbcTemplate and
+ SimpleJdbcTemplate takes the latter approach.
+ When you pass in the values you should pass them in as a
+ java.util.List of primitive objects. This list
+ will be used to insert the required place holders and pass in the values
+ during the statement execution.
+
+
+ You need to be careful when passing in a large number of values.
+ The JDBC standard doesn't guarantee that you can use more than 100
+ values for an IN expression list. Various databases exceed this
+ number, but they usually have a hard limit for how many values are
+ allowed. Oracle's limit for instance is 1000.
+
+
+ In addition to the primitive values in the value list, you can
+ create a java.util.List of object arrays. This
+ would support a case where there are multiple expressions defined for
+ the IN clause like "select * from T_ACTOR where (id, last_name) in ((1,
+ 'Johnson'), (2, 'Harrop'))". This of course requires that your database
+ supports this syntax.
+
+
+
+ Handling complex types for stored procedure calls
+
+ When calling stored procedures it's sometimes possible to use
+ complex types specific to the database. To accommodate these types
+ Spring provides a SqlReturnType for handling them
+ when they are returned from the stored procedure call and
+ SqlTypeValue when they are passed in as a
+ parameter to the stored procedure.
+
+ Here is an example of returning the value of an Oracle STRUCT
+ object of the user declared type "ITEM_TYPE". The
+ SqlReturnType interface has a single method named
+ "getTypeValue" that must be implemented. This
+ interface is used as part of the declaration of an
+ SqlOutParameter.
+
+ declareParameter(new SqlOutParameter("item", OracleTypes.STRUCT, "ITEM_TYPE",
+ new SqlReturnType() {
+ public Object getTypeValue(CallableStatement cs, int colIndx, int sqlType, String typeName)
+ throws SQLException {
+ STRUCT struct = (STRUCT)cs.getObject(colIndx);
+ Object[] attr = struct.getAttributes();
+ TestItem item = new TestItem();
+ item.setId(((Number) attr[0]).longValue());
+ item.setDescription((String)attr[1]);
+ item.setExpirationDate((java.util.Date)attr[2]);
+ return item;
+ }
+ }));Going from Java to the database and passing in the
+ value of a TestItem into a stored procedure is
+ done using the SqlTypeValue. The
+ SqlTypeValue interface has a single method named
+ "createTypeValue" that must be implemented. The
+ active connection is passed in and can be used to create database
+ specific objects like StructDescriptors or
+ ArrayDescriptors
+
+ SqlTypeValue value = new AbstractSqlTypeValue() {
+ protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
+ StructDescriptor itemDescriptor = new StructDescriptor(typeName, conn);
+ Struct item = new STRUCT(itemDescriptor, conn,
+ new Object[] {
+ testItem.getId(),
+ testItem.getDescription(),
+ new java.sql.Date(testItem.getExpirationDate().getTime())
+ });
+ return item;
+ }
+};This SqlTypeValue can now be added
+ to the Map containing the input parameters for the execute call of the
+ stored procedure.
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/jms.xml b/spring-framework-reference/src/jms.xml
new file mode 100644
index 00000000000..4d5de40584b
--- /dev/null
+++ b/spring-framework-reference/src/jms.xml
@@ -0,0 +1,1217 @@
+
+
+ JMS (Java Message Service)
+
+
+ Introduction
+
+ Spring provides a JMS integration framework that simplifies the use
+ of the JMS API and shields the user from differences between the JMS 1.0.2
+ and 1.1 APIs.
+ JMS can be roughly divided into two areas of functionality, namely the
+ production and consumption of messages. The JmsTemplate
+ class is used for message production and synchronous message reception. For
+ asynchronous reception similar to J2EE's message-driven bean style, Spring
+ provides a number of message listener containers that are used to create
+ Message-Driven POJOs (MDPs).
+
+
+ Domain Unification
+ There are two major releases of the JMS specification, 1.0.2 and
+ 1.1.
+ 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
+ Session.
+
+
+ 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.
+
+
+
+ The package org.springframework.jms.core provides
+ the core functionality for using JMS. It contains JMS template classes
+ that simplifies the use of the JMS by handling the creation and release of
+ resources, much like the JdbcTemplate does for
+ JDBC. The design principle common to Spring template classes is to provide
+ helper methods to perform common operations and for more sophisticated
+ usage, delegate the essence of the processing task to user implemented
+ callback interfaces. The JMS template follows the same design. The classes
+ offer various convenience methods for the sending of messages, consuming a
+ message synchronously, and exposing the JMS session and message producer
+ to the user.
+
+ The package org.springframework.jms.support
+ provides JMSException translation functionality. The translation converts
+ the checked JMSException hierarchy to a mirrored
+ hierarchy of unchecked exceptions. If there are any provider specific
+ subclasses of the checked javax.jms.JMSException,
+ this exception is wrapped in the unchecked
+ UncategorizedJmsException.
+ The package org.springframework.jms.support.converter provides a
+ MessageConverter abstraction to convert between Java objects
+ and JMS messages.
+ The package org.springframework.jms.support.destination provides
+ various strategies for managing JMS destinations, such as providing a
+ service locator for destinations stored in JNDI.
+
+ Finally, the package
+ org.springframework.jms.connection provides an
+ implementation of the ConnectionFactory suitable
+ for use in standalone applications. It also contains an implementation of
+ Spring's PlatformTransactionManager for
+ JMS (the cunningly named JmsTransactionManager).
+ This allows for seamless integration of JMS as a transactional resource into
+ Spring's transaction management mechanisms.
+
+
+
+ Using Spring JMS
+
+
+ JmsTemplate
+
+ There are two variants of the functionality offered by the
+ JmsTemplate: the JmsTemplate
+ uses the JMS 1.1 API, and the subclass JmsTemplate102
+ uses the JMS 1.0.2 API.
+
+ Code that uses the JmsTemplate only needs to
+ implement callback interfaces giving them a clearly defined contract. The
+ MessageCreator callback interface creates a message
+ given a Session provided by the calling code
+ in JmsTemplate. In order to allow for more complex
+ usage of the JMS API, the callback SessionCallback
+ provides the user with the JMS session and the callback
+ ProducerCallback exposes a
+ Session and
+ MessageProducer pair.
+
+ The JMS API exposes two types of send methods, one that takes
+ delivery mode, priority, and time-to-live as Quality of Service (QOS)
+ parameters and one that takes no QOS parameters which uses default values.
+ Since there are many send methods in JmsTemplate,
+ the setting of the QOS parameters have been exposed as bean properties to
+ avoid duplication in the number of send methods. Similarly, the timeout
+ value for synchronous receive calls is set using the property
+ setReceiveTimeout.
+
+ Some JMS providers allow the setting of default QOS values
+ administratively through the configuration of the ConnectionFactory. This
+ has the effect that a call to MessageProducer's
+ send method send(Destination destination, Message
+ message) will use different QOS default values than those
+ specified in the JMS specification. In order to provide consistent
+ management of QOS values, the JmsTemplate must
+ therefore be specifically enabled to use its own QOS values by setting
+ the boolean property isExplicitQosEnabled
+ to true.
+
+
+ Instances of the JmsTemplate class are
+ thread-safe once configured. This is important because
+ it means that you can configure a single instance of a
+ JmsTemplate and then safely inject this
+ shared reference into multiple collaborators. To be
+ clear, the JmsTemplate is stateful, in that it
+ maintains a reference to a ConnectionFactory,
+ but this state is not conversational state.
+
+
+
+
+ Connections
+
+ The JmsTemplate requires a reference to a
+ ConnectionFactory. The
+ ConnectionFactory is part of the JMS
+ specification and serves as the entry point for working with JMS. It is
+ used by the client application as a factory to create connections with
+ the JMS provider and encapsulates various configuration parameters, many
+ of which are vendor specific such as SSL configuration options.
+
+ When using JMS inside an EJB, the vendor provides implementations
+ of the JMS interfaces so that they can participate in declarative
+ transaction management and perform pooling of connections and session.
+ In order to use this implementation, J2EE containers typically require
+ that you declare a JMS connection factory as a
+ resource-ref inside the EJB or servlet deployment
+ descriptors. To ensure the use of these features with the
+ JmsTemplate inside an EJB, the client application
+ should ensure that it references the managed implementation of the
+ ConnectionFactory.
+
+ Spring provides an implementation of the
+ ConnectionFactory interface,
+ SingleConnectionFactory, that will return the
+ same Connection on all
+ createConnection calls and ignore calls to
+ close. This is useful for testing and
+ standalone environments so that the same connection can be used for
+ multiple JmsTemplate calls that may span any
+ number of transactions. SingleConnectionFactory
+ takes a reference to a standard ConnectionFactory
+ that would typically come from JNDI.
+
+
+
+ Destination Management
+
+ Destinations, like ConnectionFactories, are JMS administered
+ objects that can be stored and retrieved in JNDI. When configuring a
+ Spring application context you can use the JNDI factory class
+ JndiObjectFactoryBean to perform dependency
+ injection on your object's references to JMS destinations. However,
+ often this strategy is cumbersome if there are a large number of
+ destinations in the application or if there are advanced destination
+ management features unique to the JMS provider. Examples of such
+ advanced destination management would be the creation of dynamic
+ destinations or support for a hierarchical namespace of destinations.
+ The JmsTemplate delegates the resolution of a
+ destination name to a JMS destination object to an implementation of the
+ interface DestinationResolver.
+ DynamicDestinationResolver is the default
+ implementation used by JmsTemplate and
+ accommodates resolving dynamic destinations. A
+ JndiDestinationResolver is also provided that
+ acts as a service locator for destinations contained in JNDI and
+ optionally falls back to the behavior contained in
+ DynamicDestinationResolver.
+
+ Quite often the destinations used in a JMS application are only
+ known at runtime and therefore cannot be administratively created when
+ the application is deployed. This is often because there is shared
+ application logic between interacting system components that create
+ destinations at runtime according to a well-known naming convention.
+ Even though the creation of dynamic destinations are not part of the JMS
+ specification, most vendors have provided this functionality. Dynamic
+ destinations are created with a name defined by the user which
+ differentiates them from temporary destinations and are often not
+ registered in JNDI. The API used to create dynamic destinations varies
+ from provider to provider since the properties associated with the
+ destination are vendor specific. However, a simple implementation choice
+ that is sometimes made by vendors is to disregard the warnings in the
+ JMS specification and to use the TopicSession
+ method createTopic(String topicName) or the
+ QueueSession method
+ createQueue(String queueName) to create a new
+ destination with default destination properties. Depending on the vendor
+ implementation, DynamicDestinationResolver may
+ then also create a physical destination instead of only resolving
+ one.
+
+ The boolean property pubSubDomain is used to
+ configure the JmsTemplate 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.
+ In the 1.0.2 implementation the value of this property determines if the
+ JmsTemplate's send operations will send a message
+ to a Queue or to a Topic.
+ This flag has no effect on send operations for
+ the 1.1 implementation. However, in both implementations, this property
+ determines the behavior of dynamic destination resolution via
+ implementations of the DestinationResolver interface.
+
+ You can also configure the JmsTemplate with
+ a default destination via the property
+ defaultDestination. The default destination will be
+ used with send and receive operations that do not refer to a specific
+ destination.
+
+
+
+ Message Listener Containers
+
+ One of the most common uses of JMS messages in the EJB world is to
+ drive message-driven beans (MDBs). Spring offers a solution to create
+ message-driven POJOs (MDPs) in a way that does not tie a user to an EJB
+ container. (See the section entitled
+ for detailed coverage of Spring's MDP support.)
+
+ A message listener container is used to receive messages
+ from a JMS message queue and drive the MessageListener that is
+ injected into it. The listener container is responsible for all
+ threading of message reception and dispatches into the listener
+ for processing. A message listener container is the intermediary between an
+ MDP and a messaging provider, and takes care of registering to receive messages,
+ participating in transactions, resource acquisition and release, exception
+ conversion and suchlike. This allows you as an application developer to write
+ the (possibly complex) business logic associated with receiving a message
+ (and possibly responding to it), and delegates boilerplate JMS
+ infrastructure concerns to the framework.
+
+ There are three standard JMS message listener containers packaged
+ with Spring, each with its specialised feature set.
+
+
+ SimpleMessageListenerContainer
+
+ This message listener container is the simplest of the three
+ standard flavors. It simply creates a fixed number of JMS sessions
+ at startup and uses them throughout the lifespan of the container.
+ This container doesn't allow for dynamic adaption to runtime demands
+ or participate in externally managed transactions. However,
+ it does have the fewest requirements on the JMS provider: This
+ listener container only requires simple JMS API compliance.
+
+
+
+ DefaultMessageListenerContainer
+
+ This message listener container is the one used in most cases.
+ In contrast to SimpleMessageListenerContainer,
+ this container variant does allow for dynamic adaption to runtime
+ demands and is able to participate in externally managed transactions.
+ Each received message is registered with an XA transaction
+ (when configured with a JtaTransactionManager);
+ processing can take advantage of XA transation semantics.
+ This listener container strikes a good balance between low
+ requirements on the JMS provider and good functionality including
+ transaction participation.
+
+
+
+ ServerSessionMessageListenerContainer
+
+ This listener container leverages the JMS ServerSessionPool SPI
+ to allow for dynamic management of JMS sessions. The use of this variety
+ of message listener container enables the provider to perform dynamic
+ runtime tuning but, at the expense of requiring the JMS provider to support
+ the ServerSessionPool SPI. If there is no need for provider-driven runtime
+ tuning, look at the DefaultMessageListenerContainer
+ or the SimpleMessageListenerContainer instead.
+
+
+
+
+ Transaction management
+
+ Spring provides a JmsTransactionManager
+ that manages transactions for a single JMS
+ ConnectionFactory. This allows JMS applications
+ to leverage the managed transaction features of Spring as described in
+ . The JmsTransactionManager
+ performs local resource transactions, binding a JMS Connection/Session
+ pair from the specified ConnectionFactory to the
+ thread. JmsTemplate automatically detects such
+ transactional resources and operates on them accordingly.
+
+ In a J2EE environment, the ConnectionFactory
+ will pool Connections and Sessions, so those resources are efficiently
+ reused across transactions. In a standalone environment, using Spring's
+ SingleConnectionFactory will result in a shared
+ JMS Connection, with each transaction having its
+ own independent Session. Alternatively, consider
+ the use of a provider-specific pooling adapter such as ActiveMQ's
+ PooledConnectionFactory class.
+
+ JmsTemplate can also be used with the
+ JtaTransactionManager and an XA-capable JMS
+ ConnectionFactory for performing distributed
+ transactions. Note that this requires the use of a JTA transaction
+ manager as well as a properly XA-configured ConnectionFactory!
+ (Check your J2EE server's / JMS provider's documentation.)
+
+ Reusing code across a managed and unmanaged transactional
+ environment can be confusing when using the JMS API to create a
+ Session from a Connection.
+ This is because the JMS API has only one factory method to create a
+ Session and it requires values for the
+ transaction and acknowledgement modes. In a managed environment, setting
+ these values is the responsibility of the environment's transactional
+ infrastructure, so these values are ignored by the vendor's wrapper to
+ the JMS Connection. When using the JmsTemplate in
+ an unmanaged environment you can specify these values through the use of
+ the properties sessionTransacted and
+ sessionAcknowledgeMode. When using a
+ PlatformTransactionManager with
+ JmsTemplate, the template will always be given a
+ transactional JMS Session.
+
+
+
+
+ Sending a Message
+
+ The JmsTemplate contains many convenience
+ methods to send a message. There are send methods that specify the
+ destination using a javax.jms.Destination object
+ and those that specify the destination using a string for use in a JNDI
+ lookup. The send method that takes no destination argument uses the
+ default destination. Here is an example that sends a message to a queue
+ using the 1.0.2 implementation.
+
+
+
+ This example uses the MessageCreator
+ callback to create a text message from the supplied
+ Session object and the
+ JmsTemplate is constructed by passing a reference
+ to a ConnectionFactory and a boolean specifying
+ the messaging domain. A zero argument constructor and
+ connectionFactory / queue bean
+ properties are provided and can be used for constructing the instance
+ (using a BeanFactory or plain Java code). Alternatively, consider
+ deriving from Spring's JmsGatewaySupport
+ convenience base class, which provides pre-built bean properties for JMS
+ configuration.
+
+ When configuring the JMS 1.0.2 support in an application context,
+ it is important to remember setting the value of the boolean property
+ pubSubDomain property in order to indicate if you
+ want to send to Queues or Topics.
+
+ The method send(String destinationName, MessageCreator
+ creator) lets you send to a message using the string name
+ of the destination. If these names are registered in JNDI, you should
+ set the destinationResolver property of the
+ template to an instance of
+ JndiDestinationResolver.
+
+ If you created the JmsTemplate and
+ specified a default destination, the send(MessageCreator c)
+ sends a message to that destination.
+
+
+ Using Message Converters
+
+ In order to facilitate the sending of domain model objects, the
+ JmsTemplate has various send methods that take a
+ Java object as an argument for a message's data content. The overloaded
+ methods convertAndSend and
+ receiveAndConvert in
+ JmsTemplate delegate the conversion process to an
+ instance of the MessageConverter interface. This
+ interface defines a simple contract to convert between Java objects and
+ JMS messages. The default implementation
+ SimpleMessageConverter supports conversion
+ between String and
+ TextMessage, byte[] and
+ BytesMesssage, and
+ java.util.Map and
+ MapMessage. By using the converter, you and your
+ application code can focus on the business object that is being sent or
+ received via JMS and not be concerned with the details of how it is
+ represented as a JMS message.
+
+ The sandbox currently includes a
+ MapMessageConverter which uses reflection to
+ convert between a JavaBean and a MapMessage.
+ Other popular implementations choices you might implement yourself are
+ Converters that use an existing XML marshalling package, such as JAXB,
+ Castor, XMLBeans, or XStream, to create a
+ TextMessage representing the object.
+
+ To accommodate the setting of a message's properties, headers, and
+ body that can not be generically encapsulated inside a converter class,
+ the MessagePostProcessor interface gives you access
+ to the message after it has been converted, but before it is sent. The
+ example below demonstrates how to modify a message header and a property after
+ a java.util.Map is converted to a message.
+
+
+ This results in a message of the form:
+
+
+
+
+ SessionCallback and ProducerCallback
+ While the send operations cover many common usage scenarios, there
+ are cases when you want to perform multiple operations on a JMS
+ Session or
+ MessageProducer. The
+ SessionCallback and
+ ProducerCallback expose the JMS
+ Session and
+ Session / MessageProducer
+ pair respectfully. The execute() methods on
+ JmsTemplate execute these callback
+ methods.
+
+
+
+
+ Receiving a message
+
+
+ Synchronous Reception
+
+ While JMS is typically associated with asynchronous processing, it
+ is possible to consume messages synchronously. The overloaded
+ receive(..) methods provide this functionality.
+ During a synchronous receive, the calling thread blocks until a message
+ becomes available. This can be a dangerous operation since the calling
+ thread can potentially be blocked indefinitely. The property
+ receiveTimeout specifies how long the receiver
+ should wait before giving up waiting for a message.
+
+
+
+ Asynchronous Reception - Message-Driven POJOs
+
+ In a fashion similar to a Message-Driven Bean (MDB) in the EJB world,
+ the Message-Driven POJO (MDP) acts as a receiver for JMS messages. The one
+ restriction (but see also below for the discussion of the
+ MessageListenerAdapter class) on an MDP is that it
+ must implement the javax.jms.MessageListener
+ interface. Please also be aware that in the case where your POJO will be
+ receiving messages on multiple threads, it is important to ensure that your
+ implementation is thread-safe.
+ Below is a simple implementation of an MDP:
+
+ Once you've implemented your MessageListener,
+ it's time to create a message listener container.
+ Find below an example of how to define and configure one of the message listener
+ containers that ships with Spring (in this case the
+ DefaultMessageListenerContainer).
+ <!-- this is the Message Driven POJO (MDP) -->
+
+
+]]><!-- and this is the message listener container -->
+
+
+ ]]>]]>]]>
+ Please refer to the Spring Javadoc of the various message
+ listener containers for a full description of the features supported by each implementation.
+
+
+
+ The SessionAwareMessageListener interface
+ The SessionAwareMessageListener interface
+ is a Spring-specific interface that provides a similar contract the JMS
+ MessageListener interface, but also provides
+ the message handling method with access to the JMS Session
+ from which the Message was received.
+
+ You can choose to have your MDPs implement this interface (in preference to the
+ standard JMS MessageListener interface) if you
+ want your MDPs to be able to respond to any received messages (using the
+ Session supplied in the
+ onMessage(Message, Session) method). All of the message listener
+ container implementations that ship wth Spring have support for MDPs that implement either
+ the MessageListener or
+ SessionAwareMessageListener interface. Classes
+ that implement the SessionAwareMessageListener come
+ with the caveat that they are then tied to Spring through the interface. The choice of whether
+ or not to use it is left entirely up to you as an application developer or architect.
+ Please note that the 'onMessage(..)' method of the
+ SessionAwareMessageListener interface throws
+ JMSException. In contrast to the standard JMS
+ MessageListener interface, when using the
+ SessionAwareMessageListener interface, it is the responsibility
+ of the client code to handle any exceptions thrown.
+
+
+
+ The MessageListenerAdapter
+ The MessageListenerAdapter class is the final component in
+ Spring's asynchronous messaging support: in a nutshell, it allows you to
+ expose almost any class as a MDP (there are of course some constraints).
+
+ If you are using the JMS 1.0.2 API, you will want to use the
+ MessageListenerAdapter102 class which provides the exact
+ same functionality and value add as the MessageListenerAdapter
+ class, but for the JMS 1.0.2 API.
+
+ Consider the following interface definition. Notice that although the interface extends
+ neither the MessageListener nor
+ SessionAwareMessageListener interfaces, it can still
+ be used as a MDP via the use of the MessageListenerAdapter class.
+ Notice also how the various message handling methods are strongly typed according to
+ the contents of the various Message
+ types that they can receive and handle.
+
+ // implementation elided for clarity...
+ In particular, note how the above implementation of the MessageDelegate
+ interface (the above DefaultMessageDelegate class) has
+ no JMS dependencies at all. It truly is a POJO that we will
+ make into an MDP via the following configuration.
+ <!-- this is the Message Driven POJO (MDP) -->
+
+
+
+
+]]>
+
+<!-- and this is the message listener container... -->
+
+
+ ]]>]]>]]>
+ Below is an example of another MDP that can only handle the receiving of
+ JMS TextMessage messages. Notice how the message handling
+ method is actually called 'receive' (the name of the message handling
+ method in a MessageListenerAdapter defaults to
+ 'handleMessage'), but it is configurable (as you will see below).
+ Notice also how the 'receive(..)' method is strongly typed to
+ receive and respond only to JMS TextMessage messages.
+
+ // implementation elided for clarity...
+ The configuration of the attendant MessageListenerAdapter would
+ look like this:
+
+
+
+
+
+ ]]><!-- we don't want automatic message context extraction -->
+
+
+]]>
+ Please note that if the above 'messageListener' receives a
+ JMS Message of a type other than
+ TextMessage, an IllegalStateException
+ will be thrown (and subsequently swallowed).
+ Another of the capabilities of the MessageListenerAdapter
+ class is the ability to automatically send back a response Message
+ if a handler method returns a non-void value.
+ Consider the interface and class:
+ // notice the return type...
+ // implementation elided for clarity...
+ If the above DefaultResponsiveTextMessageDelegate is used in
+ conjunction with a MessageListenerAdapter then any non-null
+ value that is returned from the execution of the 'receive(..)'
+ method will (in the default configuration) be converted into a
+ TextMessage. The resulting TextMessage
+ will then be sent to the Destination (if one exists)
+ defined in the JMS Reply-To property of the original Message, or the
+ default Destination set on the
+ MessageListenerAdapter (if one has been configured); if no
+ Destination is found then an
+ InvalidDestinationException will be thrown (and please note
+ that this exception will not be swallowed and
+ will propagate up the call stack).
+
+
+
+ Processing messages within transactions
+
+ Invoking a message listener within a transaction only requires
+ reconfiguration of the listener container.
+
+ Local resource transactions can simply be activated through the
+ sessionTransacted flag on the listener container
+ definition. Each message listener invocation will then operate within
+ an active JMS transaction, with message reception rolled back in case
+ of listener execution failure. Sending a response message
+ (via SessionAwareMessageListener)
+ will be part of the same local transaction, but any other resource
+ operations (such as database access) will operate independently.
+ This usually requires duplicate message detection in the listener
+ implementation, covering the case where database processing has
+ committed but message processing failed to commit.
+
+
+
+
+
+ ]]>]]>]]>
+
+ For participating in an externally managed transaction,
+ you will need to configure a transaction manager and use a listener
+ container which supports externally managed transactions: typically
+ DefaultMessageListenerContainer.
+
+ To configure a message listener container for XA transaction
+ participation, you'll want to configure a JtaTransactionManager
+ (which, by default, delegates to the J2EE server's transaction subsystem).
+ Note that the underlying JMS ConnectionFactory needs to be XA-capable
+ and properly registered with your JTA transaction coordinator!
+ (Check your J2EE server's configuration of JNDI resources.)
+ This allows message recepton as well as e.g. database access to be
+ part of the same transaction (with unified commit semantics,
+ at the expense of XA transaction log overhead).
+
+
+]]>
+
+ Then you just need to add it to our earlier container configuration. The
+ container will take care of the rest.
+
+
+
+
+
+ ]]>]]>]]>
+
+
+
+
+ Support for JCA Message Endpoints
+
+ Beginning with version 2.5, Spring also provides support for a JCA-based
+ MessageListener container. The
+ JmsMessageEndpointManager will attempt to automatically
+ determine the ActivationSpec class name from the
+ provider's ResourceAdapter class name. Therefore,
+ it is typically possible to just provide Spring's generic
+ JmsActivationSpecConfig as shown in the following example.
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ Alternatively, you may set up a JmsMessageEndpointManager
+ with a given ActivationSpec object. The
+ ActivationSpec object may also come
+ from a JNDI lookup (using <jee:jndi-lookup>).
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ Using Spring's ResourceAdapterFactoryBean,
+ the target ResourceAdapter may be
+ configured locally as depicted in the following example.
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ The specified WorkManager
+ may also point to an environment-specific thread pool - typically
+ through SimpleTaskWorkManager's
+ "asyncTaskExecutor" property. Consider defining a shared thread
+ pool for all your ResourceAdapter
+ instances if you happen to use multiple adapters.
+
+ In some environments (e.g. WebLogic 9 or above), the entire
+ ResourceAdapter object may be obtained
+ from JNDI instead (using <jee:jndi-lookup>).
+ The Spring-based message listeners can then interact with the server-hosted
+ ResourceAdapter, also using the server's
+ built-in WorkManager.
+
+ Please consult the JavaDoc for JmsMessageEndpointManager,
+ JmsActivationSpecConfig, and
+ ResourceAdapterFactoryBean for more details.
+
+ Spring also provides a generic JCA message endpoint manager which is not tied to JMS:
+ org.springframework.jca.endpoint.GenericMessageEndpointManager.
+ This component allows for using any message listener type (e.g. a CCI MessageListener)
+ and any provided-specific ActivationSpec object. Check out your JCA provider's
+ documentation to find out about the actual capabilities of your connector,
+ and consult GenericMessageEndpointManager's JavaDoc
+ for the Spring-specific configuration details.
+
+
+ JCA-based message endpoint management is very analogous to EJB 2.1
+ Message-Driven Beans; it uses the same underlying resource provider contract.
+ Like with EJB 2.1 MDBs, any message listener interface supported by your JCA
+ provider can be used in the Spring context as well. Spring nevertheless provides
+ explicit 'convenience' support for JMS, simply because JMS is the most common
+ endpoint API used with the JCA endpoint management contract.
+
+
+
+
+ JMS Namespace Support
+
+ Spring 2.5 introduces an XML namespace for simplifying JMS configuration. To use the
+ JMS namespace elements you will need to reference the JMS schema:
+
+
+xmlns:jms="http://www.springframework.org/schema/jms"http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
+
+]]><!-- <bean/> definitions here -->]]>
+
+ The namespace consists of two top-level elements: <listener-container/>
+ and <jca-listener-container/> both of which may contain one or more
+ <listener/> child elements. Here is an example of a basic configuration
+ for two listeners.
+
+
+
+
+
+
+
+]]>
+
+ The example above is equivalent to creating two distinct listener container bean
+ definitions and two distinct MessageListenerAdapter bean
+ definitions as demonstrated in the section entitled
+ . In addition to the
+ attributes shown above, the listener element may contain several
+ optional ones. The following table describes all available attributes:
+
+
+ Attributes of the JMS <listener> element
+
+
+
+
+
+ Attribute
+ Description
+
+
+
+
+ id
+
+ A bean name for the hosting listener container. If not
+ specified, a bean name will be automatically generated.
+
+
+
+ destination (required)
+
+ The destination name for this listener, resolved through the
+ DestinationResolver strategy.
+
+
+
+ ref (required)
+
+ The bean name of the handler object.
+
+
+
+ method
+
+ The name of the handler method to invoke. If the
+ ref points to a
+ MessageListener or Spring
+ SessionAwareMessageListener,
+ this attribute may be omitted.
+
+
+
+ response-destination
+
+ The name of the default response destination to send
+ response messages to. This will be applied in case of a
+ request message that does not carry a "JMSReplyTo" field.
+ The type of this destination will be determined by the
+ listener-container's "destination-type" attribute. Note:
+ This only applies to a listener method with a return
+ value, for which each result object will be converted
+ into a response message.
+
+
+
+ subscription
+
+ The name of the durable subscription, if any.
+
+
+
+ selector
+
+ An optional message selector for this listener.
+
+
+
+
+
+
+ The <listener-container/> element also accepts several optional
+ attributes. This allows for customization of the various strategies (for example,
+ taskExecutor and destinationResolver) as well as
+ basic JMS settings and resource references. Using these attributes, it is possible to define
+ highly-customized listener containers while still benefiting from the convenience of the
+ namespace.
+
+
+
+
+
+
+
+]]>
+
+ The following table describes all available attributes. Consult the class-level
+ Javadoc of the AbstractMessageListenerContainer and its
+ concrete subclasses for more detail on the individual properties. The Javadoc also
+ provides a discussion of transaction choices and message redelivery scenarios.
+
+
+ Attributes of the JMS <listener-container> element
+
+
+
+
+
+ Attribute
+ Description
+
+
+
+
+ container-type
+
+ The type of this listener container. Available options are:
+ default, simple,
+ default102, or simple102
+ (the default value is 'default').
+
+
+
+ connection-factory
+
+ A reference to the JMS
+ ConnectionFactory bean (the default bean
+ name is 'connectionFactory').
+
+
+
+ task-executor
+
+ A reference to the Spring TaskExecutor
+ for the JMS listener invokers.
+
+
+
+ destination-resolver
+
+ A reference to the DestinationResolver
+ strategy for resolving JMS Destinations.
+
+
+
+ message-converter
+
+ A reference to the MessageConverter
+ strategy for converting JMS Messages to listener method arguments. Default
+ is a SimpleMessageConverter.
+
+
+
+ destination-type
+
+ The JMS destination type for this listener: queue,
+ topic or durableTopic.
+ The default is queue.
+
+
+
+ client-id
+
+ The JMS client id for this listener container.
+ Needs to be specified when using durable subscriptions.
+
+
+
+ cache
+
+ The cache level for JMS resources: none,
+ connection, session,
+ consumer or auto.
+ By default (auto), the cache level will
+ effectively be "consumer", unless an external transaction manager
+ has been specified - in which case the effective default will be
+ none (assuming J2EE-style transaction management
+ where the given ConnectionFactory is an XA-aware pool).
+
+
+
+ acknowledge
+
+ The native JMS acknowledge mode: auto,
+ client, dups-ok or
+ transacted. A value of transacted
+ activates a locally transacted Session.
+ As an alternative, specify the transaction-manager
+ attribute described below. Default is auto.
+
+
+
+ transaction-manager
+
+ A reference to an external
+ PlatformTransactionManager
+ (typically an XA-based transaction coordinator, e.g. Spring's
+ JtaTransactionManager). If not specified,
+ native acknowledging will be used (see "acknowledge" attribute).
+
+
+
+ concurrency
+
+ The number of concurrent sessions/consumers to start for each
+ listener. Can either be a simple number indicating the maximum number (e.g. "5")
+ or a range indicating the lower as well as the upper limit (e.g. "3-5").
+ Note that a specified minimum is just a hint and might be ignored at runtime.
+ Default is 1; keep concurrency limited to 1 in case of a topic listener
+ or if queue ordering is important; consider raising it for general queues.
+
+
+
+ prefetch
+
+ The maximum number of messages to load into a single session.
+ Note that raising this number might lead to starvation of concurrent
+ consumers!
+
+
+
+
+
+
+ Configuring a JCA-based listener container with the "jms" schema support is very similar.
+
+
+
+
+
+]]>
+
+ The available configuration options for the JCA variant are described in the following table:
+
+
+ Attributes of the JMS <jca-listener-container/> element
+
+
+
+
+
+ Attribute
+ Description
+
+
+
+
+ resource-adapter
+
+ A reference to the JCA
+ ResourceAdapter bean (the default bean
+ name is 'resourceAdapter').
+
+
+
+ activation-spec-factory
+
+ A reference to the JmsActivationSpecFactory.
+ The default is to autodetect the JMS provider and its
+ ActivationSpec class
+ (see DefaultJmsActivationSpecFactory)
+
+
+
+ destination-resolver
+
+ A reference to the DestinationResolver
+ strategy for resolving JMS Destinations.
+
+
+
+
+ message-converter
+
+ A reference to the MessageConverter
+ strategy for converting JMS Messages to listener method arguments.
+ Default is a SimpleMessageConverter.
+
+
+
+ destination-type
+
+ The JMS destination type for this listener: queue,
+ topic or durableTopic.
+ The default is queue.
+
+
+
+ client-id
+
+ The JMS client id for this listener container.
+ Needs to be specified when using durable subscriptions.
+
+
+
+ acknowledge
+
+ The native JMS acknowledge mode: auto,
+ client, dups-ok or
+ transacted. A value of transacted
+ activates a locally transacted Session.
+ As an alternative, specify the transaction-manager
+ attribute described below. Default is auto.
+
+
+
+ transaction-manager
+
+ A reference to a Spring JtaTransactionManager
+ or a javax.transaction.TransactionManager
+ for kicking off an XA transaction for each incoming message.
+ If not specified, native acknowledging will be used (see
+ the "acknowledge" attribute).
+
+
+
+ concurrency
+
+ The number of concurrent sessions/consumers to start for each
+ listener. Can either be a simple number indicating the maximum number (e.g. "5")
+ or a range indicating the lower as well as the upper limit (e.g. "3-5").
+ Note that a specified minimum is just a hint and will typically be ignored
+ at runtime when using a JCA listener container. Default is 1.
+
+
+
+ prefetch
+
+ The maximum number of messages to load into a single session.
+ Note that raising this number might lead to starvation of concurrent
+ consumers!
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/jmx.xml b/spring-framework-reference/src/jmx.xml
new file mode 100644
index 00000000000..de53abc63ba
--- /dev/null
+++ b/spring-framework-reference/src/jmx.xml
@@ -0,0 +1,1760 @@
+
+
+ JMX
+
+
+ Introduction
+
+ The JMX support in Spring provides you with the features to easily
+ and transparently integrate your Spring application into a JMX
+ infrastructure.
+
+
+ JMX?
+
+ This chapter is not an introduction to JMX... it doesn't try to
+ explain the motivations of why one might want to use JMX (or indeed what
+ the letters JMX actually stand for). If you are new to JMX, check out
+ the section entitled at the end of this
+ chapter.
+
+
+ Specifically, Spring's JMX support provides four core
+ features:
+
+
+
+ The automatic registration of any Spring
+ bean as a JMX MBean
+
+
+
+ A flexible mechanism for controlling the management interface of
+ your beans
+
+
+
+ The declarative exposure of MBeans over remote, JSR-160
+ connectors
+
+
+
+ The simple proxying of both local and remote MBean
+ resources
+
+
+
+ These features are designed to work without coupling your
+ application components to either Spring or JMX interfaces and classes.
+ Indeed, for the most part your application classes need not be aware of
+ either Spring or JMX in order to take advantage of the Spring JMX
+ features.
+
+
+
+ Exporting your beans to JMX
+
+ The core class in Spring's JMX framework is the
+ MBeanExporter. This class is responsible for taking
+ your Spring beans and registering them with a JMX
+ MBeanServer. For example, consider the following
+ class:
+
+
+
+ To expose the properties and methods of this bean as attributes and
+ operations of an MBean you simply configure an instance of the
+ MBeanExporter class in your configuration file and
+ pass in the bean as shown below:
+
+
+
+ ]]><!-- this bean must not be lazily initialized if the exporting is to happen -->lazy-init="false"
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ The pertinent bean definition from the above configuration snippet
+ is the exporter bean. The beans
+ property tells the MBeanExporter exactly which of
+ your beans must be exported to the JMX MBeanServer.
+ In the default configuration, the key of each entry in the
+ beansMap is used as the
+ ObjectName for the bean referenced by the
+ corresponding entry value. This behavior can be changed as described in
+ the section entitled .
+
+ With this configuration the testBean bean is
+ exposed as an MBean under the ObjectName
+ bean:name=testBean1. By default, all
+ public properties of the bean are exposed as
+ attributes and all public methods (bar those
+ inherited from the Object class) are exposed as
+ operations.
+
+
+ Creating an MBeanServer
+
+ The above configuration assumes that the application is running in
+ an environment that has one (and only one)
+ MBeanServer already running. In this case, Spring
+ will attempt to locate the running MBeanServer
+ and register your beans with that server (if any). This behavior is
+ useful when your application is running inside a container such as
+ Tomcat or IBM WebSphere that has itss own
+ MBeanServer.
+
+ However, this approach is of no use in a standalone environment,
+ or when running inside a container that does not provide an
+ MBeanServer. To address this you can create an
+ MBeanServer instance declaratively by adding an
+ instance of the
+ org.springframework.jmx.support.MBeanServerFactoryBean
+ class to your configuration. You can also ensure that a specific
+ MBeanServer is used by setting the value of the
+ MBeanExporter's server
+ property to the MBeanServer value returned by an
+ MBeanServerFactoryBean; for example:
+
+
+
+
+
+ ]]><!--
+ this bean needs to be eagerly pre-instantiated in order for the exporting to occur;
+ this means that it must not be marked as lazily initialized
+ -->
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ Here an instance of MBeanServer is created
+ by the MBeanServerFactoryBean and is supplied to
+ the MBeanExporter via the server property. When
+ you supply your own MBeanServer instance, the
+ MBeanExporter will not attempt to locate a
+ running MBeanServer and will use the supplied
+ MBeanServer instance. For this to work correctly,
+ you must (of course) have a JMX implementation on your classpath.
+
+
+
+ Reusing an existing MBeanServer
+
+ If no server is specified, the MBeanExporter
+ tries to automatically detect a running MBeanServer.
+ This works in most environment where only one
+ MBeanServer instance is used, however when multiple
+ instances exist, the exporter might pick the wrong server. In such
+ cases, one should use the MBeanServer
+ agentId to indicate which instance to be used:
+
+
+
+ ]]><!-- indicate to first look for a server -->
+ ]]><!-- search for the MBeanServer instance with the given agentId -->]]>
+
+
+
+
+ ...
+
+]]>
+
+ For platforms/cases where the existing MBeanServer
+ has a dynamic (or unknown) agentId which is retrieved through lookup
+ methods, one should use factory-method:
+
+
+
+
+ ]]><!-- Custom MBeanServerLocator -->
+
+
+ ]]><!-- other beans here -->
+]]>
+
+
+
+ Lazy-initialized MBeans
+
+ If you configure a bean with the
+ MBeanExporter that is also configured for lazy
+ initialization, then the MBeanExporter will
+ not break this contract and will avoid
+ instantiating the bean. Instead, it will register a proxy with
+ the MBeanServer and will defer obtaining the bean
+ from the container until the first invocation on the proxy occurs.
+
+
+
+ Automatic registration of MBeans
+
+ Any beans that are exported through the
+ MBeanExporter and are already valid MBeans are
+ registered as-is with the MBeanServer without
+ further intervention from Spring. MBeans can be automatically detected
+ by the MBeanExporter by setting the
+ autodetect property to true:
+
+
+
+
+
+]]>
+
+ Here, the bean called spring:mbean=true is
+ already a valid JMX MBean and will be automatically registered by
+ Spring. By default, beans that are autodetected for JMX registration
+ have their bean name used as the ObjectName. This
+ behavior can be overridden as detailed in the section entitled
+ .
+
+
+
+ Controlling the registration behavior
+
+ Consider the scenario where a Spring
+ MBeanExporter attempts to register an
+ MBean with an MBeanServer
+ using the ObjectName
+ 'bean:name=testBean1'. If an
+ MBean instance has already been registered under
+ that same ObjectName, the default behavior is to
+ fail (and throw an
+ InstanceAlreadyExistsException).
+
+ It is possible to control the behavior of exactly what happens
+ when an MBean is registered with an
+ MBeanServer. Spring's JMX support allows for
+ three different registration behaviors to control the registration
+ behavior when the registration process finds that an
+ MBean has already been registered under the same
+ ObjectName; these registration behaviors are
+ summarized on the following table:
+
+
+ Registration Behaviors
+
+
+
+
+
+
+
+
+
+
+ Registration behavior
+
+ Explanation
+
+
+
+
+
+ REGISTRATION_FAIL_ON_EXISTING
+
+ This is the default registration behavior. If an
+ MBean instance has already been
+ registered under the same ObjectName,
+ the MBean that is being registered will
+ not be registered and an
+ InstanceAlreadyExistsException will be
+ thrown. The existing MBean is
+ unaffected.
+
+
+
+ REGISTRATION_IGNORE_EXISTING
+
+ If an MBean instance has
+ already been registered under the same
+ ObjectName, the
+ MBean that is being registered will
+ not be registered. The existing
+ MBean is unaffected, and no
+ Exception will be thrown.
+ This is useful in settings where multiple applications
+ want to share a common MBean in a
+ shared MBeanServer.
+
+
+
+ REGISTRATION_REPLACE_EXISTING
+
+ If an MBean instance has
+ already been registered under the same
+ ObjectName, the existing
+ MBean that was previously registered
+ will be unregistered and the new MBean
+ will be registered in its place (the new
+ MBean effectively replaces the previous
+ instance).
+
+
+
+
+
+ The above values are defined as constants on the
+ MBeanRegistrationSupport class (the
+ MBeanExporter class derives from this
+ superclass). If you want to change the default registration behavior,
+ you simply need to set the value of the
+ registrationBehaviorName property on your
+ MBeanExporter definition to one of those
+ values.
+
+ The following example illustrates how to effect a change from the
+ default registration behavior to the
+ REGISTRATION_REPLACE_EXISTING behavior:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ Controlling the management interface of your beans
+
+ In the previous example, you had little control over the management
+ interface of your bean; all of the
+ public properties and methods of each exported bean
+ was exposed as JMX attributes and operations respectively. To exercise
+ finer-grained control over exactly which properties and methods of your
+ exported beans are actually exposed as JMX attributes and operations,
+ Spring JMX provides a comprehensive and extensible mechanism for
+ controlling the management interfaces of your beans.
+
+
+ The MBeanInfoAssembler
+ Interface
+
+ Behind the scenes, the MBeanExporter
+ delegates to an implementation of the
+ org.springframework.jmx.export.assembler.MBeanInfoAssembler
+ interface which is responsible for defining the management interface of
+ each bean that is being exposed. The default implementation,
+ org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler,
+ simply defines a management interface that exposes all public properties
+ and methods (as you saw in the previous examples). Spring provides two
+ additional implementations of the
+ MBeanInfoAssembler interface that allow
+ you to control the generated management interface using either
+ source-level metadata or any arbitrary interface.
+
+
+
+ Using source-Level metadata
+
+ Using the MetadataMBeanInfoAssembler you
+ can define the management interfaces for your beans using source level
+ metadata. The reading of metadata is encapsulated by the
+ org.springframework.jmx.export.metadata.JmxAttributeSource
+ interface. Out of the box, Spring JMX provides support for two
+ implementations of this interface:
+ org.springframework.jmx.export.metadata.AttributesJmxAttributeSource
+ for Commons Attributes and
+ org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
+ for JDK 5.0 annotations. The
+ MetadataMBeanInfoAssembler
+ must be configured with an implementation instance
+ of the JmxAttributeSource interface for it to
+ function correctly (there is no default). For the
+ following example, we will use the Commons Attributes metadata
+ approach.
+
+ To mark a bean for export to JMX, you should annotate the bean
+ class with the ManagedResource attribute. In the
+ case of the Commons Attributes metadata approach this class can be found
+ in the org.springframework.jmx.metadata package. Each
+ method you wish to expose as an operation must be marked with the
+ ManagedOperation attribute and each property you
+ wish to expose must be marked with the
+ ManagedAttribute attribute. When marking
+ properties you can omit either the annotation of the getter or the
+ setter to create a write-only or read-only attribute
+ respectively.
+
+ The example below shows the JmxTestBean
+ class that you saw earlier marked with Commons Attributes
+ metadata:
+
+
+
+ Here you can see that the JmxTestBean class
+ is marked with the ManagedResource attribute and
+ that this ManagedResource attribute is configured
+ with a set of properties. These properties can be used to configure
+ various aspects of the MBean that is generated by the
+ MBeanExporter, and are explained in greater
+ detail later in section entitled .
+
+ You will also notice that both the age and
+ name properties are annotated with the
+ ManagedAttribute attribute, but in the case of
+ the age property, only the getter is marked. This
+ will cause both of these properties to be included in the management
+ interface as attributes, but the age attribute will
+ be read-only.
+
+ Finally, you will notice that the add(int, int)
+ method is marked with the ManagedOperation
+ attribute whereas the dontExposeMe() method is not.
+ This will cause the management interface to contain only one operation,
+ add(int, int), when using the
+ MetadataMBeanInfoAssembler.
+
+ The code below shows how you configure the
+ MBeanExporter to use the
+ MetadataMBeanInfoAssembler:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ Here you can see that an
+ MetadataMBeanInfoAssembler bean has been
+ configured with an instance of the
+ AttributesJmxAttributeSource class and passed to
+ the MBeanExporter through the assembler property.
+ This is all that is required to take advantage of metadata-driven
+ management interfaces for your Spring-exposed MBeans.
+
+
+
+ Using JDK 5.0 Annotations
+
+ To enable the use of JDK 5.0 annotations for management interface
+ definition, Spring provides a set of annotations that mirror the Commons
+ Attribute attribute classes and an implementation of the
+ JmxAttributeSource strategy interface,
+ the AnnotationsJmxAttributeSource class, that
+ allows the MBeanInfoAssembler to read
+ them.
+
+ The example below shows a bean where the management interface is defined
+ by the presence of JDK 5.0 annotation types:
+
+
+
+ As you can see little has changed, other than the basic syntax of
+ the metadata definitions.
+
+
+
+
+
+
+
+
+
+
+ ]]><!-- will create management interface using annotation metadata -->
+
+
+
+ ]]><!-- will pick up the ObjectName from the annotation -->
+
+
+
+
+
+
+
+]]>
+
+
+
+ Source-Level Metadata Types
+
+ The following source level metadata types are available for use in
+ Spring JMX:
+
+
+ Source-Level Metadata Types
+
+
+
+
+
+
+
+
+
+
+
+
+ Purpose
+
+ Commons Attributes Attribute
+
+ JDK 5.0 Annotation
+
+ Attribute / Annotation Type
+
+
+
+
+
+ Mark all instances of a Class as
+ JMX managed resources
+
+ ManagedResource
+
+ @ManagedResource
+
+ Class
+
+
+
+ Mark a method as a JMX operation
+
+ ManagedOperation
+
+ @ManagedOperation
+
+ Method
+
+
+
+ Mark a getter or setter as one half of a JMX
+ attribute
+
+ ManagedAttribute
+
+ @ManagedAttribute
+
+ Method (only getters and setters)
+
+
+
+ Define descriptions for operation parameters
+
+ ManagedOperationParameter
+
+ @ManagedOperationParameter and
+ @ManagedOperationParameters
+
+ Method
+
+
+
+
+
+ The following configuration parameters are available for use on
+ these source-level metadata types:
+
+
+ Source-Level Metadata Parameters
+
+
+
+
+
+
+
+
+
+
+ Parameter
+
+ Description
+
+ Applies to
+
+
+
+
+
+ ObjectName
+
+ Used by MetadataNamingStrategy
+ to determine the ObjectName of a
+ managed resource
+
+ ManagedResource
+
+
+
+ description
+
+ Sets the friendly description of the resource,
+ attribute or operation
+
+ ManagedResource,
+ ManagedAttribute,
+ ManagedOperation,
+ ManagedOperationParameter
+
+
+
+ currencyTimeLimit
+
+ Sets the value of the
+ currencyTimeLimit descriptor field
+
+ ManagedResource,
+ ManagedAttribute
+
+
+
+ defaultValue
+
+ Sets the value of the defaultValue
+ descriptor field
+
+ ManagedAttribute
+
+
+
+ log
+
+ Sets the value of the log descriptor
+ field
+
+ ManagedResource
+
+
+
+ logFile
+
+ Sets the value of the logFile
+ descriptor field
+
+ ManagedResource
+
+
+
+ persistPolicy
+
+ Sets the value of the persistPolicy
+ descriptor field
+
+ ManagedResource
+
+
+
+ persistPeriod
+
+ Sets the value of the persistPeriod
+ descriptor field
+
+ ManagedResource
+
+
+
+ persistLocation
+
+ Sets the value of the
+ persistLocation descriptor field
+
+ ManagedResource
+
+
+
+ persistName
+
+ Sets the value of the persistName
+ descriptor field
+
+ ManagedResource
+
+
+
+ name
+
+ Sets the display name of an operation parameter
+
+ ManagedOperationParameter
+
+
+
+ index
+
+ Sets the index of an operation parameter
+
+ ManagedOperationParameter
+
+
+
+
+
+
+
+ The AutodetectCapableMBeanInfoAssembler
+ interface
+
+ To simplify configuration even further, Spring introduces the
+ AutodetectCapableMBeanInfoAssembler interface
+ which extends the MBeanInfoAssembler
+ interface to add support for autodetection of MBean resources. If you
+ configure the MBeanExporter with an instance of
+ AutodetectCapableMBeanInfoAssembler then it is
+ allowed to "vote" on the inclusion of beans for exposure to JMX.
+
+ Out of the box, the only implementation of the
+ AutodetectCapableMBeanInfo interface is the
+ MetadataMBeanInfoAssembler which will vote to
+ include any bean which is marked with the
+ ManagedResource attribute. The default approach
+ in this case is to use the bean name as the
+ ObjectName which results in a configuration like
+ this:
+
+
+
+
+ ]]><!-- notice how no 'beans' are explicitly configured here -->
+
+
+
+
+
+
+
+
+ ]]><!-- (for Commons Attributes-based metadata) -->
+
+
+
+
+
+ ]]><!-- (for Java 5+ annotations-based metadata) -->
+ -->]]>
+
+
+
+]]>
+
+ Notice that in this configuration no beans are passed to the
+ MBeanExporter; however, the
+ JmxTestBean will still be registered since it is
+ marked with the ManagedResource attribute and the
+ MetadataMBeanInfoAssembler detects this and votes
+ to include it. The only problem with this approach is that the name of
+ the JmxTestBean now has business meaning. You can
+ address this issue by changing the default behavior for
+ ObjectName creation as defined in the section
+ entitled .
+
+
+
+ Defining management interfaces using Java interfaces
+
+ In addition to the
+ MetadataMBeanInfoAssembler, Spring also includes
+ the InterfaceBasedMBeanInfoAssembler which allows
+ you to constrain the methods and properties that are exposed based on
+ the set of methods defined in a collection of interfaces.
+
+ Although the standard mechanism for exposing MBeans is to use
+ interfaces and a simple naming scheme, the
+ InterfaceBasedMBeanInfoAssembler extends this
+ functionality by removing the need for naming conventions, allowing you
+ to use more than one interface and removing the need for your beans to
+ implement the MBean interfaces.
+
+ Consider this interface that is used to define a management
+ interface for the JmxTestBean class that you saw
+ earlier:
+
+
+
+ This interface defines the methods and properties that will be
+ exposed as operations and attributes on the JMX MBean. The code below
+ shows how to configure Spring JMX to use this interface as the
+ definition for the management interface:
+
+
+
+
+
+
+
+
+
+
+ org.springframework.jmx.IJmxTestBean
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ Here you can see that the
+ InterfaceBasedMBeanInfoAssembler is configured to
+ use the IJmxTestBean interface when
+ constructing the management interface for any bean. It is important to
+ understand that beans processed by the
+ InterfaceBasedMBeanInfoAssembler are
+ not required to implement the interface used to
+ generate the JMX management interface.
+
+ In the case above, the IJmxTestBean
+ interface is used to construct all management interfaces for all beans.
+ In many cases this is not the desired behavior and you may want to use
+ different interfaces for different beans. In this case, you can pass
+ InterfaceBasedMBeanInfoAssembler a
+ Properties instance via the
+ interfaceMappings property, where the key of each
+ entry is the bean name and the value of each entry is a comma-separated
+ list of interface names to use for that bean.
+
+ If no management interface is specified through either the
+ managedInterfaces or
+ interfaceMappings properties, then the
+ InterfaceBasedMBeanInfoAssembler will reflect on
+ the bean and use all of the interfaces implemented by that bean to
+ create the management interface.
+
+
+
+ Using
+ MethodNameBasedMBeanInfoAssembler
+
+ The MethodNameBasedMBeanInfoAssembler
+ allows you to specify a list of method names that will be exposed to JMX
+ as attributes and operations. The code below shows a sample
+ configuration for this:
+
+
+
+
+
+
+
+
+ add,myOperation,getName,setName,getAge
+
+
+
+]]>
+
+ Here you can see that the methods add and
+ myOperation will be exposed as JMX operations and
+ getName(), setName(String) and
+ getAge() will be exposed as the appropriate half of a
+ JMX attribute. In the code above, the method mappings apply to beans
+ that are exposed to JMX. To control method exposure on a bean-by-bean
+ basis, use the methodMappings property of
+ MethodNameMBeanInfoAssembler to map bean names to
+ lists of method names.
+
+
+
+
+ Controlling the ObjectNames for your beans
+
+ Behind the scenes, the MBeanExporter
+ delegates to an implementation of the
+ ObjectNamingStrategy to obtain
+ ObjectNames for each of the beans it is
+ registering. The default implementation,
+ KeyNamingStrategy, will, by default, use the key of
+ the beansMap as the
+ ObjectName. In addition, the
+ KeyNamingStrategy can map the key of the
+ beansMap to an entry in a
+ Properties file (or files) to resolve the
+ ObjectName. In addition to the
+ KeyNamingStrategy, Spring provides two additional
+ ObjectNamingStrategy implementations: the
+ IdentityNamingStrategy that builds an
+ ObjectName based on the JVM identity of the bean
+ and the MetadataNamingStrategy that uses source
+ level metadata to obtain the ObjectName.
+
+
+ Reading ObjectNames from Properties
+
+ You can configure your own
+ KeyNamingStrategy instance and configure it to
+ read ObjectNames from a
+ Properties instance rather than use bean key. The
+ KeyNamingStrategy will attempt to locate an entry
+ in the Properties with a key corresponding to the
+ bean key. If no entry is found or if the
+ Properties instance is null
+ then the bean key itself is used.
+
+ The code below shows a sample configuration for the
+ KeyNamingStrategy:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bean:name=testBean1
+
+
+
+ names1.properties,names2.properties
+
+ ]]>
+
+ Here an instance of KeyNamingStrategy is
+ configured with a Properties instance that is
+ merged from the Properties instance defined by
+ the mapping property and the properties files located in the paths
+ defined by the mappings property. In this configuration, the
+ testBean bean will be given the
+ ObjectNamebean:name=testBean1
+ since this is the entry in the Properties
+ instance that has a key corresponding to the bean key.
+
+ If no entry in the Properties instance can
+ be found then the bean key name is used as the
+ ObjectName.
+
+
+
+ Using the MetadataNamingStrategy
+
+ The MetadataNamingStrategy uses
+ the objectName property of the
+ ManagedResource attribute on each bean to create
+ the ObjectName. The code below shows the
+ configuration for the
+ MetadataNamingStrategy:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ If no objectName has been provided for
+ the ManagedResource attribute, then an
+ ObjectName will be created with the
+ following format:
+ [fully-qualified-package-name]:type=[short-classname],name=[bean-name].
+ For example, the generated ObjectName for the
+ following bean would be: com.foo:type=MyClass,name=myBean.
+
+
+ ]]>
+
+
+
+
+ The <context:mbean-export/> element
+ If you are using at least Java 5, then a convenience subclass of
+ MBeanExporter is available:
+ AnnotationMBeanExporter.
+ When defining an instance of this subclass, the namingStrategy,
+ assembler, and attributeSource
+ configuration is no longer needed, since it will always use standard Java
+ annotation-based metadata (autodetection is always enabled as well). In fact,
+ an even simpler syntax is supported with the inclusion of Spring's
+ 'context' namespace in Spring 2.5. Rather than defining an
+ MBeanExporter bean, provide this single element:
+
+ ]]>
+
+ You can provide a reference to a particular MBean server if
+ necessary, and the defaultDomain attribute
+ (a property of AnnotationMBeanExporter)
+ accepts an alternate value for the generated MBean
+ ObjectNames' domains. This would be used
+ in place of the fully qualified package name as described in the
+ previous section on
+ MetadataNamingStrategy.
+
+
+ ]]>.
+
+
+ Do not use interface-based AOP proxies in combination with autodetection of
+ JMX annotations in your bean classes. Interface-based proxies 'hide' the target class,
+ which also hides the JMX managed resource annotations. Hence, use target-class proxies
+ in that case: through setting the 'proxy-target-class' flag on <aop:config/>,
+ <tx:annotation-driven/>, etc. Otherwise, your JMX beans
+ might be silently ignored at startup...
+
+
+
+
+
+
+ JSR-160 Connectors
+
+ For remote access, Spring JMX module offers two
+ FactoryBean implementations inside the
+ org.springframework.jmx.support package for creating
+ both server- and client-side connectors.
+
+
+ Server-side Connectors
+
+ To have Spring JMX create, start and expose a JSR-160
+ JMXConnectorServer use the following
+ configuration:
+
+ <bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>
+
+ By default ConnectorServerFactoryBean creates a
+ JMXConnectorServer bound to
+ "service:jmx:jmxmp://localhost:9875". The
+ serverConnector bean thus exposes the local
+ MBeanServer to clients through the JMXMP protocol
+ on localhost, port 9875. Note that the JMXMP protocol is marked as
+ optional by the JSR 160 specification: currently, the main open-source
+ JMX implementation, MX4J, and the one provided with J2SE 5.0 do
+ not support JMXMP.
+
+ To specify another URL and register the
+ JMXConnectorServer itself with the
+ MBeanServer use the serviceUrl
+ and ObjectName properties respectively:
+
+
+
+
+]]>
+
+ If the ObjectName property is set Spring
+ will automatically register your connector with the
+ MBeanServer under that
+ ObjectName. The example below shows the full set
+ of parameters which you can pass to the
+ ConnectorServerFactoryBean when creating a
+ JMXConnector:
+
+
+
+
+
+
+
+
+
+]]>
+
+ Note that when using a RMI-based connector you need the lookup
+ service (tnameserv or rmiregistry) to be started in order for the name
+ registration to complete. If you are using Spring to export remote
+ services for you via RMI, then Spring will already have constructed an
+ RMI registry. If not, you can easily start a registry using the
+ following snippet of configuration:
+
+
+
+]]>
+
+
+
+ Client-side Connectors
+
+ To create an MBeanServerConnection to a
+ remote JSR-160 enabled MBeanServer use the
+ MBeanServerConnectionFactoryBean as shown
+ below:
+
+
+
+]]>
+
+
+
+ JMX over Burlap/Hessian/SOAP
+
+ JSR-160 permits extensions to the way in which communication is
+ done between the client and the server. The examples above are using the
+ mandatory RMI-based implementation required by the JSR-160 specification
+ (IIOP and JRMP) and the (optional) JMXMP. By using other providers or
+ JMX implementations (such as MX4J) you can take advantage
+ of protocols like SOAP, Hessian, Burlap over simple HTTP or SSL and
+ others:
+
+
+
+
+]]>
+
+ In the case of the above example, MX4J 3.0.0 was used; see the
+ official MX4J documentation for more information.
+
+
+
+
+ Accessing MBeans via Proxies
+
+ Spring JMX allows you to create proxies that re-route calls to
+ MBeans registered in a local or remote MBeanServer.
+ These proxies provide you with a standard Java interface through which you
+ can interact with your MBeans. The code below shows how to configure a
+ proxy for an MBean running in a local
+ MBeanServer:
+
+
+
+
+]]>
+
+ Here you can see that a proxy is created for the MBean registered
+ under the ObjectName:
+ bean:name=testBean. The set of interfaces that the
+ proxy will implement is controlled by the
+ proxyInterfaces property and the rules for mapping
+ methods and properties on these interfaces to operations and attributes on
+ the MBean are the same rules used by the
+ InterfaceBasedMBeanInfoAssembler.
+
+ The MBeanProxyFactoryBean can create a proxy
+ to any MBean that is accessible via an
+ MBeanServerConnection. By default, the local
+ MBeanServer is located and used, but you can
+ override this and provide an MBeanServerConnection
+ pointing to a remote MBeanServer to cater for
+ proxies pointing to remote MBeans:
+
+
+
+
+
+
+
+
+
+]]>
+
+ Here you can see that we create an
+ MBeanServerConnection pointing to a remote machine
+ using the MBeanServerConnectionFactoryBean. This
+ MBeanServerConnection is then passed to the
+ MBeanProxyFactoryBean via the
+ server property. The proxy that is created will forward
+ all invocations to the MBeanServer via this
+ MBeanServerConnection.
+
+
+
+ Notifications
+
+ Spring's JMX offering includes comprehensive support for JMX
+ notifications.
+
+
+ Registering Listeners for Notifications
+
+ Spring's JMX support makes it very easy to register any number of
+ NotificationListeners with any number of MBeans
+ (this includes MBeans exported by Spring's
+ MBeanExporter and MBeans registered via some
+ other mechanism). By way of an example, consider the scenario where one
+ would like to be informed (via a Notification)
+ each and every time an attribute of a target MBean changes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ With the above configuration in place, every time a JMX
+ Notification is broadcast from the target MBean
+ (bean:name=testBean1), the
+ ConsoleLoggingNotificationListener bean that was
+ registered as a listener via the
+ notificationListenerMappings property will be
+ notified. The ConsoleLoggingNotificationListener
+ bean can then take whatever action it deems appropriate in response to
+ the Notification.
+
+ You can also use straight bean names as the link between exported beans
+ and listeners:
+
+
+
+
+
+
+
+
+
+
+
+
+ testBean
+
+
+
+
+]]>
+
+ If one wants to register a single NotificationListener
+ instance for all of the beans that the enclosing MBeanExporter
+ is exporting, one can use the special wildcard '*' (sans quotes)
+ as the key for an entry in the notificationListenerMappings
+ property map; for example:
+
+
+
+]]>
+
+ If one needs to do the inverse (that is, register a number of distinct
+ listeners against an MBean), then one has to use the
+ notificationListeners list property instead (and in
+ preference to the notificationListenerMappings
+ property). This time, instead of configuring simply a
+ NotificationListener for a single MBean, one
+ configures NotificationListenerBean instances...
+ a NotificationListenerBean encapsulates a
+ NotificationListener and the
+ ObjectName (or
+ ObjectNames) that it is to be registered against
+ in an MBeanServer. The
+ NotificationListenerBean also encapsulates a
+ number of other properties such as a
+ NotificationFilter and an arbitrary handback
+ object that can be used in advanced JMX notification scenarios.
+
+ The configuration when using
+ NotificationListenerBean instances is not wildly
+ different to what was presented previously:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bean:name=testBean1
+
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+ The above example is equivalent to the first notification example.
+ Lets assume then that we want to be given a handback object every time a
+ Notification is raised, and that additionally we
+ want to filter out extraneous Notifications by
+ supplying a NotificationFilter. (For a full
+ discussion of just what a handback object is, and indeed what a
+ NotificationFilter is, please do consult that
+ section of the JMX specification (1.2) entitled 'The JMX
+ Notification Model'.)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]><!-- handles notifications from two distinct MBeans -->bean:name=testBean1
+ bean:name=testBean2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]]><!-- implements both the NotificationListener and NotificationFilter interfaces -->
+
+
+
+
+
+
+
+
+
+
+
+]]>
+
+
+
+ Publishing Notifications
+
+ Spring provides support not just for registering to receive
+ Notifications, but also for publishing
+ Notifications.
+
+
+ Please note that this section is really only relevant to Spring
+ managed beans that have been exposed as MBeans via an
+ MBeanExporter; any existing, user-defined
+ MBeans should use the standard JMX APIs for notification publication.
+
+
+ The key interface in Spring's JMX notification publication support
+ is the NotificationPublisher interface (defined
+ in the org.springframework.jmx.export.notification
+ package). Any bean that is going to be exported as an MBean via an
+ MBeanExporter instance can implement the related
+ NotificationPublisherAware interface to gain
+ access to a NotificationPublisher instance. The
+ NotificationPublisherAware interface simply
+ supplies an instance of a NotificationPublisher
+ to the implementing bean via a simple setter method, which the bean can
+ then use to publish Notifications.
+
+ As stated in the Javadoc for the
+ NotificationPublisher class, managed beans that
+ are publishing events via the
+ NotificationPublisher mechanism are
+ not responsible for the state management of any
+ notification listeners and the like ... Spring's JMX support will take
+ care of handling all the JMX infrastructure issues. All one need do as
+ an application developer is implement the
+ NotificationPublisherAware interface and start
+ publishing events using the supplied
+ NotificationPublisher instance. Note that the
+ NotificationPublisher will be set
+ after the managed bean has been registered with an
+ MBeanServer.
+
+ Using a NotificationPublisher instance is
+ quite straightforward... one simply creates a JMX
+ Notification instance (or an instance of an
+ appropriate Notification subclass), populates
+ the notification with the data pertinent to the event that is to be
+ published, and one then invokes the
+ sendNotification(Notification) on the
+ NotificationPublisher instance, passing in the
+ Notification.
+
+ Find below a simple example... in this scenario, exported
+ instances of the JmxTestBean are going to publish
+ a NotificationEvent every time the
+ add(int, int) operation is invoked.
+
+ // other getters and setters omitted for clarity
+
+ The NotificationPublisher interface and the
+ machinery to get it all working is one of the nicer features of Spring's JMX support.
+ It does however come with the price tag of coupling your classes to both Spring and JMX; as
+ always, the advice here is to be pragmatic... if you need the functionality offered by the
+ NotificationPublisher and you can accept the coupling to both Spring
+ and JMX, then do so.
+
+
+
+
+ Further Resources
+
+ This section contains links to further resources about JMX.
+
+
+
+ The JMX homepage at Sun
+
+
+
+ The JMX specification (JSR-000003)
+
+
+
+ The JMX Remote API specification (JSR-000160)
+
+
+
+ The MX4J
+ homepage (an Open Source implementation of various JMX
+ specs)
+
+
+
+ Getting Started with JMX - an introductory article from Sun.
+
+
+
+
\ No newline at end of file
diff --git a/spring-framework-reference/src/mail.xml b/spring-framework-reference/src/mail.xml
new file mode 100644
index 00000000000..dd77e2df489
--- /dev/null
+++ b/spring-framework-reference/src/mail.xml
@@ -0,0 +1,403 @@
+
+
+ Email
+
+
+ Introduction
+
+ Library dependencies
+ 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.
+
+
+ The JavaMailmail.jar library
+
+
+ The JAFactivation.jar library
+
+
+ All of these libraries are available in the Spring-with-dependencies
+ distribution of the Spring Framework (in addition to also being freely
+ available on the web).
+
+
+ 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.
+
+ The org.springframework.mail package is the root level package
+ for the Spring Framework's email support. The central interface for sending
+ emails is the MailSender interface; a simple value object
+ encapsulating the properties of a simple mail such as from and
+ to (plus many others) is the SimpleMailMessage 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 MailException. Please
+ refer to the Javadocs for more information on the rich mail exception hierarchy.
+
+ The org.springframework.mail.javamail.JavaMailSender
+ interface adds specialized JavaMail features such as MIME
+ message support to the MailSender interface
+ (from which it inherits). JavaMailSender also provides a
+ callback interface for preparation of JavaMail MIME messages, called
+ org.springframework.mail.javamail.MimeMessagePreparator
+
+
+
+
+ Usage
+ Let's assume there is a business interface called OrderManager:
+
+
+ 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.
+
+
+ Basic MailSender and SimpleMailMessage usage
+ // Do the business calculations...// Call the collaborators to persist the order...// Create a thread safe "copy" of the template message and customize it// simply log it and go on...
+
+ Find below the bean definitions for the above code:
+
+
+
+
+]]><!-- this is a template message that we can pre-load with default state -->
+
+
+
+
+
+
+
+]]>
+
+
+
+
+ Using the JavaMailSender and the MimeMessagePreparator
+ Here is another implementation of OrderManager using
+ the MimeMessagePreparator callback interface. Please note
+ in this case that the mailSender property is of type
+ JavaMailSender so that we are able to use the JavaMail
+ MimeMessage class:
+
+ // Do the business calculations...// Call the collaborators to persist the order...// simply log it and go on...
+
+
+ The mail code is a crosscutting concern and could well be a candidate
+ for refactoring into a custom Spring AOP aspect,
+ which then could be executed at appropriate joinpoints on the
+ OrderManager target.
+
+
+ The Spring Framework's mail support ships with two
+ MailSender implementations. The standard JavaMail
+ implementation and the implementation on top of Jason Hunter's
+ MailMessage class that is included in
+ the com.oreilly.servlet
+ package. Please refer to the relevant Javadocs for more information.
+
+
+
+
+
+ Using the JavaMail MimeMessageHelper
+
+ A class that comes in pretty handy when dealing with JavaMail messages is
+ the org.springframework.mail.javamail.MimeMessageHelper class,
+ which shields you from having to use the verbose JavaMail API. Using
+ the MimeMessageHelper it is pretty easy to
+ create a MimeMessage:
+ // of course you would use DI in any real-world cases
+
+
+ Sending attachments and inline resources
+ Multipart email messages allow for both attachments and inline resources.
+ Examples of inline resources would be be images or a stylesheet you want to use
+ in your message, but that you don't want displayed as an attachment.
+
+ Attachments
+ The following example shows you how to use the
+ MimeMessageHelper to send an email along with a
+ single JPEG image attachment.
+ // use the true flag to indicate you need a multipart message// let's attach the infamous windows Sample file (this time copied to c:/)
+
+
+ Inline resources
+ The following example shows you how to use the
+ MimeMessageHelper to send an email along with an
+ inline image.
+ // use the true flag to indicate you need a multipart message// use the true flag to indicate the text included is HTML