Spring NoSuchBeanDefinitionException

Spring NoSuchBeanDefinitionException

1. Überblick

In diesem Artikel diskutieren wir dieSpring org.springframework.beans.factory.NoSuchBeanDefinitionException - dies ist eine häufige Ausnahme, die vonBeanFactory ausgelöst wird, wenn versucht wird,a bean that simply isn’t defined im Frühlingskontext aufzulösen.

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 sichthe full list of exceptions and solutions in Spring an.

Weitere Lektüre:

Spring Exceptions Tutorial

Einige der häufigsten Ausnahmen im Frühjahr mit Beispielen - warum sie auftreten und wie sie schnell gelöst werden können.

Read more

Spring BeanCreationException

Eine schnelle und praktische Anleitung zum Umgang mit verschiedenen Ursachen der Spring BeanCreationException

Read more

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

Die häufigste Ursache für diese Ausnahme ist der Versuch, eine nicht definierte Bean zu injizieren. Zum Beispiel -BeanB ist die Verkabelung in einem 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 mitthe no such bean definition exception fehl:

org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.example.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 durch Spring deutlich angegeben: "expected at least 1 bean which qualifies as autowire candidate for this dependency"

Ein Grund, warumBeanB möglicherweise nicht im Kontext vorhanden ist - wenn Beans automatisch vonclasspath scanning aufgenommen werden undBeanB korrekt als Bean (@Component,@Repositorykommentiert wird ) s,@Service,@Controller usw.) - ist, dass es ina package that is not scanned by Spring definiert werden kann:

package org.example.packageB;
@Component
public class BeanB { ...}

Während der Klassenpfad-Scan kann wie folgt konfiguriert werden:

@Configuration
@ComponentScan("org.example.packageA")
public class ContextWithJavaConfig {
    ...
}

Wenn Beans nicht automatisch vondefined manually gescannt werden, istBeanB 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 oben genannte Szenario wird eine andere Meldung angezeigt.

Nehmen wir dasselbe Beispiel, in demBeanB inBeanA verdrahtet 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.example.springbootmvc.nosuchbeandefinitionexception.BeanA required a bean of type 'com.example.springbootmvc.nosuchbeandefinitionexception.BeanB' that could not be found.


Action:

Consider defining a bean of type 'com.example.springbootmvc.nosuchbeandefinitionexception.BeanB' in your configuration.

Hier istcom.example.springbootmvc.nosuchbeandefinitionexception das Paket fürBeanA,BeanB undNoSuchBeanDefinitionDemoApp.

Das Snippet für dieses Beispiel befindet sich inthis Github project.

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 undBeanB2:

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

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

@Component
public class BeanA {

    @Autowired
    private IBeanB dependency;
    ...
}

Und wieder führt dies dazu, dassNoSuchBeanDefinitionException vonBeanFactory geworfen werden:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type
  [org.example.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:“expected single matching bean but found 2”.

Beachten Sie jedoch, dass in diesem Fall die genaue Ausnahme nichtNoSuchBeanDefinitionException ist, sondern eine Unterklasse -the NoUniqueBeanDefinitionException. Diese neue Ausnahme warintroduced in Spring 3.2.1, genau aus diesem Grund - um zwischen der Ursache zu unterscheiden, bei der keine Bean-Definition gefunden wurde, und dieser - bei der mehrere Definitionen im Kontext gefunden wurden.

Vor dieser Änderung war die obige Ausnahme:

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

Einsolution to this problem is to use the @Qualifier annotation, um genau den Namen der Bean anzugeben, die wir verkabeln möchten:

@Component
public class BeanA {

    @Autowired
    @Qualifier("beanB2")
    private IBeanB dependency;
    ...
}

Jetzt hat Spring genug Informationen, um zu entscheiden, welche Bean injiziert werden soll -BeanB1 oderBeanB2 (der Standardname vonBeanB2 istbeanB2).

5. Ursache: Es ist keine Bean namens […] definiert

EinNoSuchBeanDefinitionException kann auch geworfen werden, wenn eine nicht definierte Beanrequested by name aus dem Spring-Kontext ist:

@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: „No bean named X is defined“.

6. Ursache: Proxied Beans

Wenn eine Bean im Kontext mithilfe des dynamischen JDK-Proxy-Mechanismus als Proxy verwendet wird, giltthe proxy will not extend the target bean (es werden jedoch dieselben Schnittstellen implementiert).

Wenn die Bean über eine Schnittstelle injiziert wird, wird sie aus diesem Grund korrekt verkabelt. Wenn die Bean jedoch von der tatsächlichen Klasse injiziert wird, findet Spring keine Bean-Definition, die der Klasse entspricht, da der Proxy die Klasse nicht tatsächlich erweitert.

Ein sehr häufiger Grund, warum die Bean als Proxy verwendet werden kann, sindSpring transactional support - nämlich Bohnen, die mit@Transactional versehen sind.

Wenn beispielsweiseServiceAServiceB injiziert und beide Dienste transaktional sind, funktioniertinjecting by the class definition nicht:

@Service
@Transactional
public class ServiceA implements IServiceA{

    @Autowired
    private ServiceB serviceB;
    ...
}

@Service
@Transactional
public class ServiceB implements IServiceB{
    ...
}

Die gleichen zwei Dienste, diesmal korrektinjecting by the interface, 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 Tutorial wurden Beispiele für mögliche Ursachen für die gemeinsamenNoSuchBeanDefinitionException erörtert - mit einem Schwerpunkt darauf, wie diese Ausnahmen in der Praxis behoben werden können.

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

Schließlich könntenthe full list of exceptions and solutions im Frühjahr eine gute Ressource zum Lesezeichen sein.