Dependency Injection in Spring Boot verstehen — vom Anfänger zum Profi
Was ist Dependency Injection?
Dependency Injection (DI) ist das Herzstück von Spring Boot. Statt dass eine Klasse
ihre Abhängigkeiten selbst erzeugt (new Service()), erhält sie diese von außen —
vom Spring Container. Das nennt man Inversion of Control (IoC): Die Kontrolle
über die Objekterstellung wird umgekehrt.
// Ohne DI — eng gekoppelt
class OrderService {
private final PaymentGateway gateway = new StripeGateway(); // fest verdrahtet
}
// Mit DI — lose gekoppelt
class OrderService {
private final PaymentGateway gateway;
OrderService(PaymentGateway gateway) { // Spring injiziert die Implementierung
this.gateway = gateway;
}
}
Der Vorteil? Sie können StripeGateway durch PayPalGateway ersetzen, ohne
OrderService zu ändern. Tests werden trivial: übergeben Sie einen Mock.
Die drei Arten der Injection
Spring Boot bietet drei Wege, Abhängigkeiten zu injizieren:
1. Constructor Injection (empfohlen)
@Service
public class OrderService {
private final OrderRepository repo;
private final PaymentGateway gateway;
// Spring findet die Beans automatisch über den Konstruktor
OrderService(OrderRepository repo, PaymentGateway gateway) {
this.repo = repo;
this.gateway = gateway;
}
}
Warum empfohlen? Felder sind final (immutable), Abhängigkeiten sichtbar in
der Signatur, leicht testbar (new OrderService(mockRepo, mockGateway)), fail-fast
beim Start (Spring prüft beim Hochfahren, ob alle Beans vorhanden sind).
2. Setter Injection
@Service
public class OrderService {
private OrderRepository repo;
@Autowired
public void setRepo(OrderRepository repo) {
this.repo = repo;
}
}
Nützlich für optionale Abhängigkeiten, aber das Feld kann nicht final sein —
Gefahr von NullPointerException wenn die Abhängigkeit fehlt.
3. Feld-Injection (veraltet)
@Service
public class OrderService {
@Autowired
private OrderRepository repo; // nicht final, nicht sichtbar, schwer testbar
}
Spring's Dokumentation rät davon ab. Es funktioniert, aber Sie verlieren alle Vorteile von Constructor Injection.
Constructor Injection ist der Goldstandard
Spring Boot empfiehlt Constructor Injection seit Version 4.x. Wenn eine Klasse
nur einen Konstruktor hat, ist @Autowired nicht nötig — Spring injiziert
automatisch. Nutzen Sie final-Felder für Thread-Safety und Klarheit.
Bean Scopes
Nicht jede Bean ist ein Singleton. Spring bietet mehrere Scopes:
| Scope | Lebensdauer | Verwendung |
|---|---|---|
| singleton (Standard) | Eine Instanz pro ApplicationContext | Statuslose Services, Repositories |
| prototype | Neue Instanz bei jeder Anforderung | Stateful Objekte, DTOs |
| request | Eine Instanz pro HTTP-Request | Request-spezifische Daten |
| session | Eine Instanz pro HTTP-Session | User-spezifische Daten |
@Service
@Scope("prototype")
public class ShoppingCart { /* neue Instanz bei jedem Gebrauch */ }
@Qualifier und @Primary bei Mehrdeutigkeiten
Wenn mehrere Beans denselben Typ implementieren, weiß Spring nicht, welche zu injizieren. Zwei Lösungen:
// Lösung 1: @Primary — bevorzugte Bean
@Primary
@Service
public class StripeGateway implements PaymentGateway { /* ... */ }
// Lösung 2: @Qualifier — explizite Auswahl
@Service
public class OrderService {
OrderService(@Qualifier("paypalGateway") PaymentGateway gateway) { /* ... */ }
}
Spring Boot Course: Vertiefung
Dieser Artikel deckt die Grundlagen von Modul 2 unseres Spring Boot-Kurses ab. Im Kurs lernen Sie jedes Konzept interaktiv mit dem Java Playground:
→ Spring Core & DI — Modul 2 → REST APIs — Modul 3 → Testing — Modul 7
✅ Wichtige Erkenntnisse
Haken setzen, um deinen Lernfortschritt zu markieren: