Kopplung und Objektaufbau

Was ist Dependency Injection?

Abhängigkeitsinjektion

Dependency Injection ist ein Entwurfsprinzip, bei dem eine Klasse die Objekte, die sie zum Arbeiten braucht, von außen übergeben bekommt, statt sie selbst zu erzeugen. Damit legt nicht mehr die Klasse fest, welche konkrete Implementierung sie benutzt, sondern die Stelle, die sie zusammenbaut.

Sobald du einen Mailversand testen willst, ohne echte Mails zu verschicken, merkst du, ob die Klasse ihre Abhängigkeiten selbst erzeugt oder übergeben bekommt.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Gehört zu
Inversion of Control
Übliche Form
Übergabe über den Konstruktor
Container in
Spring, .NET, Angular, NestJS
Nutzen
Tests mit Attrappen statt echter Systeme

Der Unterschied an einem Beispiel

Eine Klasse zur Rechnungsstellung, die in ihrem Konstruktor selbst einen konkreten Mailversand erzeugt, ist an genau diesen Versand gebunden. Wer sie testet, verschickt Mails. Wer sie in einer anderen Umgebung nutzen will, muss den Quelltext ändern.

Übergibst du stattdessen ein Objekt, das eine Versandschnittstelle erfüllt, entscheidet der Aufrufer. In der Produktion reicht er den echten Versand herein, im Test ein Attrappenobjekt, das den Aufruf nur aufzeichnet. Der Code der Rechnungsklasse bleibt in beiden Fällen unverändert.

Das ist der ganze Kern. Alles Weitere, Container, Annotationen, Konfigurationsdateien, ist Bequemlichkeit für den Fall, dass es nicht um zwei, sondern um zweihundert Objekte geht.

Varianten und was der Container macht

Bei der Constructor Injection kommen alle Abhängigkeiten über den Konstruktor herein. Das ist die empfohlene Form, weil ein Objekt danach vollständig ist und Felder final sein können. Bleibt eine Abhängigkeit optional, bietet sich Setter Injection an. Von der Field Injection, also der Zuweisung direkt an die Felder, raten die meisten Teams ab, weil sich das Objekt außerhalb des Frameworks nicht mehr ohne Reflexion aufbauen lässt und die Liste der Abhängigkeiten unsichtbar wird.

In Java übernimmt ein Container das Zusammenstecken. Spring erzeugt die Objekte, erkennt am Konstruktor, was gebraucht wird, und liefert passende Instanzen. Jakarta EE macht dasselbe über CDI mit der Annotation Inject. Der Container verwaltet außerdem die Lebensdauer, also ob ein Objekt einmal pro Anwendung oder pro Anfrage existiert.

Ein sichtbarer Nebeneffekt: Fehler verschieben sich vom Kompilieren in den Start. Wenn keine passende Implementierung gefunden wird oder zwei Kandidaten in Frage kommen, meldet sich der Container beim Hochfahren. Die Meldung nennt in der Regel Typ und Einbaustelle, damit lässt sich die Ursache schnell einkreisen.

Wo es kippt

Ein Konstruktor mit acht Parametern ist kein Argument gegen Dependency Injection, sondern ein Hinweis, dass die Klasse zu viele Aufgaben hat. Das Prinzip macht solche Häufungen sichtbar, statt sie im Inneren zu verstecken, und die richtige Antwort ist ein anderer Schnitt der Klasse.

Der zweite Stolperstein sind Zyklen. Wenn A B braucht und B wiederum A, kommt der Container beim Aufbau nicht weiter. Auch hier hilft kein Trick, sondern die Frage, welche gemeinsame Aufgabe in eine dritte Klasse gehört.

Und nicht jede Abhängigkeit muss injiziert werden. Eine Klasse für ein Datum oder eine Liste erzeugst du weiterhin direkt. Das Prinzip zielt auf alles, was du in einem Test austauschen oder in einer anderen Umgebung anders verdrahten willst.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Nicht verwechseln

Dependency Injection und was oft damit gleichgesetzt wird

Dependency Injection gegen Inversion of Control

Inversion of Control ist das übergeordnete Prinzip, dass die Steuerung beim Rahmenwerk liegt. Dependency Injection ist eine konkrete Ausprägung davon.

Dependency Injection gegen Service Locator

Beim Service Locator holt sich die Klasse ihre Abhängigkeiten aktiv aus einem Verzeichnis. Sie kennt dieses Verzeichnis dann und ist damit schwerer isoliert zu testen als eine Klasse, die alles übergeben bekommt.

Dependency Injection gegen Factory

Eine Factory kapselt die Erzeugung von Objekten. Sie kann Teil der Lösung sein, nimmt der Klasse aber nicht die Entscheidung ab, welche Implementierung sie benutzt.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
In der Praxis

Der Konstruktor verrät, wie es um die Klasse steht

Wenn eine Klasse acht Dinge übergeben bekommt, ist nicht die Injektion das Problem, sondern der Zuschnitt. Der Konstruktor listet ungeschönt auf, wovon die Klasse abhängt, und diese Liste ist der beste Hinweis darauf, dass hier zwei oder drei Aufgaben in einer Datei liegen.

Mit einem Container fällt ein Teil der Fehler erst beim Start der Anwendung auf statt beim Übersetzen. Fehlt eine Registrierung, merkst du davon im Editor nichts, sondern erst, wenn der Dienst hochfährt. Deshalb gehört ein Test dazu, der den Container einmal vollständig aufbaut.

Am unangenehmsten sind falsche Lebensdauern. Ein Objekt, das nur einmal existiert und sich dabei etwas aus dem aktuellen Aufruf merkt, gibt diese Information beim nächsten Aufruf an jemand anderen weiter. Solche Fehler treten unter Last auf und lassen sich am Arbeitsplatz kaum nachstellen.

Dependency Injection lernen

Wie der Container Objekte findet, verdrahtet und verwaltet, machen die Trainings zum Spring-Framework an einer Anwendung nachvollziehbar, die du selbst aufbaust.

Häufige Fragen

Brauche ich für Dependency Injection ein Framework?
Nein. Das Prinzip funktioniert mit einfachen Konstruktoraufrufen. Ein Container lohnt sich, wenn viele Objekte zusammengesteckt werden und du deren Lebensdauer nicht von Hand verwalten willst.
Warum Constructor statt Field Injection?
Weil ein über den Konstruktor gebautes Objekt nach der Erzeugung vollständig und unveränderlich ist, sich ohne Framework instanziieren lässt und seine Abhängigkeiten offen in der Signatur zeigt. Bei Field Injection stehen sie versteckt an den Feldern.
Was tun bei mehreren passenden Implementierungen?
Der Container braucht eine Entscheidungshilfe, in Spring etwa eine Kennzeichnung als bevorzugte Variante oder einen Qualifier an der Einbaustelle. Ohne diese Angabe bricht der Start mit einem Hinweis auf die mehrdeutige Zuordnung ab.
Persönlich für dich da

Deine Ansprechpartner

Du willst das Thema nicht nur nachschlagen, sondern anwenden können? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Ordnet mit dir ein, welcher Kurs zu deinem Vorwissen passt.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant Inhouse-Trainings, die an euren eigenen Daten und Abläufen ansetzen.

Dependency Injection im Kurs statt im Lexikon

Nachschlagen bringt dich bis zum Verstehen. Anwenden lernst du an echten Aufgaben.