Home Unternehmen             Portfolio             Trainingsshop    Kunden & Partner Aktuelles    Kontakt
Home  Pfeil  ORDIX News  Pfeil  3/2009  Pfeil  Java/JEE
suche: 
Dieser Artikel richtet sich an Java-Entwickler und Architekten, die einen kompakten Überblick über die Neuerungen von Spring 3.0 erhalten möchten.

Weiterführende Links

Titelbild


Spring 3.0:

Der Frühling geht in die Verlängerung!


Mittlerweile ist bereits der dritte Meilenstein von Spring 3.0 erreicht worden. Das Team von SpringSource beschäftigt sich fleißig mit der Fertigstellung des ersten Release Candidate. Es ist somit an der Zeit, um einen Blick auf die Neuerungen von Spring 3.0 zu werfen.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
public class ServerConnectorTest {
    @Resource(name = "connector1")
    private Connector connector1;
    @Resource(name = "server1")
    private Server server1;
    @Resource(name = "connector2")
    private Connector connector2;
    @Resource(name = "server2")
    private Server server2;
    @Resource(name = "connectorMock")
    private ConnectorMock connectorMock;

    @Test
    public void testConnect() {
        // ohne EL
        System.out.println("Connector: " + connector1);
        System.out.println("Server: " + server1);
        server1.open();
        connector1.connect2server();

        // mit EL
        System.out.println("Connector: " + connector2);
        System.out.println("Server: " + server2);
        server2.open();
        connector2.connect2server();

        // Mock mit Default-Wert
        System.out.println("ConnectorMock: " +
            connectorMock);
        connectorMock.connect2server();
    }
}
Abb. 1: Die Testklasse erzeugt den ApplicationContext über Annotations und vereinfacht dadurch das Laden der Beans.
 
Connector:                        127.0.0.1:8001
Server:                           127.0.0.1:8001
Listener opened on:               127.0.0.1:8001
Connection to server established: 127.0.0.1:8001
Connector:                        127.0.0.1:8002
Server:                           127.0.0.1:8002
Listener geöffnet:                127.0.0.1:8002
Connection to server established: 127.0.0.1:8002
ConnectorMock:                    127.0.0.1:8002
Connection to server established: 127.0.0.1:8002
Abb. 2: Die Konsolenausgabe der Testklasse ServerConnectorTest.
 
<?xml version="1.0" encoding="UTF-8"?>
<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 />

    <!-- Server und Connector ohne SpEL -->
    <bean id="ip" class="java.lang.String">
        <constructor-arg value="127.0.0.1" />
    </bean>
    <bean id="port" class="java.lang.Integer">
        <constructor-arg value="8001" />
    </bean>
    <bean id="server1"
        class="de.ordix.on.spring.services.Server">
        <constructor-arg ref="ip" />
        <constructor-arg ref="port" />
    </bean>
    <bean id="connector1"
        class="de.ordix.on.spring.services.Connector">
        <constructor-arg ref="ip" />
        <constructor-arg ref="port" />
    </bean>

    <!-- Server und Connector mit SpEL -->
    <bean id="server2"
        class="de.ordix.on.spring.services.Server">
        <constructor-arg value="127.0.0.1" />
        <constructor-arg value="8002" />
        <property name="language"
            value="#{ systemProperties['user.language'] }" />
    </bean>
    <bean id="connector2"
        class="de.ordix.on.spring.services.Connector">
        <constructor-arg
            value="#{ server2.ip + ':' + server2.port }" />
    </bean>
    <bean id="connectorMock"
        class="de.ordix.on.spring.test.mock.ConnectorMock" />

</beans>

Abb. 3: Konfiguration von Spring mit und ohne SpEL.
 
 

Einleitung

Als Integrationsframework der Wahl trennt sich Spring in der dritten Generation von einigen Altlasten. Der Core wurde auf die Basis von Java 5 gebracht, wodurch die Typensicherheit durch die neue Spring-API genutzt werden kann. Java 1.4 bleibt damit außen vor. Erweiteter Support für Annotations und die neue Spring Expression Language (SpEL) zeigen ebenfalls ihre Stärken. Für das Web-Umfeld stehen REST, Portlet 2.0 und die Konversationsverwaltung im Mittelpunkt. Der Aufbau der Spring-Bibliotheken hat sich ebenfalls verändert.

Annotations sind "in"

Die Konfiguration von Spring über Annotations wurde mit Spring 2.5 eingeführt. Dadurch kann man Spring-Beans mittels Java-Annotations definieren und konfigurieren. In der Praxis hat sich die Verwendung von Annotations generell durchgesetzt und daher hat sich bei Spring auch hier einiges getan.

Gerade bei der Verwendung von JUnit oder anderen Test-Frameworks gibt es ein großes Einsparpotenzial, wenn es um die Testvorbereitung geht: Die Ausgangssituation muss schnell geschaffen sein. Meist kommen im Test nur wenige Spring-Beans zum Einsatz.

Gültige Objekte werden mit Hilfe von Spring generell über den Application Context erzeugt. Zur Vereinfachung bieten sich in Testklassen aber vor allem folgende Annotations an:
@RunWith, @ContextConfiguration und @Autowired bzw. @Resource.

Die Abbildung 1 zeigt eine kleine Testklasse, die genau diese Annotations verwendet. Mit @RunWith wird zunächst die generelle Spring-Unterstützung aktiviert. Durch @ContextConfiguration wird die zu verwendende Spring-Konfiguration bestimmt. Instanzvariablen können dann über den Namen (@Resource) oder über den Datentyp (@Autowired) gefüllt werden. Die Ausgabe auf der Konsole können Sie der Abbildung 2 entnehmen.

Mit der SpEL wurde auch die Annotation @Value eingeführt. Hierauf werfen wir im nächsten Abschnitt einen detaillierten Blick.

Neue Ausdrucksweise für Spring

Die ersten Anregungen für die Unterstützung der Expression Language liegen schon lange zurück (05.12.2003). Im Wesentlichen geht es darum, dass Ausdrücke zur Laufzeit ausgewertet werden, was die Flexibilität der Anwendung erhöht. Dies kennt man bisher bereits von JSP oder JSF.

XML-basierte Konfiguration
Bisher war es beispielsweise ein Problem, bestimmte Werte in der Spring-Konfiguration mehreren Beans zuzuweisen. Eine Möglichkeit war die Erstellung einer String-Bean und deren Injektion in andere Beans, wie es Abbildung 3 zeigt. Diese Vorgehensweise ist zwar funktional, aber nicht unbedingt elegant. Hinzu kommt, dass ein Verknüpfen von Werten ebenfalls nicht möglich ist.

Die SpEL hingegen erlaubt einen Zugriff auf die Werte von anderen Spring-Beans. Dazu wird dem Ausdruck ein # vorangestellt und der Wert in geschweiften Klammern angegeben (#{bean-id.property}). In Abbildung 3 ist dies im Zusammenhang mit einer Verknüpfung von zwei dynamischen Werten und einer festen Zeichenkette zu sehen. Die Bean mit der ID connector2 bekommt also die folgende Zeichenkette injiziert:
127.0.0.2:8002

Vorbelegt ist von Spring bereits die Variable systemProperties. Damit können die entsprechenden Werte einfach über die Angabe des Namens in eckigen Klammern abgefragt werden. Abbildung 3 zeigt die Abfrage der Systemsprache bei der Spring-Bean server2. Eigene Werte können beim Start der JVM über die Option -D an das Programm übergeben werden.

Annotation-basierte Konfiguration

Weitaus interessanter wird die Verwendung der SpEL in Annotations. Diese haben nämlich grundsätzlich den Nachteil, dass eine Änderung immer ein Rekompillieren erfordert. Spring 3.0 führt für die Nutzung der SpEL die @Value-Annotation ein. Hierdurch können Properties von Spring-Beans beispielsweise mit Default-Werten belegt werden. Werden die Properties also nicht explizit über die Spring-Konfiguration gesetzt, so werden die Standardwerte der @Value-Annotation verwendet.

Das Beispiel zeigt dies bei der Konfiguration der ConnectorMock-Bean. Es wird hier keine Property innerhalb der Spring-#XML-Datei gesetzt, sondern die connectionUrl bekommt die Bean über die @Value-Annotation. Achten Sie darauf, dass der gesetzte Wert im Default-Konstruktor durch Spring überschrieben wird.

Neu strukturiert ans Werk

Bisher gab es von Spring eine zentrale Bibliothek, die spring.jar. Diese enthielt bisher alle Klassen des Spring-Frameworks und wurde nun aufgesplittet. Entsprechend der Paketstruktur bietet sich einem nun der folgende Aufbau:

Wenn bisher auch die Bibliotheken von Fremdanbietern mitgeliefert wurden, setzt Spring ab jetzt auf Technologien wie Maven oder OSGi, um Abhängigkeiten automatisch aufzulösen.

Fazit

Die elementaren Neuigkeiten fallen für den Außenstehenden in die Bereiche Expression Language, Erweiterung der Annotations und der neue Aufbau der JAR-Struktur. Unter der Haube wurde die Java-Version auf Java 5 angehoben und einige Funktionen wurden auf "Deprecate" gesetzt. Ein Wechsel auf die aktuelle Version sollte aber in den meisten Fällen recht leicht sein. Das SpEL-Beispiel können Sie übrigens unter folgender Adresse herunterladen [1].

Thomas Rohde (info@ordix.de).