diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml
index f2f62ea5334..699bb587110 100644
--- a/spring-framework-reference/src/beans.xml
+++ b/spring-framework-reference/src/beans.xml
@@ -2525,7 +2525,7 @@ public class ReplacementComputeValue implements MethodReplacer {
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">
+ <bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
<!-- arbitrary method replacement -->
<replaced-method name="computeValue" replacer="replacementComputeValue">
diff --git a/spring-framework-reference/src/classic-aop-spring.xml b/spring-framework-reference/src/classic-aop-spring.xml
new file mode 100644
index 00000000000..e20cf2e9116
--- /dev/null
+++ b/spring-framework-reference/src/classic-aop-spring.xml
@@ -0,0 +1,1955 @@
+
+
+
+ Classic Spring AOP Usage
+
+ 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 AOP 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.
+
+
+
+
+
+
diff --git a/spring-framework-reference/src/classic-spring.xml b/spring-framework-reference/src/classic-spring.xml
index 53a879f0e18..82a121cad22 100644
--- a/spring-framework-reference/src/classic-spring.xml
+++ b/spring-framework-reference/src/classic-spring.xml
@@ -352,4 +352,102 @@
...
+
+
+ JMS Usage
+
+ One of the benefits of Spring's JMS support is to shield the user
+ from differences between the JMS 1.0.2 and 1.1 APIs. (For a description of
+ the differences between the two APIs see sidebar on Domain Unification).
+ Since it is now common to encounter only the JMS 1.1 API the use of
+ classes that are based on the JMS 1.0.2 API has been deprecated in Spring
+ 3.0. This section describes Spring JMS support for the JMS 1.0.2
+ deprecated classes.
+
+
+ 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.
+
+
+
+
+ JmsTemplate
+
+ Located in the package
+ org.springframework.jms.core the class
+ JmsTemplate102 provides all of the features of
+ the JmsTemplate described the JMS chapter, but is
+ based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence,
+ if you are using JmsTemplate102 you need to set the boolean property
+ pubSubDomain 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.
+
+
+
+ Asynchronous Message Reception
+
+ MessageListenerAdapter's
+ are used in conjunction with Spring's message
+ listener containers to support asynchronous message reception by
+ exposing almost any class as a Message-driven POJO. If you are using the
+ JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as
+ MessageListenerAdapter102,
+ SimpleMessageListenerContainer102, and
+ DefaultMessageListenerContainer102. These classes
+ provide the same functionality as the JMS 1.1 based counterparts but
+ rely only on the JMS 1.0.2 API.
+
+
+
+ Connections
+
+ The ConnectionFactory interface is part of
+ the JMS specification and serves as the entry point for working with
+ JMS. Spring provides an implementation of the
+ ConnectionFactory interface,
+ SingleConnectionFactory102, based on the JMS
+ 1.0.2 API that will return the same Connection on
+ all createConnection calls and ignore calls to
+ close. You will need to set the boolean
+ property pubSubDomain to indicate which messaging
+ domain is used as SingleConnectionFactory102 will
+ always explicitly differentiate between a
+ javax.jms.QueueConnection and a
+ javax.jmsTopicConnection.
+
+
+
+ Transaction Management
+
+ In a JMS 1.0.2 environment the class
+ JmsTransactionManager102 provides support for
+ managing JMS transactions for a single Connection Factory. Please refer
+ to the reference documentation on JMS Transaction
+ Management for more information on this functionality.
+
+
diff --git a/spring-framework-reference/src/jms.xml b/spring-framework-reference/src/jms.xml
index 4698d73e036..8e05ce3c4d8 100644
--- a/spring-framework-reference/src/jms.xml
+++ b/spring-framework-reference/src/jms.xml
@@ -1,7 +1,6 @@
-
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
JMS (Java Message Service)
@@ -9,37 +8,16 @@
IntroductionSpring 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).
+ of the JMS API much like Spring's integration does for the JDBC
+ API.
-
- 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.
-
-
+ 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).The package org.springframework.jms.core provides
the core functionality for using JMS. It contains JMS template classes
@@ -54,16 +32,20 @@
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
+ 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.
@@ -71,281 +53,325 @@
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 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
+ Using Spring JMS
-
- JmsTemplate
+
+ 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.
+ The JmsTemplate class is the central class
+ in the JMS core package. It simplifies the use of JMS since it handles
+ the creation and release of resources when sending or synchronously
+ recieving messages.
- 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.
+ Code that uses the JmsTemplate only needs
+ to implement callback interfaces giving them a clearly defined high
+ level 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.
+ 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.
+ 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.
-
-
+
+ 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.
+
+ Connections
- 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.
+ 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.
- 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.
+ 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.
- 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.
+
+ Caching Messaging Resources
- 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.
+ The standard API involves creating many intermediate objects. To
+ send a message the following 'API' walk is performed
- 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
+ ConnectionFactory->Connection->Session->MessageProducer->send
- 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.)
+ Between the ConnectionFactory and the Send operation there are
+ three intermediate objects that are created and destroyed. To optimise
+ the resource usage and increase performance two implementations of
+ IConnectionFactory are provided.
+
- 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.
+
+ SingleConnectionFactory
- There are three standard JMS message listener containers packaged
- with Spring, each with its specialised feature set.
+ 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.
+
-
- SimpleMessageListenerContainer
+
+ CachingConnectionFactory
- 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.
-
+ The CachingConnectionFactory extends the
+ functionality of SingleConnectionFactory and
+ adds the caching of Sessions, MessageProducers, and MessageConsumers.
+ The initial cache size is set to 1, use the property
+ SessionCacheSize to increase the number of cached
+ sessions. Note that the number of actual cached sessions will be more
+ than that number as sessions are cached based on their acknowledgment
+ mode, so there can be up to 4 cached session instances when
+ SessionCacheSize is set to one, one for each
+ AcknowledgementMode. MessageProducers and MessageConsumers are cached
+ within their owning session and also take into account the unique
+ properties of the producers and consumers when caching.
+ MessageProducers are cached based on their destination.
+ MessageConsumers are cached based on a key composed of the
+ destination, selector, noLocal delivery flag, and the durable
+ subscription name (if creating durable consumers).
+
+
-
- DefaultMessageListenerContainer
+
+ Destination Management
- 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.
-
+ 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.
-
- ServerSessionMessageListenerContainer
+ 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.
- 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.
-
-
+ 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.
+ This property is used by JmsTemplate determines
+ the behavior of dynamic destination resolution via implementations of
+ the DestinationResolver interface.
-
- Transaction management
+ 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.
+
- 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.
+
+ Message Listener Containers
- 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.
+ 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.)
- 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.)
+ 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.
- 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.
-
+ 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
+ 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
@@ -353,7 +379,7 @@
default destination. Here is an example that sends a message to a queue
using the 1.0.2 implementation.
- import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
@@ -361,7 +387,6 @@ import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jms.core.JmsTemplate;
-import org.springframework.jms.core.JmsTemplate102;
public class JmsQueueSender {
@@ -369,7 +394,7 @@ public class JmsQueueSender {
private Queue queue;
public void setConnectionFactory(ConnectionFactory cf) {
- this.jmsTemplate = new JmsTemplate102(cf, false);
+ this.jmsTemplate = new JmsTemplate(cf, false);
}
public void setQueue(Queue queue) {
@@ -383,41 +408,34 @@ public class JmsQueueSender {
}
});
}
-}]]>
+}
- 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
+ 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
+ (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.
+ 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)
+ 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
+
+
+ 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
@@ -442,16 +460,18 @@ public class JmsQueueSender {
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.
+ 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.
+ 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.
- public void sendWithConversion() {
Map map = new HashMap();
map.put("Name", "Mark");
map.put("Age", new Integer(47));
@@ -462,9 +482,11 @@ public class JmsQueueSender {
return message;
}
});
-}]]>
+}
+
This results in a message of the form:
- MapMessage={
Header={
... standard headers ...
CorrelationID={123-00001}
@@ -476,32 +498,35 @@ public class JmsQueueSender {
Name={String:Mark}
Age={Integer:47}
}
-}]]>
-
+}
+
-
- SessionCallback and ProducerCallback
- While the send operations cover many common usage scenarios, there
+
+ 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
+ Session /
+ MessageProducer pair respectfully. The
+ execute() methods on
JmsTemplate execute these callback
methods.
-
+
- Receiving a message
+ Receiving a message
-
- Synchronous Reception
+
+ Synchronous Reception
- While JMS is typically associated with asynchronous processing, it
+ 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
@@ -509,21 +534,24 @@ public class JmsQueueSender {
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:
-
+ 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:
+
+ import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@@ -543,76 +571,94 @@ public class ExampleListener implements MessageListener {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
-}]]>
- 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.
- 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) -->
+<bean id="messageListener" class="jmsexample.ExampleListener" />
+
+<!-- and this is the message listener container -->
+<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="destination" ref="destination"/>
+ <property name="messageListener" ref="messageListener" />
+</bean>
+
+ 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.
+
+ package org.springframework.jms.listener;
public interface SessionAwareMessageListener {
- void onMessage(Message message, Session session) ]]>
- 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.
- throws JMSException;
+}
+
+ 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).
+
+ 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.
+
+ public interface MessageDelegate {
void handleMessage(String message);
@@ -621,600 +667,676 @@ public interface SessionAwareMessageListener {
void handleMessage(byte[] message);
void handleMessage(Serializable message);
-}]]>
- // 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.
- public class DefaultMessageDelegate implements MessageDelegate {
+ // 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) -->
+<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
+ <constructor-arg>
+ <bean class="jmsexample.DefaultMessageDelegate"/>
+ </constructor-arg>
+</bean>
+
+<!-- and this is the message listener container... -->
+<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="destination" ref="destination"/>
+ <property name="messageListener" ref="messageListener" />
+</bean>
+
+ 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.
+
+ public interface TextMessageDelegate {
void receive(TextMessage message);
-}]]>
- // 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...public class DefaultTextMessageDelegate implements TextMessageDelegate {
+ // implementation elided for clarity...
+}
+
+ The configuration of the attendant
+ MessageListenerAdapter would look like
+ this:
+
+ <bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
+ <constructor-arg>
+ <bean class="jmsexample.DefaultTextMessageDelegate"/>
+ </constructor-arg>
+ <property name="defaultListenerMethod" value="receive"/>
+ <!-- we don't want automatic message context extraction -->
+ <property name="messageConverter">
+ <null/>
+ </property>
+</bean>
+
+ 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:
+
+ public interface ResponsiveTextMessageDelegate {
+
+ // notice the return type...
String receive(TextMessage message);
-}]]>
- // 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.
+ public class DefaultResponsiveTextMessageDelegate implements ResponsiveTextMessageDelegate {
+ // implementation elided for clarity...
+}
- 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.
+ 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
- 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.
+ Invoking a message listener within a transaction only requires
+ reconfiguration of the listener container.
- 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).
+ 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.
-
-]]>
+ <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="destination" ref="destination"/>
+ <property name="messageListener" ref="messageListener"/>
+ <property name="sessionTransacted" value="true"/>
+</bean>
- Then you just need to add it to our earlier container configuration. The
- container will take care of the rest.
+ 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).
+
+ <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
+
+
+ Then you just need to add it to our earlier container
+ configuration. The container will take care of the rest.
+
+ <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
+ <property name="connectionFactory" ref="connectionFactory"/>
+ <property name="destination" ref="destination"/>
+ <property name="messageListener" ref="messageListener"/>
+ <property name="transactionManager" ref="transactionManager"/>
+</bean>
+ 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.
-
+ 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.
-
-
-
-
-
-
-
-
-]]>
+ <bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">
+ <property name="resourceAdapter" ref="resourceAdapter"/>
+ <property name="activationSpecConfig">
+ <bean class="org.springframework.jms.listener.endpoint.JmsActivationSpecConfig">
+ <property name="destinationName" value="myQueue"/>
+ </bean>
+ </property>
+ <property name="messageListener" ref="myMessageListener"/>
+</bean>
- 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>).
+ 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>).
-
-
-
-
-
-
-
-
-
-]]>
+ <bean class="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">
+ <property name="resourceAdapter" ref="resourceAdapter"/>
+ <property name="activationSpec">
+ <bean class="org.apache.activemq.ra.ActiveMQActivationSpec">
+ <property name="destination" value="myQueue"/>
+ <property name="destinationType" value="javax.jms.Queue"/>
+ </bean>
+ </property>
+ <property name="messageListener" ref="myMessageListener"/>
+</bean>Using Spring's ResourceAdapterFactoryBean,
the target ResourceAdapter may be
configured locally as depicted in the following example.
-
-
-
-
-
-
-
-
-
-]]>
+ <bean id="resourceAdapter" class="org.springframework.jca.support.ResourceAdapterFactoryBean">
+ <property name="resourceAdapter">
+ <bean class="org.apache.activemq.ra.ActiveMQResourceAdapter">
+ <property name="serverUrl" value="tcp://localhost:61616"/>
+ </bean>
+ </property>
+ <property name="workManager">
+ <bean class="org.springframework.jca.work.SimpleTaskWorkManager"/>
+ </property>
+</bean>
- 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.
+ 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 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,
+ 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:
+ 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.
+ 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.
+ 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:
-
-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:
+
+ <?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:jms="http://www.springframework.org/schema/jms"xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-]]>http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
+http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-2.5.xsd">
-]]><!-- <bean/> definitions here --><!-- <bean/> definitions here -->
-]]>
+</beans>
- 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 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.
-
+ <jms:listener-container>
-
+ <jms:listener destination="queue.orders" ref="orderService" method="placeOrder"/>
-
+ <jms:listener destination="queue.confirmations" ref="confirmationLogger" method="log"/>
-]]>
+</jms:listener-container>
+
+ 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:
- 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
+ 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.
-
+
+ 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.
-
+ destination (required)
+
+ The destination name for this listener, resolved
+ through the DestinationResolver
+ strategy.
+
ref (required)
-
- The bean name of the handler object.
-
+
+ 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.
-
+
+ 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.
-
+
+ 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.
-
+
+ The name of the durable subscription, if
+ any.
+
selector
-
- An optional message selector for this listener.
-
+
+ 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 <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.
- <jms:listener-container connection-factory="myConnectionFactory"
task-executor="myTaskExecutor"
destination-resolver="myDestinationResolver"
transaction-manager="myTransactionManager"
- concurrency="10">
+ concurrency="10">
-
+ <jms:listener destination="queue.orders" ref="orderService" method="placeOrder"/>
-
+ <jms:listener destination="queue.confirmations" ref="confirmationLogger" method="log"/>
-]]>
+</jms:listener-container>
+
+ 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.
- 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
+ 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').
-
+
+ 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').
-
+
+ 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.
-
+
+ A reference to the Spring
+ TaskExecutor for the JMS listener
+ invokers.
+
destination-resolver
-
- A reference to the DestinationResolver
- strategy for resolving JMS Destinations.
-
+
+ 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.
-
+
+ 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.
-
+
+ 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.
-
+
+ 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).
-
+
+ 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.
-
+
+ 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).
-
+
+ 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.
-
+
+ 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!
-
+ 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
+ Configuring a JCA-based listener container with the "jms" schema
+ support is very similar.
+
+ <jms:jca-listener-container resource-adapter="myResourceAdapter"
+ destination-resolver="myDestinationResolver"
+ transaction-manager="myTransactionManager"
+ concurrency="10">
+
+ <jms:listener destination="queue.orders" ref="myMessageListener"/>
+
+</jms:jca-listener-container>
+
+ 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!
+
+
+
+
+
+
diff --git a/spring-framework-reference/src/metadata.xml b/spring-framework-reference/src/metadata.xml
index abc5001a6c2..131e95d9f39 100644
--- a/spring-framework-reference/src/metadata.xml
+++ b/spring-framework-reference/src/metadata.xml
@@ -1,247 +1,148 @@
-
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
- Annotations and Source Level Metadata Support
-
- Introduction
- Source-level metadata is the addition of attributes or
- annotations to program elements - usually, classes
- and/or methods.
- For example, we might add metadata to a class as follows:
-
- We could add metadata to a method as follows:
-
- Both of these examples use Jakarta Commons Attributes syntax.
-
- Source-level metadata was introduced to the mainstream by XDoclet
- (in the Java world) and by the release of Microsoft's .NET platform, which
- uses source-level attributes to control transactions, pooling and other
- behavior.
-
-
- The value in this approach has been recognized in the J2EE
- community. For example, it's much less verbose than the traditional XML
- deployment descriptors used exclusively by EJB. While it is desirable to
- externalize some things from program source code, some important
- enterprise settings - notably transaction characteristics - arguably belong
- in program source. Contrary to the assumptions of the EJB spec, it seldom
- makes sense to modify the transactional characteristics of a method
- (although parameters like transaction timeouts might change!).
-
-
- Although metadata attributes are typically used mainly by framework
- infrastructure to describe the services application classes require, it
- should also be possible for metadata attributes to be queried at runtime.
- This is a key distinction from solutions such as XDoclet, which
- view metadata primarily as a way of generating code such as EJB artefacts.
-
-
- There are a number of solutions in this space, including:
-
-
-
- Standard Java Annotations: the
- standard Java metadata implementation (developed as JSR-175 and available
- in Java 5). Spring has specific Java 5 annotations for transactional
- demarcation, JMX, and aspects (to be precise they are AspectJ annotations).
- However, since Spring supports Java 1.4 as well, a solution for said
- JVM versions is needed too. Spring metadata support provides such a
- solution.
-
-
- XDoclet: well-established
- solution, primarily intended for code generation.
-
-
- Various open source attribute
- implementations, for Java 1.4, of which Commons
- Attributes is the most complete implementation. All these require
- a special pre- or post-compilation step.
-
-
-
-
- Spring's metadata support
- In keeping with its provision of abstractions over important
- concepts, Spring provides a facade to metadata implementations, in the
- form of the org.springframework.metadata.Attributes
- interface. Such a facade adds value for several reasons:
-
-
- Even though Java 5 provides metadata support at language level, there will
- still be value in providing such an abstraction:
-
-
-
- Java 5 metadata is static. It is associated with a class
- at compile time, and cannot be changed in a deployed
- environment (annotation state can actually be changed
- at runtime using reflection, but doing so would really be
- a bad practice). There is a need for hierarchical metadata,
- providing the ability to override certain attribute values in
- deployment - for example, in an XML file.
-
-
- Java 5 metadata is returned through the Java reflection
- API. This makes it impossible to mock during test time. Spring
- provides a simple interface to allow this.
-
-
- There will be a need for metadata support in 1.3 and 1.4
- applications for at least two years. Spring aims to provide
- working solutions now; forcing the use of
- Java 5 is not an option in such an important area.
-
-
-
-
- Current metadata APIs, such as Commons Attributes (used by
- Spring 1.0-1.2) are hard to test. Spring provides a simple metadata
- interface that is much easier to mock.
-
-
- The Spring Attributes interface looks like this:
- Annotations and Source Level Metadata Support
- Collection getAttributes(Class targetClass);
+
+ Introduction
- Collection getAttributes(Class targetClass, Class filter);
+ Java 5 introduced source-level metadata called annotations to
+ program elements, usually, classes and/or methods
- Collection getAttributes(Method targetMethod);
+ For example we might add metadata at the class level using the
+ Spring's @Transactional annotation that is used to support Spring's
+ declarative transaction management features.
- Collection getAttributes(Method targetMethod, Class filter);
+ @Transactional
+public class PetStoreImpl implements PetStoreFacade, OrderService {
- Collection getAttributes(Field targetField);
+ We could also add metadata to a method as follows:
- Collection getAttributes(Field targetField, Class filter);
-}]]>
-
- This is a lowest common denominator interface. JSR-175 offers more
- capabilities than this, such as attributes on method arguments.
-
-
- Note that this interface offers Object
- attributes, like .NET. This distinguishes it from attribute systems such
- as that of Nanning Aspects, which offer only String
- attributes. There is a significant advantage in supporting
- Object attributes, namely that it enables
- attributes to participate in class hierarchies and allows such
- attributes to react intelligently to their configuration parameters.
-
-
- With most attribute providers, attribute classes are configured
- via constructor arguments or JavaBean properties. Commons Attributes
- supports both.
-
- As with all Spring abstraction APIs, Attributes
- is an interface. This makes it easy to mock attribute implementations for unit tests.
-
-
- Annotations
-
- The Spring Framework ships with a number of custom Java 5+ annotations.
-
-
- @Required
- The @Required annotation in the
- org.springframework.beans.factory.annotation
- package can be used to mark a property as
- being 'required-to-be-set' (i.e. an
- annotated (setter) method of a class must be configured to be
- dependency injected with a value), else an
- Exception will be thrown by the container
- at runtime.
- The best way to illustrate the usage of this annotation is to
- show an example:
- public class PetStoreImpl implements PetStoreFacade, OrderService {
- ]]>// the SimpleMovieLister has a dependency on the MovieFinder
+
+ The value of using annoations has been broadly embrassed by the JEE
+ community. For example, it's much less verbose than the traditional XML
+ deployment descriptors. While it is desirable to externalize some things
+ from program source code, some important enterprise settings - notably
+ transaction characteristics - arguably belong in program source.
+
+ Spring uses custom Java 5 annotations thoughout the framework across
+ a wide range of features such as DI, MVC, and AOP and supports JEE
+ standard annotations such as @PreDestroy and @PostConstruct defined by
+ JSR-250. This chapter describes the @Required attribute and provides links
+ to other parts the documentation where the various attributes are
+ described in more detail.
+
+
+
+ Annotations
+
+ The Spring Framework ships with a number of custom Java 5+
+ annotations.
+
+
+ @Required
+
+ The @Required annotation in the
+ org.springframework.beans.factory.annotation package
+ can be used to mark a property as being
+ 'required-to-be-set' (i.e. an annotated (setter)
+ method of a class must be configured to be dependency injected with a
+ value), else an Exception will be thrown by the
+ container at runtime.
+
+ The best way to illustrate the usage of this annotation is to show
+ an example:
+
+ 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// a setter method so that the Spring container can 'inject' a MovieFinder
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
- ]]>// business logic that actually 'uses' the injected MovieFinder is omitted...
-
- Hopefully the above class definition reads easy on the eye.
- Any and all BeanDefinitions for the
- SimpleMovieLister class must be provided
- with a value.
-
-
- Let's look at an example of some XML configuration that will
- not pass validation.
-
-
- ]]><!-- whoops, no MovieFinder is set (and this property is @Required) -->]]>
-
- At runtime the following message will be generated by the Spring container
- (the rest of the stack trace has been truncated).
-
-
-
- There is one last little (small, tiny) piece of Spring configuration
- that is required to actually 'switch on' this
- behavior. Simply annotating the 'setter' properties
- of your classes is not enough to get this behavior. You need
- to enable a component that is aware of the @Required
- annotation and that can process it appropriately.
-
-
- This component is the RequiredAnnotationBeanPostProcessor class.
- This is a special BeanPostProcessor
- implementation that is @Required-aware
- and actually provides the 'blow up if this required property
- has not been set' logic. It is very easy
- to configure; simply drop the following bean definition into your Spring
- XML configuration.
-
- ]]>
-
- Finally, one can configure an instance of the
- RequiredAnnotationBeanPostProcessor class to look
- for anotherAnnotation type.
- This is great if you already have your own
- @Required-style annotation. Simply plug it into
- the definition of a RequiredAnnotationBeanPostProcessor and
- you are good to go.
-
-
- By way of an example, let's suppose you (or your organization / team) have
- defined an attribute called @ Mandatory.
- You can make a RequiredAnnotationBeanPostProcessor
- instance @Mandatory-aware like so:
-
-
-
-]]>
-
- Here is the source code for the @Mandatory
- annotation. You will need to ensure that your custom annotation type
- is itself annotated with appropriate annotations for its target
- and runtime retention policy.
-
- // business logic that actually 'uses' the injected MovieFinder is omitted...
+}
+
+ Hopefully the above class definition reads easy on the eye. Any
+ and all BeanDefinitions for the
+ SimpleMovieLister class must be provided with a
+ value.
+
+ Let's look at an example of some XML configuration that will
+ not pass validation.
+
+ <bean id="movieLister" class="x.y.SimpleMovieLister">
+ <!-- whoops, no MovieFinder is set (and this property is @Required) -->
+</bean>
+
+ At runtime the following message will be generated by the Spring
+ container (the rest of the stack trace has been truncated).
+
+ Exception in thread "main" java.lang.IllegalArgumentException:
+ Property 'movieFinder' is required for bean 'movieLister'.
+
+ There is one last little (small, tiny) piece of Spring
+ configuration that is required to actually 'switch
+ on' this behavior. Simply annotating the
+ 'setter' properties of your classes is not enough
+ to get this behavior. You need to enable a component that is aware of
+ the @Required annotation and that can
+ process it appropriately.
+
+ This component is the
+ RequiredAnnotationBeanPostProcessor class. This
+ is a special BeanPostProcessor
+ implementation that is @Required-aware
+ and actually provides the 'blow up if this required property
+ has not been set' logic. It is very easy
+ to configure; simply drop the following bean definition into your Spring
+ XML configuration.
+
+ <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
+
+ Finally, one can configure an instance of the
+ RequiredAnnotationBeanPostProcessor class to look
+ for another
+ Annotation type. This is great if you
+ already have your own @Required-style
+ annotation. Simply plug it into the definition of a
+ RequiredAnnotationBeanPostProcessor and you are
+ good to go.
+
+ By way of an example, let's suppose you (or your organization /
+ team) have defined an attribute called @
+ Mandatory. You can make a
+ RequiredAnnotationBeanPostProcessor instance
+ @Mandatory-aware like so:
+
+ <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
+ <property name="requiredAnnotationType" value="your.company.package.Mandatory"/>
+</bean>
+
+ Here is the source code for the
+ @Mandatory annotation. You will need to
+ ensure that your custom annotation type is itself annotated with
+ appropriate annotations for its target and runtime retention
+ policy.
+
+ package your.company.package;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -251,256 +152,38 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Mandatory {
-}]]>
-
-
- Other @Annotations in Spring
-
- Annotations are also used in a number of other places throughout Spring.
- Rather than being described here, these annotations are described in that
- section or chapter of the reference documentation to which they are most
- relevant.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Integration with Jakarta Commons Attributes
-
- Presently Spring supports only Jakarta Commons Attributes out of the
- box, although it is easy to provide implementations of the
- org.springframework.metadata.Attributes interface for
- other metadata providers.
-
-
- Commons Attributes 2.2
- (http://jakarta.apache.org/commons/attributes/)
- is a capable attributes solution. It supports attribute configuration via
- constructor arguments and JavaBean properties, which offers better
- self-documentation in attribute definitions. (Support for JavaBean
- properties was added at the request of the Spring team.)
-
-
- We've already seen two examples of Commons Attributes attributes
- definitions. In general, we will need to express:
-
-
-
-
- The name of the attribute class. This can
- be a fully qualified name (FQN), as shown above. If the relevant attribute class has already
- been imported, the FQN isn't required. It's also possible to specify
- "attribute packages" in attribute compiler configuration.
-
-
-
-
- Any necessary parameterization. This is done via
- constructor arguments or JavaBean properties.
-
-
-
- Bean properties look as follows:
-
-
- It's possible to combine constructor arguments and JavaBean
- properties (as in Spring IoC).
-
-
- Because, unlike Java 1.5 attributes, Commons Attributes is not
- integrated with the Java language, it is necessary to run a special
- attribute compilation step as part of the build
- process.
-
-
- To run Commons Attributes as part of the build process, you will
- need to do the following:
-
-
- 1. Copy the necessary library jars to
- $ANT_HOME/lib. Four Jars are required, and all are
- distributed with Spring:
-
-
-
- the Commons Attributes compiler jar and API jar
-
-
- xJavadoc.jar from XDoclet
-
-
- commons-collections.jar from Jakarta Commons
-
-
-
- 2. Import the Commons Attributes ant tasks into your project build
- script, as follows:
-
- ]]>
-
- 3. Next, define an attribute compilation task, which will use the
- Commons Attributes attribute-compiler task to "compile" the attributes in
- the source. This process results in the generation of additional sources,
- to a location specified by the destdir attribute. Here we show the use of
- a temporary directory for storing the generated files:
-
-
+}
+
-
-
-
+
+ Other @Annotations in Spring
-]]>
-
- The compile target that runs javac over the sources should depend on
- this attribute compilation task, and must also compile the generated
- sources, which we output to our destination temporary directory. If there
- are syntax errors in your attribute definitions, they will normally be
- caught by the attribute compiler. However, if the attribute definitions
- are syntactically plausible, but specify invalid types or class names, the
- compilation of the generated attribute classes may fail. In this case, you
- can look at the generated classes to establish the cause of the
- problem.
-
-
- Commons Attributes also provides Maven support. Please refer to
- Commons Attributes documentation for further information.
-
-
- While this attribute compilation process may look complex, in fact
- it's a one-off cost. Once set up, attribute compilation is incremental, so
- it doesn't usually noticeably slow the build process. And once the
- compilation process is set up, you may find that use of attributes as
- described in this chapter can save you a lot of time in other
- areas.
-
-
- If you require attribute indexing support (only currently required
- by Spring for attribute-targeted web controllers, discussed below), you
- will need an additional step, which must be performed on a jar file of
- your compiled classes. In this additional step, Commons Attributes will
- create an index of all the attributes defined on your sources, for
- efficient lookup at runtime. The step looks like this:
-
-
-
-
+ Annotations are also used in a number of other places throughout
+ Spring. Rather than being described here, these annotations are
+ described in that section or chapter of the reference documentation to
+ which they are most relevant.
-]]>
-
- See the /attributes directory of the Spring JPetStore sample
- application for an example of this build process. You can take the build
- script it contains and modify it for your own projects.
-
-
- If your unit tests depend on attributes, try to express the
- dependency on the Spring Attributes abstraction, rather than Commons
- Attributes. Not only is this more portable - for example, your tests will
- still work if you switch to Java 1.5 attributes in future - it simplifies
- testing. Also, Commons Attributes is a static API, while Spring provides a
- metadata interface that you can easily mock.
-
-
-
- Metadata and Spring AOP autoproxying
-
- The most important uses of metadata attributes are in conjunction
- with Spring AOP. This provides a .NET-like programming model, where
- declarative services are automatically provided to application objects
- that declare metadata attributes. Such metadata attributes can be
- supported out of the box by the framework, as in the case of declarative
- transaction management, or can be custom.
-
-
- Fundamentals
-
- This builds on the Spring AOP autoproxy functionality.
- Configuration might look like this:
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-]]>
-
- The basic concepts here should be familiar from the discussion of
- autoproxying in the AOP chapter.
-
-
- The most important bean definitions are the auto-proxy creator
- and the advisor. Note that the actual bean names are not important;
- what matters is their class.
-
-
- The bean definition of class
- org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
- will automatically advise ("auto-proxy") all bean instances in the
- current factory based on matching advisor implementations. This class
- knows nothing about attributes, but relies on advisors' pointcuts
- matching. The pointcuts, however, do know about attributes.
-
-
- Thus we simply need an AOP advisor that will provide declarative
- transaction management based on attributes.
-
-
- It is possible to add arbitrary custom advisor implementations as
- well, and they will also be evaluated and applied automatically. (You
- can use advisors whose pointcuts match on criteria besides attributes in
- the same autoproxy configuration, if necessary.)
-
-
- Finally, the attributes bean is the Commons
- Attributes Attributes implementation. Replace it with another
- implementation of the
- org.springframework.metadata.Attributes
- interface to source attributes from a different source.
-
-
-
- Declarative transaction management
-
- The most common use of source-level attributes is to provide
- declarative transaction management. Once the bean definitions
- shown above are in place, you can define any number of application
- objects requiring declarative transactions. Only those classes or
- methods with transaction attributes will be given transaction advice.
- You need to do nothing except define the required transaction
- attributes.
-
- Please note that you can specify transaction attributes at either class
- or method level. Class-level attributes, if specified, will be "inherited"
- by all methods whereas method attributes will wholly override any
- class-level attributes.
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-framework-reference/src/spring-framework-reference.xml b/spring-framework-reference/src/spring-framework-reference.xml
index 9b18161341a..1815f40b02a 100644
--- a/spring-framework-reference/src/spring-framework-reference.xml
+++ b/spring-framework-reference/src/spring-framework-reference.xml
@@ -331,6 +331,7 @@
+