Intro to Inversion of Control und Dependency Injection mit Spring

Intro to Inversion of Control und Dependency Injection mit Spring

Überblick

In diesem Artikel, wir werden die Einführung der Konzepte des IoC (Inversion of Control) und DI (Dependency Injection), und wir werden dann nehmen Sie einen Blick an, wie diese Umsetzung im Spring framework.,

Weitere Informationen:

im Frühjahr: @Autowired, @Resource und @Inject

Dieser Artikel vergleicht und kontrastiert die Verwendung von Anmerkungen zur Abhängigkeitsinjektion, nämlich die Anmerkungen @Resource, @Inject und @Autowired.
Lesen Sie mehr →

@Component vs @Repository und @Service in Spring

Erfahren Sie mehr über die Unterschiede zwischen den Annotationen @Component, @Repository und @Service und wann Sie sie verwenden.
Lesen Sie mehr →

Was ist Inversion der Kontrolle?,

Die Inversion der Steuerung ist ein Prinzip in der Softwareentwicklung, mit dem die Steuerung von Objekten oder Teilen eines Programms in einen Container oder ein Framework übertragen wird. Es wird am häufigsten im Kontext der objektorientierten Programmierung verwendet.

Im Gegensatz zur herkömmlichen Programmierung, bei der unser benutzerdefinierter Code eine Bibliothek aufruft, ermöglicht das IoC einem Framework, die Kontrolle über den Ablauf eines Programms zu übernehmen und unseren benutzerdefinierten Code aufzurufen. Um dies zu ermöglichen, verwenden Frameworks Abstraktionen mit integriertem zusätzlichem Verhalten., Wenn wir unser eigenes Verhalten hinzufügen möchten, müssen wir die Klassen des Frameworks erweitern oder unsere eigenen Klassen hinzufügen.,

Die Vorteile dieser Architektur sind:

  • Entkopplung der Ausführung einer Aufgabe von ihrer Implementierung
  • erleichtert den Wechsel zwischen verschiedenen Implementierungen
  • größere Modularität eines Programms
  • größere Leichtigkeit beim Testen eines Programms durch Isolieren einer Komponente oder Verspotten ihrer Abhängigkeiten und Ermöglichen der Kommunikation von Komponenten über Verträge

Die Inversion der Kontrolle kann durch verschiedene Mechanismen erreicht werden, z., Factory Pattern und Dependency Injection (DI).,

Als nächstes schauen wir uns DI an.

Was Ist Dependency Injection?

Dependency injection ist ein Muster zur Implementierung von IoC, wobei das invertierte Steuerelement die Einstellung der Abhängigkeiten des Objekts ist.

Das Verbinden von Objekten mit anderen Objekten oder das „Injizieren“ von Objekten in andere Objekte erfolgt durch einen Assembler und nicht durch die Objekte selbst.,

So erstellen Sie eine Objektabhängigkeit in der herkömmlichen Programmierung:

public class Store { private Item item; public Store() { item = new ItemImpl1(); }}

Im obigen Beispiel müssen wir eine Implementierung der Item Schnittstelle innerhalb der Store Klasse instanziieren.

Mit DI können wir das Beispiel umschreiben, ohne die gewünschte Implementierung von Item anzugeben:

public class Store { private Item item; public Store(Item item) { this.item = item; }}

In den nächsten Abschnitten werden wir sehen, wie wir die Implementierung von Item über Metadaten bereitstellen können.,

Sowohl IoC als auch DI sind einfache Konzepte, haben jedoch tiefe Auswirkungen auf die Art und Weise, wie wir unsere Systeme strukturieren, sodass es sich lohnt, sie gut zu verstehen.

Der Spring IoC Container

Ein IoC Container ist ein gemeinsames Merkmal von Frameworks, die IoC implementieren.

Im Spring Framework wird der IoC Container durch die Schnittstelle ApplicationContext dargestellt. Der Spring-Container ist für die Instanziierung, Konfiguration und Zusammenstellung von Objekten, die als Beans bezeichnet werden, sowie für die Verwaltung ihres Lebenszyklus verantwortlich.,

Das Spring Framework bietet mehrere Implementierungen der ApplicationContext-Schnittstelle-ClassPathXmlApplicationContext und FileSystemXmlApplicationContext für eigenständige Anwendungen und WebApplicationContext für Webanwendungen.

Um Beans zusammenzustellen, verwendet der Container Konfigurationsmetadaten, die in Form von XML-Konfiguration oder Anmerkungen vorliegen können.

Hier ist eine Möglichkeit, einen Container manuell zu instanziieren:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Um das Elementattribut im obigen Beispiel festzulegen, können wir Metadaten verwenden., Anschließend liest der Container diese Metadaten und verwendet sie zum Zusammenstellen von Beans zur Laufzeit.

Die Abhängigkeitsinjektion im Frühjahr kann über Konstruktoren, Setter oder Felder erfolgen.

Konstruktorbasierte Abhängigkeitsinjektion

Im Falle einer konstruktorbasierten Abhängigkeitsinjektion ruft der Container einen Konstruktor mit Argumenten auf, die jeweils eine Abhängigkeit darstellen, die wir festlegen möchten.

Spring löst jedes Argument in erster Linie nach Typ auf, gefolgt vom Namen des Attributs und Index für die Disambiguierung., Sehen wir uns die Konfiguration einer Bean und ihrer Abhängigkeiten mithilfe von Anmerkungen an:

Die Annotation @Configuration gibt an, dass die Klasse eine Quelle von Bean-Definitionen ist. Außerdem können wir es mehreren Konfigurationsklassen hinzufügen.

Die @Bean Annotation wird für eine Methode zum Definieren einer Bean verwendet. Wenn wir keinen benutzerdefinierten Namen angeben, wird der Bean-Name standardmäßig auf den Methodennamen gesetzt.

Für eine Bean mit dem Standard-Singleton-Bereich prüft Spring zuerst, ob eine zwischengespeicherte Instanz der Bean bereits vorhanden ist, und erstellt nur dann eine neue, wenn dies nicht der Fall ist., Wenn wir den Prototypbereich verwenden, gibt der Container für jeden Methodenaufruf eine neue Bean-Instanz zurück.

Eine andere Möglichkeit, die Konfiguration der Beans zu erstellen, besteht in der XML-Konfiguration:

Setter-basierte Abhängigkeitsinjektion

Für Setter-basierte DI ruft der Container Setter-Methoden unserer Klasse auf, nachdem ein Konstruktor ohne Argument oder eine statische Factory-Methode ohne Argument aufgerufen wurde, um die Bean zu instanziieren., Lassen Sie uns diese Konfiguration mit Anmerkungen erstellen:

@Beanpublic Store store() { Store store = new Store(); store.setItem(item1()); return store;}

Wir können auch XML für die gleiche Konfiguration von Beans verwenden:

<bean class="org.baeldung.store.Store"> <property name="item" ref="item1" /></bean>

Konstruktorbasierte und setter-basierte Injektionstypen können für dieselbe Bean kombiniert werden. Die Spring-Dokumentation empfiehlt die Verwendung einer konstruktorbasierten Injektion für obligatorische Abhängigkeiten und einer setterbasierten Injektion für optionale Abhängigkeiten.

7., Feldbasierte Abhängigkeitsinjektion

Bei feldbasierten DI können wir die Abhängigkeiten injizieren, indem wir sie mit einer @Autowired Annotation markieren:

public class Store { @Autowired private Item item; }

Wenn beim Erstellen des Speicherobjekts keine Konstruktor-oder Setter-Methode zum Injizieren der Element-Bean vorhanden ist, verwendet der Container Reflektion, um Elemente in den Speicher einzufügen.

Dies können wir auch mithilfe der XML-Konfiguration erreichen.,

Dieser Ansatz sieht möglicherweise einfacher und sauberer aus, wird jedoch nicht empfohlen, da er einige Nachteile aufweist, z. B.:

  • Diese Methode verwendet Reflektion, um die Abhängigkeiten zu injizieren, was teurer ist als konstruktorbasierte oder Setter-basierte Injektion
  • Es ist wirklich einfach, mit diesem Ansatz weiterhin mehrere Abhängigkeiten hinzuzufügen. Wenn Sie die Konstruktorinjektion mit mehreren Argumenten verwenden würden, hätten wir gedacht, dass die Klasse mehr als eine Sache tut, die das Prinzip der einzelnen Verantwortung verletzen kann.,

Weitere Informationen zur Annotation @Autowired finden Sie im Artikel Wiring In Spring.

Autowiring-Abhängigkeiten

Mit der Verdrahtung kann der Spring-Container Abhängigkeiten zwischen kollaborativen Beans automatisch auflösen, indem die Beans überprüft werden, die definiert wurden.,

Es gibt vier Arten der automatischen Verkabelung einer Bean mithilfe einer XML – Konfiguration:

  • nein: der Standardwert-dies bedeutet, dass für die Bean keine automatische Verkabelung verwendet wird und wir die Abhängigkeiten explizit benennen müssen
  • byName: Die automatische Verkabelung erfolgt basierend auf dem Namen der Eigenschaft, daher sucht Spring nach einer Bean mit demselben Namen wie die Eigenschaft, die festgelegt werden muss
  • byType: ähnlich wie die byName-Autowiring, nur basierend auf dem Typ der Immobilie. Dies bedeutet, dass Spring nach einer Bean mit demselben Typ der zu setzenden Eigenschaft sucht., Wenn es mehr als eine Bean dieses Typs gibt, löst das Framework eine Ausnahme aus.,kann auch Beans mit der Annotation @Autowired für die automatische Verkabelung nach Typ injizieren:
    public class Store { @Autowired private Item item;}

    Wenn es mehr als eine Bean desselben Typs gibt, können wir die Annotation @Qualifier verwenden, um auf eine Bean nach Namen zu verweisen:

    public class Store { @Autowired @Qualifier("item1") private Item item;}

    Jetzt können wir Beans nach Typ mithilfe der XML-Konfiguration autowired:

    <bean class="org.baeldung.store.Store" autowire="byType"> </bean>

    Als nächstes injizieren wir eine Bean mit dem Namen item in die item Eigenschaft von store Bean mit dem Namen über XML:

    <bean class="org.baeldung.store.ItemImpl1" /><bean class="org.baeldung.store.Store" autowire="byName"></bean>

    Wir können die Autowiring auch überschreiben, indem wir Abhängigkeiten explizit über Konstruktorargumente oder Setter definieren.,

    Lazy Initialized Beans

    Standardmäßig erstellt und konfiguriert der Container alle Singleton-Beans während der Initialisierung. Um dies zu vermeiden, können Sie das lazy-init-Attribut mit dem Wert true in der Bean-Konfiguration verwenden:

    <bean class="org.baeldung.store.ItemImpl1" lazy-init="true" />

    Folglich wird die item1-Bean nur initialisiert, wenn sie zum ersten Mal angefordert wird und nicht beim Start., Der Vorteil davon ist eine schnellere Initialisierungszeit, aber der Kompromiss besteht darin, dass Konfigurationsfehler erst entdeckt werden können, nachdem die Bean angefordert wurde, was mehrere Stunden oder sogar Tage dauern kann, nachdem die Anwendung bereits ausgeführt wurde.

    Schlussfolgerung

    In diesem Artikel haben wir die Konzepte der Inversion von Control und Dependency Injection vorgestellt und im Spring Framework veranschaulicht.

    Sie können mehr über diese Konzepte in Martin Fowlers Artikeln lesen:

    • Inversion von Steuercontainern und das Abhängigkeitsinjektionsmuster.,
    • Inversion der Steuerung

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.