java-forum.org - Java programmieren aus Leidenschaft
Java 6 Einstieg und professioneller Einsatz
Alter Preis: 34,90 EUR
Jetzt: 0,00 EUR

zzgl. Versandkosten

Zurück   java-forum.org - Java programmieren aus Leidenschaft > Blogs > Java Snippets

Eine Sammlung von nützlichen Code-Schnipseln
Bewertung: 5 Stimmen mit einer durchschnittlichen Bewertung von 4,80.

How-To: Dependency Injection mit Spring

"How-To: Dependency Injection mit Spring" bei Mister Wong speichern "How-To: Dependency Injection mit Spring" bei YiGG.de speichern "How-To: Dependency Injection mit Spring" bei Google speichern "How-To: Dependency Injection mit Spring" bei del.icio.us speichern
Veröffentlicht: 24.03.2009 um 07:00 von tfa
Aktualisiert: 04.04.2012 um 06:05 von tfa

Einleitung

Dependency Injection (DI) dient zur Konfiguration von Software-Komponenten (Erzeugung und Initialisierung von Objekten), wobei deren Abhängigkeit untereinander so gering wie möglich gehalten werden soll. Das Prinzip hinter DI heißt Inversion of Control (IoC). Hiernach werden abhängige Objekte nicht von der Komponente selbst erzeugt oder beschafft, sondern diese werden von Außen in sie injiziert. Die Injektion wird von einem DI-Framework - etwa SpringFramework - durchgeführt.

Im folgenden Beispiel benötigen mehrere Komponenten jeweils eine Referenz auf ein Config-Objekt, das für die Anwendung wichtige Präferenzen speichern soll. Das Config-Objekt wird durch DI in die abhängigen Komponenten (ReadController, WriteController) injiziert.
Das Config-Objekt enthält einfach eine Map der Präferenzen nach dem Schema Schlüssel->Wert. Die von Spring verwalteten Objekte (also im Beispiel Config, ReadController, WriteController) werden als Beans bezeichnet.

Das zu injizierende Bean

Zunächst wird eine Schnittstelle für das Config-Objekt definiert. Dies ist zwar nicht unbedingt notwendig für DI. Aber meistens ist es besser und zukunftsicherer gegen Schnittstellen statt gegen konkrete Klassen zu programmieren, wenn man die Implementierung später austauschen möchte, was durch DI ja erleichtert werden soll.

Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package depinjdemo;
 
/*
 * Schnittstelle für Konfiguration-Objekt.
 * 
 * In der Anwendung soll ein und dasselbe Config-Objekt an vielen 
 * verschiedenen Stellen (d.h. Klassen) verwendet werden.
 */
public interface Config {
 
    public String getValue(String key);
 
    public void setValue(String key, String value);
 
}
//--------------------------------------------------------------
package depinjdemo;
 
import java.util.HashMap;
import java.util.Map;
 
/*
 * Standard-Implementierung der Config-Schnittstelle.
 */
public class ConfigImpl implements Config {
 
    private Map<String, String> prefs = new HashMap<String, String>();
 
    public String getValue(String key) {
        return this.prefs.get(key);
    }
 
    public void setValue(String key, String value) {
        this.prefs.put(key, value);
    }
}

Die zu konfigurierenden Beans

Das Config-Objekt bzw. die Implementierung ConfigImpl wird von den Klassen ReadController und WriteController benötigt. Die Klassen definieren hierzu je eine Member-Variable vom Typ Config. Getter oder Setter sind nicht notwendig. Die Variable wird mit der Annotation @Autowired markiert. Hierdurch wird Spring angewiesen, die Variable automatisch zu "verkabeln". Spring sucht eine Bean in seinem Kontext (s.u.), die dem Typ der zu injizierenden Variable (Config) entspricht. Dieses Bean wird der Member-Variablen zugewiesen.
Gibt es im Kontext mehr eine Bean des passenden Typs, muss zusätzlich die ID des gewünschten Objekts angegeben werden. Dies geschieht mit der Annotation @Qualifier("idDerBean").

Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package depinjdemo;
 
import org.springframework.beans.factory.annotation.Autowired;
 
// Beispielklasse, die Config-Objekt verwenden soll.
public class ReadController {
 
    // Config-Objekt wird von Spring injiziert.
    @Autowired
    private Config conf;
 
    public ReadController() {}
 
    public void printConfig() {
        System.out.println("Konfiguration: Test=" + this.conf.getValue("Test"));
    }
}
//------------------------------------------
package depinjdemo;
 
import org.springframework.beans.factory.annotation.Autowired;
 
// Beispielklasse, die Config-Objekt verwenden soll.
public class WriteController {
 
    // Config-Objekt wird von Spring injiziert.
    @Autowired
    private Config conf;
 
    public WriteController() {}    
 
    public void doConfig() {
        this.conf.setValue("Test", "42");
    }
}

Konfigurationsdatei für Spring

Schließlich muss Spring selbst konfiguriert werden. In einer XML-Datei werden die Namen (IDs) und Klassen der Beans angegeben.

xml Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.xsd
                        http: //www.springframework.org/schema/context http: //www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- Beans über Annotationen konfigurieren -->        
    <context:annotation-config />
    
    <bean id="configBean" class="depinjdemo.ConfigImpl" />
    <bean id="reader"     class="depinjdemo.ReadController" />
    <bean id="writer"     class="depinjdemo.WriteController" />
</beans>

Das Hauptprogramm

Jetzt kann Spring gestartet und die konfigurierten Beans können benutzt werden:

Java Code: Quelltext in neuem Fenster öffnen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package depinjdemo;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/*
 * Hauptprogramm für Spring-DI-Demo
 */
public class Main {
 
    public static void main(String... args) {
        // Spring initialisieren und Kontext laden.
        // applicationContext.xml ist die oben angegebene Konfigurationsdatei.
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
 
        // Über das Context-Objekt können die konfigurierten Beans über ihre Namen abgerufen werden.
        WriteController wc = (WriteController) ctx.getBean("writer");
        ReadController rc = (ReadController) ctx.getBean("reader");
 
        wc.doConfig();
        rc.printConfig();
    }
}

Singleton?

Standardmäßig werden Beans von Spring im Singleton-Scope erzeugt:
xml Code: Quelltext in neuem Fenster öffnen
1
<bean id="configBean" class="depinjdemo.ConfigImpl" scope="singleton"/>
Dies darf aber nicht mit dem Singleton-Entwurfsmuster, wonach nur ein einziges Objekt dieser Klasse möglich ist, verwechselt werden. Spring legt in dieser Einstellung nur ein Objekt pro Kontext und pro Bean-ID an. Mehrere Aufrufe bzw. Referenzierungen des Beans liefern immer das selbe Objekt zurück. Es ist aber durchaus möglich, andere Beans dieses Typs mit unterschiedlichen IDs anzulegen.

Das Gegenteil des Singleton-Scopes ist der Prototyp. Prototype-Beans werden bei jedem Aufruf und jeder Referenzierung von Spring neu angelegt. Ändert man den Scope des Config-Beans im obigen Beispiel auf Prototype, so erhalten WriterController und ReaderController jeweils ein eigenes ConfigImpl-Objekt.
xml Code: Quelltext in neuem Fenster öffnen
1
<bean id="configBean" class="depinjdemo.ConfigImpl" scope="prototype"/>

Ressourcen
Kategorie: Spring
Hits 10015 Kommentare 0
« Zurück     Startseite des Blogs     Nächste »
Kommentare 0

Kommentare

 

Alle Zeitangaben in WEZ +1. Es ist jetzt 02:44 Uhr.


Powered by vBulletin® Version 3.8.6 (Deutsch)
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.2
Thanks for Smilies by smilies.4-user.de