Spring NoSuchBeanDefinitionException

1. Übersicht

In diesem Artikel wird die Spring org.springframework.beans.factory.NoSuchBeanDefinitionException erläutert. Dies ist eine häufige Ausnahme, die von BeanFactory ausgelöst wird, wenn versucht wird, eine Bean aufzulösen , die im Spring Context einfach nicht definiert ist .

Wir werden die möglichen Ursachen für dieses Problem und die verfügbaren Lösungen veranschaulichen.

Und natürlich treten Ausnahmen auf, wenn Sie sie am wenigsten erwarten. Schauen Sie sich die vollständige Liste der Ausnahmen und Lösungen im Frühjahr an.

2. Ursache: Keine qualifizierende Bean vom Typ […] für Abhängigkeit gefunden

Die häufigste Ursache für diese Ausnahme ist der einfache Versuch, eine nicht definierte Bean zu injizieren. Beispiel: BeanB verkabelt einen Mitarbeiter - BeanA:

@Component public class BeanA { @Autowired private BeanB dependency; //... }

Wenn die Abhängigkeit - BeanB - im Spring-Kontext nicht definiert ist, schlägt der Bootstrap-Prozess mit der Ausnahme "Keine solche Bean-Definition" fehl :

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.BeanB] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Der Grund wird von Spring klar angegeben: "Es wird mindestens 1 Bean erwartet, die als Autodrahtkandidat für diese Abhängigkeit qualifiziert ist. "

Ein Grund dafür, dass BeanB möglicherweise nicht im Kontext vorhanden ist - wenn Beans automatisch durch das Scannen von Klassenpfaden erfasst werden und wenn BeanB korrekt als Bean ( @Component , @Repository , @Service , @Controller usw.) mit Anmerkungen versehen ist - ist, dass dies möglicherweise der Fall ist definiert in einem Paket, das nicht von Spring gescannt wird :

package com.baeldung.packageB; @Component public class BeanB { ...}

Während das Scannen von Klassenpfaden wie folgt konfiguriert werden kann:

@Configuration @ComponentScan("com.baeldung.packageA") public class ContextWithJavaConfig { ... }

Wenn Beans nicht automatisch gescannt werden, sondern manuell definiert werden , wird BeanB im aktuellen Spring-Kontext einfach nicht definiert.

3. Ursache: Feld […] in […] Erforderlich ist eine Bean vom Typ […], die nicht gefunden werden konnte

In einer Spring Boot-Anwendung für das obige Szenario wird eine andere Meldung angezeigt.

Nehmen wir dasselbe Beispiel, in dem BeanB in BeanA verkabelt ist, aber nicht definiert ist:

@Component public class BeanA { @Autowired private BeanB dependency; //... }

Wenn wir versuchen, diese einfache Anwendung auszuführen, wird versucht, BeanA zu laden :

@SpringBootApplication public class NoSuchBeanDefinitionDemoApp { public static void main(String[] args) { SpringApplication.run(NoSuchBeanDefinitionDemoApp.class, args); } }

Die Anwendung startet nicht mit der Fehlermeldung:

*************************** APPLICATION FAILED TO START *************************** Description: Field dependency in com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA required a bean of type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' that could not be found. Action: Consider defining a bean of type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' in your configuration.

Hier ist com.baeldung.springbootmvc.nosuchbeandefinitionexception das Paket für BeanA , BeanB und NoSuchBeanDefinitionDemoApp .

Das Snippet für dieses Beispiel finden Sie in diesem Github-Projekt.

4. Ursache: Es ist keine qualifizierende Bean vom Typ […] definiert

Eine weitere Ursache für die Ausnahme ist das Vorhandensein von zwei Bean-Definitionen im Kontext anstelle von einer. Wenn beispielsweise eine Schnittstelle - IBeanB - von zwei Beans implementiert wird - BeanB1 und BeanB2 :

@Component public class BeanB1 implements IBeanB { // } @Component public class BeanB2 implements IBeanB { // }

Wenn BeanA diese Schnittstelle automatisch verdrahtet, weiß Spring nicht, welche der beiden Implementierungen injiziert werden soll:

@Component public class BeanA { @Autowired private IBeanB dependency; ... }

Dies führt wiederum dazu, dass eine NoSuchBeanDefinitionException von der BeanFactory ausgelöst wird :

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2

In ähnlicher Weise gibt Spring den Grund für den Verdrahtungsfehler deutlich an: "erwartete einzelne passende Bean, aber gefunden 2" .

Beachten Sie jedoch, dass in diesem Fall die genaue Ausnahme, die ausgelöst wird, nicht NoSuchBeanDefinitionException ist, sondern eine Unterklasse - die NoUniqueBeanDefinitionException . Diese neue Ausnahme wurde in Spring 3.2.1 aus genau diesem Grund eingeführt, um zwischen der Ursache, bei der keine Bean-Definition gefunden wurde, und dieser Ursache zu unterscheiden, bei der mehrere Definitionen im Kontext gefunden werden.

Vor dieser Änderung war die obige Ausnahme:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2

Eine Lösung für dieses Problem besteht darin, mithilfe der Annotation @Qualifier genau den Namen der Bean anzugeben, die verdrahtet werden soll:

@Component public class BeanA { @Autowired @Qualifier("beanB2") private IBeanB dependency; ... }

Jetzt hat Spring genug Informationen, um zu entscheiden, welche Bean injiziert werden soll - BeanB1 oder BeanB2 (der Standardname von BeanB2 ist beanB2 ).

5. Ursache: Es ist keine Bean mit dem Namen […] definiert

Eine NoSuchBeanDefinitionException kann auch ausgelöst werden, wenn eine nicht definierte Bean namentlich aus dem Spring-Kontext angefordert wird :

@Component public class BeanA implements InitializingBean { @Autowired private ApplicationContext context; @Override public void afterPropertiesSet() { context.getBean("someBeanName"); } }

In diesem Fall gibt es keine Bean-Definition für "someBeanName", was zu der folgenden Ausnahme führt:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'someBeanName' is defined

Auch hier gibt Spring den Grund für den Fehler klar und präzise an: „ Es ist keine Bean mit dem Namen X definiert “.

6. Ursache: Proxied Beans

When a bean in the context is proxied using the JDK Dynamic Proxy mechanism, then the proxy will not extend the target bean (it will, however, implement the same interfaces).

Because of this, if the bean is injected by an interface, it will be correctly wired in. If however the bean is injected by the actual class, then Spring will not find a bean definition that matches the class – since the proxy does not actually extend the class.

A very common reason the bean may be proxied is the Spring transactional support – namely beans that are annotated with @Transactional.

Wenn beispielsweise ServiceA ServiceB injiziert und beide Services transaktional sind, funktioniert das Injizieren nach der Klassendefinition nicht:

@Service @Transactional public class ServiceA implements IServiceA{ @Autowired private ServiceB serviceB; ... } @Service @Transactional public class ServiceB implements IServiceB{ ... }

Die gleichen zwei Dienste, die diesmal korrekt von der Schnittstelle injiziert werden , sind in Ordnung:

@Service @Transactional public class ServiceA implements IServiceA{ @Autowired private IServiceB serviceB; ... } @Service @Transactional public class ServiceB implements IServiceB{ ... }

7. Fazit

In diesem Lernprogramm wurden Beispiele für mögliche Ursachen für die allgemeine NoSuchBeanDefinitionException erläutert, wobei der Schwerpunkt darauf lag, wie diese Ausnahmen in der Praxis behoben werden können.

Die Implementierung all dieser Ausnahmebeispiele finden Sie im GitHub-Projekt - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.

Schließlich könnte die vollständige Liste der Ausnahmen und Lösungen im Frühjahr eine gute Ressource für Lesezeichen sein.