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>
|