Java ist auch eine Insel

Freitag, Mai 09, 2008

Annotationen in Spring 2.0/2.5 für Autowire und neue Beans

Bis Spring 2.0 gab es im Wesentlichen nur eine Möglichkeit, Spring-Beans zu deklarieren und Bean-Referenzen zu injizieren. Ab Spring 2.0 und besonders in Spring 2.5 gibt es einen Richtungswechsel. Statt Bean-Definitionen und Injizierungsanweisungen ausschließlich über XML-Dokumente zu beschreiben, kommen Annotationen hinzu. Spring nutzt zum Einen Standard-Annotationen aus Java 6 (Common Annoations) aber auch eigene.

Nehmen wir zwei Beans an:

    <bean id="today" class="java.util.Date" />
    <bean id="calendarPrinter"
      class="com.tutego.spring.annotation.CalendarPrinter" />

Die Bean CalendarPrinter soll ein Datum injiziert bekommen.

    public class CalendarPrinter {
      public void setDate( Date date ) …

Über XML lässt sich das einfach beschreiben, doch seit Spring 2.5 veranlasst eine Annotation Spring dazu, die Verweise automatisch zu injizieren:
@Autowired

@Autowired ist eine Annotation für Methoden und Attribute, damit Spring selbständig den Verweis setzt:

    public class CalendarPrinter {
      @Autowired
      public void setDate(@Qualifier("today") Date d) …
    }

Die Annotation @Qualifier ist nur dann nötig, wenn es mehrere Beans dieses Typs gibt. (Nicht bei uns.)

Damit Spring überhaupt die Verknüpfung vornimmt, ist in der XML-Datei ein Hinweis zu setzen.

Die erste Möglichkeit ist:

    <bean
     class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

Eine im Allgemeinen bessere Alternative (die AutowiredAnnotationBeanPostProcessor und CommonAnnotationBeanPostProcessor zusammenfasst) ist

    <context:annotation-config/>

Die Annotation @Autowired ist genauso gültig bei Attributen:

    public class CalendarPrinter
    {
      @Autowired Date date;

      public void doIt()
      {
        System.out.println( date );
      }
    }

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean id="today" class="java.util.Date" />
<bean id="calendarPrinter" class="com.tutego.spring.annotation.CalendarPrinter" />
</beans>

Java 6 (für Java 5 ist ein Extra-Jar nötig) führt aus JSR-250 die Lebenszyklus-Annotationen @PostConstruct und @PreDestroy sowie @Resource ein.

    public class CalendarPrinter {
      @PostConstruct public void initialize() {
        System.out.println( "init" );
      }
      /* @PreDestroy public void remove() {
        System.out.println( "destroy" );
      } */
    }

Beans deklarieren

Die Verknüpfung ist durch Autowire automatisiert und minimiert die XML-Konfigurationsdatei.
Zum Deklarieren von neuen Beans bringt Spring ebenfalls Annotationen mit.
Statt in der XML-Datei zu schreiben

    <bean id="calendarPrinter"
    class="com.tutego.spring.annotation.CalendarPrinter" />
    können wir annotieren:
    @Component class CalendarPrinter

Damit Spring nach annotierten Beans sucht, ist nötig:

    <context:component-scan
    base-package="com.tutego.spring" />

Die Annotation @Component ist an allen Typen erlaubt und natürlich zur Laufzeit sichtbar:

    @Target(value=TYPE)
    @Retention(value=RUNTIME)
    @Documented
    public @interface Component
    {
      String value();
    }

API zur Eigenschaft: „The value may indicate a suggestion for a logical component name, to be turned into a Spring bean in case of an autodetected component.“

Geben wir dem CalendarPrinter den Bean-Namen „ cal-printer“:

    @Component("cal-printer")
    public class CalendarPrinter

Aus dem ApplicationContext genommen folgt:

    ApplicationContext context =
      new ClassPathXmlApplicationContext( … );
    Object bean = context.getBean( "cal-printer" );
    System.out.println( bean.getClass() );
    // class com.tutego.spring.annotation.CalendarPrinter

@Component ist eine sehr allgemeine Annotation.

Besser ist es, semantische Annotationen zu nutzen, die @Component erweitern. Spring liefert drei mit:

1.        @Target(value=TYPE) … @Component
        public @interface Repository

2.        @Target(value=TYPE) … @Component
        public @interface Service

3.        @Target(value=TYPE) … @Component
        public @interface Controller

Labels:

AddThis Social Bookmark Button