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
This commit is contained in:
parent
503f69b960
commit
278488d11e
|
|
@ -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
|
||||
|
||||
<para>Java 5 introduced source-level metadata called annotations to
|
||||
program elements, usually, classes and/or methods</para>
|
||||
|
||||
<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>
|
||||
|
||||
<programlisting language="java">@Transactional
|
||||
public class PetStoreImpl implements PetStoreFacade, OrderService {</programlisting>
|
||||
|
||||
<para>We could also add metadata to a method as follows:</para>
|
||||
|
||||
<programlisting>public class PetStoreImpl implements PetStoreFacade, OrderService {
|
||||
|
||||
. . .
|
||||
|
||||
@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 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>
|
||||
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-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);
|
||||
|
||||
Collection getAttributes(Class targetClass, Class filter);
|
||||
|
||||
Collection getAttributes(Method targetMethod);
|
||||
|
||||
Collection getAttributes(Method targetMethod, Class filter);
|
||||
|
||||
Collection getAttributes(Field targetField);
|
||||
|
||||
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>
|
||||
|
||||
<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[
|
||||
<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>
|
||||
<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"><![CDATA[<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>]]></programlisting>
|
||||
<para>
|
||||
Finally, one can configure an instance of the
|
||||
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"><![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;
|
||||
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>
|
||||
}</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>
|
||||
|
||||
<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>
|
||||
<para><xref linkend="transaction-declarative-annotations" /></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><xref linkend="aop-atconfigurable"/></para>
|
||||
<para><xref linkend="aop-atconfigurable" /></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><xref linkend="aop-ataspectj"/></para>
|
||||
<para><xref linkend="aop-ataspectj" /></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><xref linkend="beans-annotation-config"/></para>
|
||||
<para><xref linkend="beans-annotation-config" /></para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><xref linkend="beans-classpath-scanning"/></para>
|
||||
<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}">
|
||||
<fileset dir="${src.dir}" includes="**/*.java"/>
|
||||
</attribute-compiler>
|
||||
|
||||
</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"/>
|
||||
|
||||
</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"/>
|
||||
|
||||
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
|
||||
<property name="transactionInterceptor" ref="txInterceptor" />
|
||||
</bean>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
|
@ -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