GetBean () im Frühjahr verstehen

1. Einleitung

In diesem Tutorial werden wir verschiedene Varianten der BeanFactory.getBean () -Methode durchgehen .

Einfach ausgedrückt, wie der Name der Methode ebenfalls andeutet, ist dies für das Abrufen einer Bean-Instanz aus dem Spring-Container verantwortlich .

2. Spring Beans Setup

Definieren wir zunächst einige Spring Beans zum Testen. Es gibt verschiedene Möglichkeiten, Bean-Definitionen für den Spring-Container bereitzustellen. In unserem Beispiel verwenden wir jedoch eine annotationsbasierte Java-Konfiguration:

@Configuration class AnnotationConfig { @Bean(name = {"tiger", "kitty"}) @Scope(value = "prototype") Tiger getTiger(String name) { return new Tiger(name); } @Bean(name = "lion") Lion getLion() { return new Lion("Hardcoded lion name"); } interface Animal {} } 

Wir haben zwei Bohnen erstellt. Lion hat den Standard-Singleton-Bereich. Tiger ist explizit auf den Prototypenbereich eingestellt. Beachten Sie außerdem, dass wir für jede Bean Namen definiert haben, die wir in weiteren Anfragen verwenden werden.

3. Die getBean () APIs

BeanFactory bietet fünf verschiedene Signaturen der Methode getBean () , die wir in den folgenden Unterabschnitten untersuchen werden.

3.1. Bean nach Namen abrufen

Mal sehen, wie wir eine Lion Bean-Instanz mit ihrem Namen abrufen können :

Object lion = context.getBean("lion"); assertEquals(Lion.class, lion.getClass());

In dieser Variante geben wir einen Namen an und erhalten im Gegenzug eine Instanz der Object- Klasse, wenn im Anwendungskontext eine Bean mit dem angegebenen Namen vorhanden ist. Andernfalls lösen sowohl diese als auch alle anderen Implementierungen NoSuchBeanDefinitionException aus, wenn die Bean-Suche fehlschlägt.

Der Hauptnachteil ist, dass wir die Bohne nach dem Abrufen auf den gewünschten Typ umwandeln müssen. Dies kann zu einer weiteren Ausnahme führen, wenn die zurückgegebene Bean einen anderen Typ als erwartet hat .

Angenommen, wir versuchen, einen Tiger mit dem Namen "Löwe" zu bekommen. Wenn wir das Ergebnis in Tiger umwandeln , wird eine ClassCastException ausgelöst :

assertThrows(ClassCastException.class, () -> { Tiger tiger = (Tiger) context.getBean("lion"); });

3.2. Bean nach Name und Typ abrufen

Hier müssen wir sowohl den Namen als auch den Typ der angeforderten Bean angeben:

Lion lion = context.getBean("lion", Lion.class);

Im Vergleich zur vorherigen Methode ist diese Methode sicherer, da wir sofort Informationen über Typinkongruenzen erhalten:

assertThrows(BeanNotOfRequiredTypeException.class, () -> context.getBean("lion", Tiger.class)); }

3.3. Bean nach Typ abrufen

Bei der dritten Variante von getBean () reicht es aus, nur den Bean-Typ anzugeben:

Lion lion = context.getBean(Lion.class);

In diesem Fall müssen wir einem möglicherweise nicht eindeutigen Ergebnis besondere Aufmerksamkeit widmen :

assertThrows(NoUniqueBeanDefinitionException.class, () -> context.getBean(Animal.class)); }

Da im obigen Beispiel sowohl Lion als auch Tiger die Animal- Schnittstelle implementieren , reicht es nicht aus, nur den Typ anzugeben, um das Ergebnis eindeutig zu bestimmen. Daher erhalten wir eine NoUniqueBeanDefinitionException .

3.4. Bean nach Namen mit Konstruktorparametern abrufen

Zusätzlich zum Bean-Namen können wir auch Konstruktorparameter übergeben:

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");

Diese Methode ist etwas anders, da sie nur für Beans mit Prototypbereich gilt .

Im Fall von Singletons erhalten wir eine BeanDefinitionStoreException.

Da eine Prototyp-Bean jedes Mal, wenn sie vom Anwendungscontainer angefordert wird, eine neu erstellte Instanz zurückgibt , können wir beim Aufrufen von getBean () sofort Konstruktorparameter bereitstellen :

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian"); Tiger secondTiger = (Tiger) context.getBean("tiger", "Striped"); assertEquals("Siberian", tiger.getName()); assertEquals("Striped", secondTiger.getName());

Wie wir sehen können, erhält jeder Tiger einen anderen Namen, je nachdem, was wir bei der Anforderung der Bean als zweiten Parameter angegeben haben.

3.5. Bean nach Typ mit Konstruktorparametern abrufen

Diese Methode ist analog zur letzten, aber wir müssen den Typ anstelle des Namens als erstes Argument übergeben:

Tiger tiger = context.getBean(Tiger.class, "Shere Khan"); assertEquals("Shere Khan", tiger.getName());

Ähnlich wie beim Abrufen einer Bean nach Namen mit Konstruktorparametern gilt diese Methode nur für Beans mit Prototypbereich .

4. Überlegungen zur Verwendung

Obwohl in der BeanFactory- Schnittstelle definiert, wird auf die getBean () -Methode am häufigsten über den ApplicationContext zugegriffen . Normalerweise möchten wir die Methode getBean () nicht direkt in unserem Programm verwenden .

Bohnen sollten vom Behälter verwaltet werden. Wenn wir eine davon verwenden möchten, sollten wir uns eher auf die Abhängigkeitsinjektion als auf einen direkten Aufruf von ApplicationContext.getBean () verlassen . Auf diese Weise können wir vermeiden, Anwendungslogik mit Framework-bezogenen Details zu mischen.

5. Schlussfolgerung

In diesem kurzen Tutorial haben wir alle Implementierungen der getBean () -Methode über die BeanFactory- Schnittstelle durchgearbeitet und die Vor- und Nachteile der einzelnen Methoden beschrieben.

Alle hier gezeigten Codebeispiele sind auf GitHub verfügbar.