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
190 lines
8.1 KiB
XML
190 lines
8.1 KiB
XML
<?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">
|
|
<chapter id="metadata">
|
|
<title>Annotations and Source Level Metadata Support</title>
|
|
|
|
<section id="metadata-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<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. 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>
|
|
@Required
|
|
public void setMovieFinder(MovieFinder movieFinder) {
|
|
this.movieFinder = movieFinder;
|
|
}
|
|
|
|
<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;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
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>
|
|
</chapter>
|