Documentation cleanup.
Move classic aop-api chapter to appendix Move JMS 1.0.2 related documentation to appendix Remove references to Commons Annotations and source level metadata abstraction Fix program highlighting issue in beans.xml git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1337 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
d2c3e738c1
commit
b69eb014bc
|
|
@ -2525,7 +2525,7 @@ public class ReplacementComputeValue implements MethodReplacer {
|
||||||
<para>The bean definition to deploy the original class and specify the
|
<para>The bean definition to deploy the original class and specify the
|
||||||
method override would look like this:</para>
|
method override would look like this:</para>
|
||||||
|
|
||||||
<programlisting language="xml"><bean id="myValueCalculator class="x.y.z.MyValueCalculator">
|
<programlisting language="xml"><bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
|
||||||
|
|
||||||
<lineannotation><!-- arbitrary method replacement --></lineannotation>
|
<lineannotation><!-- arbitrary method replacement --></lineannotation>
|
||||||
<replaced-method name="computeValue" replacer="replacementComputeValue">
|
<replaced-method name="computeValue" replacer="replacementComputeValue">
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -352,4 +352,102 @@
|
||||||
|
|
||||||
<para>...</para>
|
<para>...</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>JMS Usage</title>
|
||||||
|
|
||||||
|
<para>One of the benefits of Spring's JMS support is to shield the user
|
||||||
|
from differences between the JMS 1.0.2 and 1.1 APIs. (For a description of
|
||||||
|
the differences between the two APIs see sidebar on Domain Unification).
|
||||||
|
Since it is now common to encounter only the JMS 1.1 API the use of
|
||||||
|
classes that are based on the JMS 1.0.2 API has been deprecated in Spring
|
||||||
|
3.0. This section describes Spring JMS support for the JMS 1.0.2
|
||||||
|
deprecated classes. </para>
|
||||||
|
|
||||||
|
<sidebar>
|
||||||
|
<title>Domain Unification</title>
|
||||||
|
|
||||||
|
<para>There are two major releases of the JMS specification, 1.0.2 and
|
||||||
|
1.1.</para>
|
||||||
|
|
||||||
|
<para>JMS 1.0.2 defined two types of messaging domains, point-to-point
|
||||||
|
(Queues) and publish/subscribe (Topics). The 1.0.2 API reflected these
|
||||||
|
two messaging domains by providing a parallel class hierarchy for each
|
||||||
|
domain. As a result, a client application became domain specific in its
|
||||||
|
use of the JMS API. JMS 1.1 introduced the concept of domain unification
|
||||||
|
that minimized both the functional differences and client API
|
||||||
|
differences between the two domains. As an example of a functional
|
||||||
|
difference that was removed, if you use a JMS 1.1 provider you can
|
||||||
|
transactionally consume a message from one domain and produce a message
|
||||||
|
on the other using the same
|
||||||
|
<interfacename>Session</interfacename>.</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>The JMS 1.1 specification was released in April 2002 and
|
||||||
|
incorporated as part of J2EE 1.4 in November 2003. As a result, common
|
||||||
|
J2EE 1.3 application servers which are still in widespread use (such
|
||||||
|
as BEA WebLogic 8.1 and IBM WebSphere 5.1) are based on JMS
|
||||||
|
1.0.2.</para>
|
||||||
|
</note>
|
||||||
|
</sidebar>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>JmsTemplate</title>
|
||||||
|
|
||||||
|
<para>Located in the package
|
||||||
|
<literal>org.springframework.jms.core</literal> the class
|
||||||
|
<classname>JmsTemplate102</classname> provides all of the features of
|
||||||
|
the <classname>JmsTemplate</classname> described the JMS chapter, but is
|
||||||
|
based on the JMS 1.0.2 API instead of the JMS 1.1 API. As a consequence,
|
||||||
|
if you are using JmsTemplate102 you need to set the boolean property
|
||||||
|
<property>pubSubDomain</property> to configure the
|
||||||
|
<classname>JmsTemplate</classname> with knowledge of what JMS domain is
|
||||||
|
being used. By default the value of this property is false, indicating
|
||||||
|
that the point-to-point domain, Queues, will be used.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Asynchronous Message Reception </title>
|
||||||
|
|
||||||
|
<para><link
|
||||||
|
linkend="jms-receiving-async-message-listener-adapter">MessageListenerAdapter's</link>
|
||||||
|
are used in conjunction with Spring's <link linkend="jms-mdp">message
|
||||||
|
listener containers</link> to support asynchronous message reception by
|
||||||
|
exposing almost any class as a Message-driven POJO. If you are using the
|
||||||
|
JMS 1.0.2 API, you will want to use the 1.0.2 specific classes such as
|
||||||
|
<classname>MessageListenerAdapter102</classname>,
|
||||||
|
<classname>SimpleMessageListenerContainer102</classname>, and
|
||||||
|
<classname>DefaultMessageListenerContainer102</classname>. These classes
|
||||||
|
provide the same functionality as the JMS 1.1 based counterparts but
|
||||||
|
rely only on the JMS 1.0.2 API. </para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Connections</title>
|
||||||
|
|
||||||
|
<para>The <classname>ConnectionFactory</classname> interface is part of
|
||||||
|
the JMS specification and serves as the entry point for working with
|
||||||
|
JMS. Spring provides an implementation of the
|
||||||
|
<classname>ConnectionFactory</classname> interface,
|
||||||
|
<classname>SingleConnectionFactory102</classname>, based on the JMS
|
||||||
|
1.0.2 API that will return the same <classname>Connection</classname> on
|
||||||
|
all <methodname>createConnection</methodname> calls and ignore calls to
|
||||||
|
<methodname>close</methodname>. You will need to set the boolean
|
||||||
|
property <property>pubSubDomain</property> to indicate which messaging
|
||||||
|
domain is used as <classname>SingleConnectionFactory102</classname> will
|
||||||
|
always explicitly differentiate between a
|
||||||
|
<classname>javax.jms.QueueConnection</classname> and a
|
||||||
|
<classname>javax.jmsTopicConnection</classname>.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Transaction Management</title>
|
||||||
|
|
||||||
|
<para>In a JMS 1.0.2 environment the class
|
||||||
|
<classname>JmsTransactionManager102</classname> provides support for
|
||||||
|
managing JMS transactions for a single Connection Factory. Please refer
|
||||||
|
to the reference documentation on <link linkend="jms-tx">JMS Transaction
|
||||||
|
Management</link> for more information on this functionality.</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</appendix>
|
</appendix>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,247 +1,148 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||||
|
|
||||||
<chapter id="metadata">
|
<chapter id="metadata">
|
||||||
<title>Annotations and Source Level Metadata Support</title>
|
<title>Annotations and Source Level Metadata Support</title>
|
||||||
<section id="metadata-introduction">
|
|
||||||
<title>Introduction</title>
|
|
||||||
<para>Source-level metadata is the addition of <emphasis>attributes</emphasis> or
|
|
||||||
<emphasis>annotations</emphasis> to program elements - usually, classes
|
|
||||||
and/or methods.</para>
|
|
||||||
<para>For example, we might add metadata to a class as follows:</para>
|
|
||||||
<programlisting language="java"><![CDATA[/**
|
|
||||||
* Normal comments here
|
|
||||||
* @@org.springframework.transaction.interceptor.DefaultTransactionAttribute()
|
|
||||||
*/
|
|
||||||
public class PetStoreImpl implements PetStoreFacade, OrderService {]]></programlisting>
|
|
||||||
<para>We could add metadata to a method as follows:</para>
|
|
||||||
<programlisting><![CDATA[/**
|
|
||||||
* Normal comments here
|
|
||||||
* @@org.springframework.transaction.interceptor.RuleBasedTransactionAttribute()
|
|
||||||
* @@org.springframework.transaction.interceptor.RollbackRuleAttribute(Exception.class)
|
|
||||||
* @@org.springframework.transaction.interceptor.NoRollbackRuleAttribute("ServletException")
|
|
||||||
*/
|
|
||||||
public void echoException(Exception ex) throws Exception {
|
|
||||||
....
|
|
||||||
}]]></programlisting>
|
|
||||||
<para>Both of these examples use Jakarta Commons Attributes syntax.</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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!).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are a number of solutions in this space, including:
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para><emphasis role="bold">Standard Java Annotations</emphasis>: 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.</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para><emphasis role="bold">XDoclet</emphasis>: well-established
|
|
||||||
solution, primarily intended for code generation.</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>Various <emphasis role="bold">open source attribute
|
|
||||||
implementations</emphasis>, for Java 1.4, of which Commons
|
|
||||||
Attributes is the most complete implementation. All these require
|
|
||||||
a special pre- or post-compilation step.</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section id="metadata-spring">
|
|
||||||
<title>Spring's metadata support</title>
|
|
||||||
<para>In keeping with its provision of abstractions over important
|
|
||||||
concepts, Spring provides a facade to metadata implementations, in the
|
|
||||||
form of the <interfacename>org.springframework.metadata.Attributes</interfacename>
|
|
||||||
interface. Such a facade adds value for several reasons:</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>Even though Java 5 provides metadata support at language level, there will
|
|
||||||
still be value in providing such an abstraction:
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>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.</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>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.</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>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 <emphasis>now</emphasis>; forcing the use of
|
|
||||||
Java 5 is not an option in such an important area.</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>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.</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
<para>The Spring <interfacename>Attributes</interfacename> interface looks like this:</para>
|
|
||||||
<programlisting language="java"><![CDATA[public interface Attributes {
|
|
||||||
|
|
||||||
Collection getAttributes(Class targetClass);
|
<section id="metadata-introduction">
|
||||||
|
<title>Introduction</title>
|
||||||
|
|
||||||
Collection getAttributes(Class targetClass, Class filter);
|
<para>Java 5 introduced source-level metadata called annotations to
|
||||||
|
program elements, usually, classes and/or methods</para>
|
||||||
|
|
||||||
Collection getAttributes(Method targetMethod);
|
<para>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.</para>
|
||||||
|
|
||||||
Collection getAttributes(Method targetMethod, Class filter);
|
<programlisting language="java">@Transactional
|
||||||
|
public class PetStoreImpl implements PetStoreFacade, OrderService {</programlisting>
|
||||||
|
|
||||||
Collection getAttributes(Field targetField);
|
<para>We could also add metadata to a method as follows:</para>
|
||||||
|
|
||||||
Collection getAttributes(Field targetField, Class filter);
|
<programlisting>public class PetStoreImpl implements PetStoreFacade, OrderService {
|
||||||
}]]></programlisting>
|
|
||||||
<para>
|
|
||||||
This is a lowest common denominator interface. JSR-175 offers more
|
|
||||||
capabilities than this, such as attributes on method arguments.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that this interface offers <classname>Object</classname>
|
|
||||||
attributes, like .NET. This distinguishes it from attribute systems such
|
|
||||||
as that of Nanning Aspects, which offer only <classname>String</classname>
|
|
||||||
attributes. There is a significant advantage in supporting
|
|
||||||
<classname>Object</classname> attributes, namely that it enables
|
|
||||||
attributes to participate in class hierarchies and allows such
|
|
||||||
attributes to react intelligently to their configuration parameters.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
With most attribute providers, attribute classes are configured
|
|
||||||
via constructor arguments or JavaBean properties. Commons Attributes
|
|
||||||
supports both.
|
|
||||||
</para>
|
|
||||||
<para>As with all Spring abstraction APIs, <interfacename>Attributes</interfacename>
|
|
||||||
is an interface. This makes it easy to mock attribute implementations for unit tests.</para>
|
|
||||||
</section>
|
|
||||||
<section id="metadata-annotations">
|
|
||||||
<title>Annotations</title>
|
|
||||||
<para>
|
|
||||||
The Spring Framework ships with a number of custom Java 5+ annotations.
|
|
||||||
</para>
|
|
||||||
<section id="metadata-annotations-required">
|
|
||||||
<title><interfacename>@Required</interfacename></title>
|
|
||||||
<para>The <interfacename>@Required</interfacename> annotation in the
|
|
||||||
<literal>org.springframework.beans.factory.annotation</literal>
|
|
||||||
package can be used to <emphasis>mark</emphasis> a property as
|
|
||||||
being <emphasis>'required-to-be-set'</emphasis> (i.e. an
|
|
||||||
annotated (setter) method of a class must be configured to be
|
|
||||||
dependency injected with a value), else an
|
|
||||||
<classname>Exception</classname> will be thrown by the container
|
|
||||||
at runtime.</para>
|
|
||||||
<para>The best way to illustrate the usage of this annotation is to
|
|
||||||
show an example:</para>
|
|
||||||
<programlisting language="java"><![CDATA[public class SimpleMovieLister {
|
|
||||||
|
|
||||||
]]><lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on the <interfacename>MovieFinder</interfacename></lineannotation><![CDATA[
|
. . .
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void insertOrder(Order order) {
|
||||||
|
this.orderDao.insertOrder(order);
|
||||||
|
this.itemDao.updateQuantity(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
. . .
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>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. </para>
|
||||||
|
|
||||||
|
<para>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.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="metadata-annotations">
|
||||||
|
<title>Annotations</title>
|
||||||
|
|
||||||
|
<para>The Spring Framework ships with a number of custom Java 5+
|
||||||
|
annotations.</para>
|
||||||
|
|
||||||
|
<section id="metadata-annotations-required">
|
||||||
|
<title><interfacename>@Required</interfacename></title>
|
||||||
|
|
||||||
|
<para>The <interfacename>@Required</interfacename> annotation in the
|
||||||
|
<literal>org.springframework.beans.factory.annotation</literal> package
|
||||||
|
can be used to <emphasis>mark</emphasis> a property as being
|
||||||
|
<emphasis>'required-to-be-set'</emphasis> (i.e. an annotated (setter)
|
||||||
|
method of a class must be configured to be dependency injected with a
|
||||||
|
value), else an <classname>Exception</classname> will be thrown by the
|
||||||
|
container at runtime.</para>
|
||||||
|
|
||||||
|
<para>The best way to illustrate the usage of this annotation is to show
|
||||||
|
an example:</para>
|
||||||
|
|
||||||
|
<programlisting language="java">public class SimpleMovieLister {
|
||||||
|
|
||||||
|
<lineannotation>// the <classname>SimpleMovieLister</classname> has a dependency on the <interfacename>MovieFinder</interfacename></lineannotation>
|
||||||
private MovieFinder movieFinder;
|
private MovieFinder movieFinder;
|
||||||
|
|
||||||
]]><lineannotation>// a setter method so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation><![CDATA[
|
<lineannotation>// a setter method so that the Spring container can 'inject' a <interfacename>MovieFinder</interfacename></lineannotation>
|
||||||
@Required
|
@Required
|
||||||
public void setMovieFinder(MovieFinder movieFinder) {
|
public void setMovieFinder(MovieFinder movieFinder) {
|
||||||
this.movieFinder = movieFinder;
|
this.movieFinder = movieFinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
]]><lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation><![CDATA[
|
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation>
|
||||||
}]]></programlisting>
|
}</programlisting>
|
||||||
<para>
|
|
||||||
Hopefully the above class definition reads easy on the eye.
|
<para>Hopefully the above class definition reads easy on the eye. Any
|
||||||
Any and all <interfacename>BeanDefinitions</interfacename> for the
|
and all <interfacename>BeanDefinitions</interfacename> for the
|
||||||
<classname>SimpleMovieLister</classname> class must be provided
|
<classname>SimpleMovieLister</classname> class must be provided with a
|
||||||
with a value.
|
value.</para>
|
||||||
</para>
|
|
||||||
<para>
|
<para>Let's look at an example of some XML configuration that will
|
||||||
Let's look at an example of some XML configuration that will
|
<emphasis role="bold">not</emphasis> pass validation.</para>
|
||||||
<emphasis role="bold">not</emphasis> pass validation.
|
|
||||||
</para>
|
<programlisting language="xml"><bean id="movieLister" class="x.y.SimpleMovieLister">
|
||||||
<programlisting language="xml"><![CDATA[<bean id="movieLister" class="x.y.SimpleMovieLister">
|
<lineannotation><!-- whoops, no MovieFinder is set (and this property is <interfacename>@Required</interfacename>) --></lineannotation>
|
||||||
]]><lineannotation><!-- whoops, no MovieFinder is set (and this property is <interfacename>@Required</interfacename>) --></lineannotation><![CDATA[
|
</bean></programlisting>
|
||||||
</bean>]]></programlisting>
|
|
||||||
<para>
|
<para>At runtime the following message will be generated by the Spring
|
||||||
At runtime the following message will be generated by the Spring container
|
container (the rest of the stack trace has been truncated).</para>
|
||||||
(the rest of the stack trace has been truncated).
|
|
||||||
</para>
|
<programlisting>Exception in thread "main" java.lang.IllegalArgumentException:
|
||||||
<programlisting><![CDATA[Exception in thread "main" java.lang.IllegalArgumentException:
|
Property 'movieFinder' is required for bean 'movieLister'.</programlisting>
|
||||||
Property 'movieFinder' is required for bean 'movieLister'.]]></programlisting>
|
|
||||||
<para>
|
<para>There is one last little (small, tiny) piece of Spring
|
||||||
There is one last little (small, tiny) piece of Spring configuration
|
configuration that is required to actually <emphasis>'switch
|
||||||
that is required to actually <emphasis>'switch on'</emphasis> this
|
on'</emphasis> this behavior. Simply annotating the
|
||||||
behavior. Simply annotating the <emphasis>'setter'</emphasis> properties
|
<emphasis>'setter'</emphasis> properties of your classes is not enough
|
||||||
of your classes is not enough to get this behavior. You need
|
to get this behavior. You need to enable a component that is aware of
|
||||||
to enable a component that is aware of the <interfacename>@Required</interfacename>
|
the <interfacename>@Required</interfacename> annotation and that can
|
||||||
annotation and that can process it appropriately.
|
process it appropriately.</para>
|
||||||
</para>
|
|
||||||
<para>
|
<para>This component is the
|
||||||
This component is the <classname>RequiredAnnotationBeanPostProcessor</classname> class.
|
<classname>RequiredAnnotationBeanPostProcessor</classname> class. This
|
||||||
This is a special <interfacename>BeanPostProcessor</interfacename>
|
is a special <interfacename>BeanPostProcessor</interfacename>
|
||||||
implementation that is <interfacename>@Required</interfacename>-aware
|
implementation that is <interfacename>@Required</interfacename>-aware
|
||||||
and actually provides the <emphasis>'blow up if this required property
|
and actually provides the <emphasis>'blow up if this required property
|
||||||
has not been set'</emphasis> logic. It is <emphasis>very</emphasis> easy
|
has not been set'</emphasis> logic. It is <emphasis>very</emphasis> easy
|
||||||
to configure; simply drop the following bean definition into your Spring
|
to configure; simply drop the following bean definition into your Spring
|
||||||
XML configuration.
|
XML configuration.</para>
|
||||||
</para>
|
|
||||||
<programlisting language="xml"><![CDATA[<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>]]></programlisting>
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/></programlisting>
|
||||||
<para>
|
|
||||||
Finally, one can configure an instance of the
|
<para>Finally, one can configure an instance of the
|
||||||
<classname>RequiredAnnotationBeanPostProcessor</classname> class to look
|
<classname>RequiredAnnotationBeanPostProcessor</classname> class to look
|
||||||
for <emphasis>another</emphasis> <interfacename>Annotation</interfacename> type.
|
for <emphasis>another</emphasis>
|
||||||
This is great if you already have your own
|
<interfacename>Annotation</interfacename> type. This is great if you
|
||||||
<interfacename>@Required</interfacename>-style annotation. Simply plug it into
|
already have your own <interfacename>@Required</interfacename>-style
|
||||||
the definition of a <classname>RequiredAnnotationBeanPostProcessor</classname> and
|
annotation. Simply plug it into the definition of a
|
||||||
you are good to go.
|
<classname>RequiredAnnotationBeanPostProcessor</classname> and you are
|
||||||
</para>
|
good to go.</para>
|
||||||
<para>
|
|
||||||
By way of an example, let's suppose you (or your organization / team) have
|
<para>By way of an example, let's suppose you (or your organization /
|
||||||
defined an attribute called @ <interfacename>Mandatory</interfacename>.
|
team) have defined an attribute called @
|
||||||
You can make a <classname>RequiredAnnotationBeanPostProcessor</classname>
|
<interfacename>Mandatory</interfacename>. You can make a
|
||||||
instance <interfacename>@Mandatory</interfacename>-aware like so:
|
<classname>RequiredAnnotationBeanPostProcessor</classname> instance
|
||||||
</para>
|
<interfacename>@Mandatory</interfacename>-aware like so:</para>
|
||||||
<programlisting language="xml"><![CDATA[<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
|
|
||||||
<property name="requiredAnnotationType" value="your.company.package.Mandatory"/>
|
<programlisting language="xml"><bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
|
||||||
</bean>]]></programlisting>
|
<property name="requiredAnnotationType" value="your.company.package.Mandatory"/>
|
||||||
<para>
|
</bean></programlisting>
|
||||||
Here is the source code for the <interfacename>@Mandatory</interfacename>
|
|
||||||
annotation. You will need to ensure that your custom annotation type
|
<para>Here is the source code for the
|
||||||
is itself annotated with appropriate annotations for its target
|
<interfacename>@Mandatory</interfacename> annotation. You will need to
|
||||||
and runtime retention policy.
|
ensure that your custom annotation type is itself annotated with
|
||||||
</para>
|
appropriate annotations for its target and runtime retention
|
||||||
<programlisting language="java"><![CDATA[package your.company.package;
|
policy.</para>
|
||||||
|
|
||||||
|
<programlisting language="java">package your.company.package;
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
|
@ -251,256 +152,38 @@ import java.lang.annotation.Target;
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
public @interface Mandatory {
|
public @interface Mandatory {
|
||||||
}]]></programlisting>
|
}</programlisting>
|
||||||
</section>
|
</section>
|
||||||
<section id="metadata-annotations-other">
|
|
||||||
<title>Other @Annotations in Spring</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para><xref linkend="transaction-declarative-annotations"/></para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para><xref linkend="aop-atconfigurable"/></para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para><xref linkend="aop-ataspectj"/></para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para><xref linkend="beans-annotation-config"/></para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para><xref linkend="beans-classpath-scanning"/></para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section id="metadata-commons">
|
|
||||||
<title>Integration with Jakarta Commons Attributes</title>
|
|
||||||
<para>
|
|
||||||
Presently Spring supports only Jakarta Commons Attributes out of the
|
|
||||||
box, although it is easy to provide implementations of the
|
|
||||||
<interfacename>org.springframework.metadata.Attributes</interfacename> interface for
|
|
||||||
other metadata providers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<emphasis role="bold">Commons Attributes 2.2</emphasis>
|
|
||||||
(<ulink url="http://jakarta.apache.org/commons/attributes/">http://jakarta.apache.org/commons/attributes/</ulink>)
|
|
||||||
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.)
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
We've already seen two examples of Commons Attributes attributes
|
|
||||||
definitions. In general, we will need to express:
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>The name of the attribute class</emphasis>. 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.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>Any necessary parameterization.</emphasis> This is done via
|
|
||||||
constructor arguments or JavaBean properties.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
<para>Bean properties look as follows:</para>
|
|
||||||
<programlisting><![CDATA[/**
|
|
||||||
* @@MyAttribute(myBooleanJavaBeanProperty=true)
|
|
||||||
*/]]></programlisting>
|
|
||||||
<para>
|
|
||||||
It's possible to combine constructor arguments and JavaBean
|
|
||||||
properties (as in Spring IoC).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Because, unlike Java 1.5 attributes, Commons Attributes is not
|
|
||||||
integrated with the Java language, it is necessary to run a special
|
|
||||||
<emphasis>attribute compilation</emphasis> step as part of the build
|
|
||||||
process.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To run Commons Attributes as part of the build process, you will
|
|
||||||
need to do the following:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
1. Copy the necessary library jars to
|
|
||||||
<literal>$ANT_HOME/lib</literal>. Four Jars are required, and all are
|
|
||||||
distributed with Spring:
|
|
||||||
</para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>the Commons Attributes compiler jar and API jar</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>xJavadoc.jar from XDoclet</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>commons-collections.jar from Jakarta Commons</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
<para>
|
|
||||||
2. Import the Commons Attributes ant tasks into your project build
|
|
||||||
script, as follows:
|
|
||||||
</para>
|
|
||||||
<programlisting language="xml"><![CDATA[<taskdef resource="org/apache/commons/attributes/anttasks.properties"/>]]></programlisting>
|
|
||||||
<para>
|
|
||||||
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 <literal>destdir</literal> attribute. Here we show the use of
|
|
||||||
a temporary directory for storing the generated files:
|
|
||||||
</para>
|
|
||||||
<programlisting language="xml"><![CDATA[<target name="compileAttributes">
|
|
||||||
|
|
||||||
<attribute-compiler destdir="${commons.attributes.tempdir}">
|
<section id="metadata-annotations-other">
|
||||||
<fileset dir="${src.dir}" includes="**/*.java"/>
|
<title>Other @Annotations in Spring</title>
|
||||||
</attribute-compiler>
|
|
||||||
|
|
||||||
</target>]]></programlisting>
|
<para>Annotations are also used in a number of other places throughout
|
||||||
<para>
|
Spring. Rather than being described here, these annotations are
|
||||||
The compile target that runs javac over the sources should depend on
|
described in that section or chapter of the reference documentation to
|
||||||
this attribute compilation task, and must also compile the generated
|
which they are most relevant.</para>
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<remark>
|
|
||||||
Commons Attributes also provides Maven support. Please refer to
|
|
||||||
Commons Attributes documentation for further information.
|
|
||||||
</remark>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
</para>
|
|
||||||
<programlisting language="xml"><![CDATA[<attribute-indexer jarFile="myCompiledSources.jar">
|
|
||||||
|
|
||||||
<classpath refid="master-classpath"/>
|
|
||||||
|
|
||||||
</attribute-indexer>]]></programlisting>
|
<itemizedlist>
|
||||||
<remark>
|
<listitem>
|
||||||
See the <literal>/attributes</literal> directory of the Spring JPetStore sample
|
<para><xref linkend="transaction-declarative-annotations" /></para>
|
||||||
application for an example of this build process. You can take the build
|
</listitem>
|
||||||
script it contains and modify it for your own projects.
|
|
||||||
</remark>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="metadata-uses">
|
|
||||||
<title>Metadata and Spring AOP autoproxying</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section id="metadata-fundamentals">
|
|
||||||
<title>Fundamentals</title>
|
|
||||||
<para>
|
|
||||||
This builds on the Spring AOP autoproxy functionality.
|
|
||||||
Configuration might look like this:
|
|
||||||
</para>
|
|
||||||
<programlisting language="xml"><![CDATA[<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
|
|
||||||
|
|
||||||
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
|
<listitem>
|
||||||
<property name="transactionInterceptor" ref="txInterceptor" />
|
<para><xref linkend="aop-atconfigurable" /></para>
|
||||||
</bean>
|
</listitem>
|
||||||
|
|
||||||
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
<listitem>
|
||||||
<property name="transactionManager" ref="transactionManager" />
|
<para><xref linkend="aop-ataspectj" /></para>
|
||||||
<property name="transactionAttributeSource">
|
</listitem>
|
||||||
<bean class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">
|
|
||||||
<property name="attributes" ref="attributes" />
|
|
||||||
</bean>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes" />]]></programlisting>
|
<listitem>
|
||||||
<para>
|
<para><xref linkend="beans-annotation-config" /></para>
|
||||||
The basic concepts here should be familiar from the discussion of
|
</listitem>
|
||||||
autoproxying in the AOP chapter.
|
|
||||||
</para>
|
<listitem>
|
||||||
<para>
|
<para><xref linkend="beans-classpath-scanning" /></para>
|
||||||
The most important bean definitions are the auto-proxy creator
|
</listitem>
|
||||||
and the advisor. Note that the actual bean names are not important;
|
</itemizedlist>
|
||||||
what matters is their class.
|
</section>
|
||||||
</para>
|
</section>
|
||||||
<para>
|
</chapter>
|
||||||
The bean definition of class
|
|
||||||
<classname>org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator</classname>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Thus we simply need an AOP advisor that will provide declarative
|
|
||||||
transaction management based on attributes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.)
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally, the <literal>attributes</literal> bean is the Commons
|
|
||||||
Attributes Attributes implementation. Replace it with another
|
|
||||||
implementation of the
|
|
||||||
<interfacename>org.springframework.metadata.Attributes</interfacename>
|
|
||||||
interface to source attributes from a different source.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="metadata-tx">
|
|
||||||
<title>Declarative transaction management</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>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.</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,7 @@
|
||||||
</part>
|
</part>
|
||||||
<!-- back matter -->
|
<!-- back matter -->
|
||||||
<xi:include href="classic-spring.xml"/>
|
<xi:include href="classic-spring.xml"/>
|
||||||
|
<xi:include href="classic-aop-spring.xml"/>
|
||||||
<xi:include href="xsd-configuration.xml"/>
|
<xi:include href="xsd-configuration.xml"/>
|
||||||
<xi:include href="xml-custom.xml"/>
|
<xi:include href="xml-custom.xml"/>
|
||||||
<xi:include href="dtd.xml"/>
|
<xi:include href="dtd.xml"/>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue