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
|
||||
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>
|
||||
<replaced-method name="computeValue" replacer="replacementComputeValue">
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -352,4 +352,102 @@
|
|||
|
||||
<para>...</para>
|
||||
</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>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,247 +1,148 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!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">
|
||||
<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 {
|
||||
<title>Annotations and Source Level Metadata Support</title>
|
||||
|
||||
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>
|
||||
<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 {
|
||||
<programlisting>public class PetStoreImpl implements PetStoreFacade, OrderService {
|
||||
|
||||
]]><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;
|
||||
|
||||
]]><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
|
||||
public void setMovieFinder(MovieFinder movieFinder) {
|
||||
this.movieFinder = movieFinder;
|
||||
}
|
||||
|
||||
]]><lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation><![CDATA[
|
||||
}]]></programlisting>
|
||||
<para>
|
||||
Hopefully the above class definition reads easy on the eye.
|
||||
Any and all <interfacename>BeanDefinitions</interfacename> for the
|
||||
<classname>SimpleMovieLister</classname> class must be provided
|
||||
with a value.
|
||||
</para>
|
||||
<para>
|
||||
Let's look at an example of some XML configuration that will
|
||||
<emphasis role="bold">not</emphasis> pass validation.
|
||||
</para>
|
||||
<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><![CDATA[
|
||||
</bean>]]></programlisting>
|
||||
<para>
|
||||
At runtime the following message will be generated by the Spring container
|
||||
(the rest of the stack trace has been truncated).
|
||||
</para>
|
||||
<programlisting><![CDATA[Exception in thread "main" java.lang.IllegalArgumentException:
|
||||
Property 'movieFinder' is required for bean 'movieLister'.]]></programlisting>
|
||||
<para>
|
||||
There is one last little (small, tiny) piece of Spring configuration
|
||||
that is required to actually <emphasis>'switch on'</emphasis> this
|
||||
behavior. Simply annotating the <emphasis>'setter'</emphasis> properties
|
||||
of your classes is not enough to get this behavior. You need
|
||||
to enable a component that is aware of the <interfacename>@Required</interfacename>
|
||||
annotation and that can process it appropriately.
|
||||
</para>
|
||||
<para>
|
||||
This component is the <classname>RequiredAnnotationBeanPostProcessor</classname> class.
|
||||
This is a special <interfacename>BeanPostProcessor</interfacename>
|
||||
implementation that is <interfacename>@Required</interfacename>-aware
|
||||
and actually provides the <emphasis>'blow up if this required property
|
||||
has not been set'</emphasis> logic. It is <emphasis>very</emphasis> easy
|
||||
to configure; simply drop the following bean definition into your Spring
|
||||
XML configuration.
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>]]></programlisting>
|
||||
<para>
|
||||
Finally, one can configure an instance of the
|
||||
<classname>RequiredAnnotationBeanPostProcessor</classname> class to look
|
||||
for <emphasis>another</emphasis> <interfacename>Annotation</interfacename> type.
|
||||
This is great if you already have your own
|
||||
<interfacename>@Required</interfacename>-style annotation. Simply plug it into
|
||||
the definition of a <classname>RequiredAnnotationBeanPostProcessor</classname> and
|
||||
you are good to go.
|
||||
</para>
|
||||
<para>
|
||||
By way of an example, let's suppose you (or your organization / team) have
|
||||
defined an attribute called @ <interfacename>Mandatory</interfacename>.
|
||||
You can make a <classname>RequiredAnnotationBeanPostProcessor</classname>
|
||||
instance <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"/>
|
||||
</bean>]]></programlisting>
|
||||
<para>
|
||||
Here is the source code for the <interfacename>@Mandatory</interfacename>
|
||||
annotation. You will need to ensure that your custom annotation type
|
||||
is itself annotated with appropriate annotations for its target
|
||||
and runtime retention policy.
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[package your.company.package;
|
||||
<lineannotation>// business logic that actually 'uses' the injected <interfacename>MovieFinder</interfacename> is omitted...</lineannotation>
|
||||
}</programlisting>
|
||||
|
||||
<para>Hopefully the above class definition reads easy on the eye. Any
|
||||
and all <interfacename>BeanDefinitions</interfacename> for the
|
||||
<classname>SimpleMovieLister</classname> class must be provided with a
|
||||
value.</para>
|
||||
|
||||
<para>Let's look at an example of some XML configuration that will
|
||||
<emphasis role="bold">not</emphasis> pass validation.</para>
|
||||
|
||||
<programlisting language="xml"><bean id="movieLister" class="x.y.SimpleMovieLister">
|
||||
<lineannotation><!-- whoops, no MovieFinder is set (and this property is <interfacename>@Required</interfacename>) --></lineannotation>
|
||||
</bean></programlisting>
|
||||
|
||||
<para>At runtime the following message will be generated by the Spring
|
||||
container (the rest of the stack trace has been truncated).</para>
|
||||
|
||||
<programlisting>Exception in thread "main" java.lang.IllegalArgumentException:
|
||||
Property 'movieFinder' is required for bean 'movieLister'.</programlisting>
|
||||
|
||||
<para>There is one last little (small, tiny) piece of Spring
|
||||
configuration that is required to actually <emphasis>'switch
|
||||
on'</emphasis> this behavior. Simply annotating the
|
||||
<emphasis>'setter'</emphasis> properties of your classes is not enough
|
||||
to get this behavior. You need to enable a component that is aware of
|
||||
the <interfacename>@Required</interfacename> annotation and that can
|
||||
process it appropriately.</para>
|
||||
|
||||
<para>This component is the
|
||||
<classname>RequiredAnnotationBeanPostProcessor</classname> class. This
|
||||
is a special <interfacename>BeanPostProcessor</interfacename>
|
||||
implementation that is <interfacename>@Required</interfacename>-aware
|
||||
and actually provides the <emphasis>'blow up if this required property
|
||||
has not been set'</emphasis> logic. It is <emphasis>very</emphasis> easy
|
||||
to configure; simply drop the following bean definition into your Spring
|
||||
XML configuration.</para>
|
||||
|
||||
<programlisting language="xml"><bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/></programlisting>
|
||||
|
||||
<para>Finally, one can configure an instance of the
|
||||
<classname>RequiredAnnotationBeanPostProcessor</classname> class to look
|
||||
for <emphasis>another</emphasis>
|
||||
<interfacename>Annotation</interfacename> type. This is great if you
|
||||
already have your own <interfacename>@Required</interfacename>-style
|
||||
annotation. Simply plug it into the definition of a
|
||||
<classname>RequiredAnnotationBeanPostProcessor</classname> and you are
|
||||
good to go.</para>
|
||||
|
||||
<para>By way of an example, let's suppose you (or your organization /
|
||||
team) have defined an attribute called @
|
||||
<interfacename>Mandatory</interfacename>. You can make a
|
||||
<classname>RequiredAnnotationBeanPostProcessor</classname> instance
|
||||
<interfacename>@Mandatory</interfacename>-aware like so:</para>
|
||||
|
||||
<programlisting language="xml"><bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
|
||||
<property name="requiredAnnotationType" value="your.company.package.Mandatory"/>
|
||||
</bean></programlisting>
|
||||
|
||||
<para>Here is the source code for the
|
||||
<interfacename>@Mandatory</interfacename> annotation. You will need to
|
||||
ensure that your custom annotation type is itself annotated with
|
||||
appropriate annotations for its target and runtime retention
|
||||
policy.</para>
|
||||
|
||||
<programlisting language="java">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 {
|
||||
}]]></programlisting>
|
||||
</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">
|
||||
}</programlisting>
|
||||
</section>
|
||||
|
||||
<attribute-compiler destdir="${commons.attributes.tempdir}">
|
||||
<fileset dir="${src.dir}" includes="**/*.java"/>
|
||||
</attribute-compiler>
|
||||
<section id="metadata-annotations-other">
|
||||
<title>Other @Annotations in Spring</title>
|
||||
|
||||
</target>]]></programlisting>
|
||||
<para>
|
||||
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.
|
||||
</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"/>
|
||||
<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>
|
||||
|
||||
</attribute-indexer>]]></programlisting>
|
||||
<remark>
|
||||
See the <literal>/attributes</literal> 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.
|
||||
</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"/>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><xref linkend="transaction-declarative-annotations" /></para>
|
||||
</listitem>
|
||||
|
||||
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
|
||||
<property name="transactionInterceptor" ref="txInterceptor" />
|
||||
</bean>
|
||||
<listitem>
|
||||
<para><xref linkend="aop-atconfigurable" /></para>
|
||||
</listitem>
|
||||
|
||||
<bean id="txInterceptor" 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>
|
||||
<listitem>
|
||||
<para><xref linkend="aop-ataspectj" /></para>
|
||||
</listitem>
|
||||
|
||||
<bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes" />]]></programlisting>
|
||||
<para>
|
||||
The basic concepts here should be familiar from the discussion of
|
||||
autoproxying in the AOP chapter.
|
||||
</para>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
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>
|
||||
<listitem>
|
||||
<para><xref linkend="beans-annotation-config" /></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><xref linkend="beans-classpath-scanning" /></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@
|
|||
</part>
|
||||
<!-- back matter -->
|
||||
<xi:include href="classic-spring.xml"/>
|
||||
<xi:include href="classic-aop-spring.xml"/>
|
||||
<xi:include href="xsd-configuration.xml"/>
|
||||
<xi:include href="xml-custom.xml"/>
|
||||
<xi:include href="dtd.xml"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue