Spring NoSuchBeanDefinitionException

1. Overzicht

In dit artikel bespreken we de Voorjaar org.springframework.beans.factory.NoSuchBeanDefinitionException - dit is een veel voorkomende uitzondering die wordt gegenereerd door de BeanFactory bij het proberen op te lossen een boon die simpelweg niet gedefinieerd is in de lentecontext.

We illustreren de mogelijke oorzaken van dit probleem en de beschikbare oplossingen.

En natuurlijk gebeuren er uitzonderingen wanneer u ze het minst verwacht; Bekijk de volledige lijst met uitzonderingen en oplossingen in het voorjaar.

2. Oorzaak: geen kwalificerende bonen van het type […] gevonden voor afhankelijkheid

De meest voorkomende oorzaak van deze uitzondering is simpelweg proberen een boon te injecteren die niet is gedefinieerd. Bijvoorbeeld - BeanB is bedrading in een medewerker - BeanA:

@Component openbare klasse BeanA {@Autowired privé BeanB-afhankelijkheid; // ...}

Nu, als de afhankelijkheid - BeanB - is niet gedefinieerd in de Spring Context, zal het bootstrap-proces mislukken de geen dergelijke uitzondering voor de definitie van bonen:

org.springframework.beans.factory.NoSuchBeanDefinitionException: Geen kwalificerende bean van het type [com.baeldung.packageB.BeanB] gevonden voor afhankelijkheid: verwacht ten minste 1 bean die kwalificeert als autowire-kandidaat voor deze afhankelijkheid. Afhankelijkheidsaantekeningen: {@ org.springframework.beans.factory.annotation.Autowired (vereist = waar)}

De reden wordt duidelijk aangegeven door Spring: "verwacht ten minste 1 boon die kwalificeert als autowire-kandidaat voor deze afhankelijkheid

Een reden BeanB bestaat mogelijk niet in de context - als bonen automatisch worden opgepikt door klassenpad scannen, en als BeanB is correct geannoteerd als een boon (@Component, @Repository, @Onderhoud, @Controller, etc) - is dat het kan worden gedefinieerd in een pakket dat niet door Spring wordt gescand:

pakket com.baeldung.packageB; @Component openbare klasse BeanB {...}

Hoewel het scannen van het klassenpad als volgt kan worden geconfigureerd:

@Configuration @ComponentScan ("com.baeldung.packageA") openbare klasse ContextWithJavaConfig {...}

Als bonen niet automatisch worden gescand door handmatig gedefinieerd, dan BeanB is simpelweg niet gedefinieerd in de huidige Spring Context.

3. Oorzaak: Veld [...] in [...] vereiste een boon van het type [...] dat niet kon worden gevonden

In een Spring Boot-applicatie voor het bovenstaande scenario krijgen we een ander bericht.

Laten we hetzelfde voorbeeld nemen waar BeanB is aangesloten BeanA maar het is niet gedefinieerd:

@Component openbare klasse BeanA {@Autowired privé BeanB-afhankelijkheid; // ...}

Als we deze eenvoudige applicatie proberen uit te voeren, probeert die te laden BeanA:

@SpringBootApplication openbare klasse NoSuchBeanDefinitionDemoApp {openbare statische leegte hoofd (String [] args) {SpringApplication.run (NoSuchBeanDefinitionDemoApp.class, args); }}

De applicatie start niet met de foutmelding:

*************************** AANVRAAG IS MISLUKT **************************************************************************************************************************************************************************** ******** Beschrijving: Veldafhankelijkheid in com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA vereiste een bean van het type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' die niet kon worden gevonden. Actie: Overweeg om in uw configuratie een bean van het type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' te definiëren.

Hier, com.baeldung.springbootmvc.nosuchbeandefinitionexception is het pakket voor BeanA, BeanB en NoSuchBeanDefinitionDemoApp.

Het fragment voor dit voorbeeld is te vinden in dit Github-project.

4. Oorzaak: er is geen kwalificerende bonen van het type […] gedefinieerd

Een andere reden voor de uitzondering is het bestaan ​​van twee bean-definities in de context, in plaats van één. Als een interface bijvoorbeeld - IBeanB wordt uitgevoerd door twee bonen - Boon B1 en BeanB2:

@Component openbare klasse BeanB1 implementeert IBeanB {//} @Component openbare klasse BeanB2 implementeert IBeanB {//}

Nu als BeanA autowires deze interface, zal Spring niet weten welke van de twee implementaties hij moet injecteren:

@Component openbare klasse BeanA {@Autowired privé IBeanB-afhankelijkheid; ...}

En nogmaals, dit zal resulteren in een NoSuchBeanDefinitionException wordt gegooid door de BeanFactory:

Veroorzaakt door: org.springframework.beans.factory.NoUniqueBeanDefinitionException: er is geen kwalificerende bean van het type [com.baeldung.packageB.IBeanB] gedefinieerd: verwachte enkele overeenkomende bean maar gevonden 2: beanB1, beanB2

Evenzo geeft Spring duidelijk de reden voor de bedradingsfout aan: 'Verwachte enkele overeenkomende boon maar 2 gevonden'.

Merk echter op dat in dit geval de exacte uitzondering die wordt gegenereerd, niet is NoSuchBeanDefinitionException maar een subklasse - de NoUniqueBeanDefinitionException. Deze nieuwe uitzondering is geïntroduceerd in Spring 3.2.1, precies om deze reden - om onderscheid te maken tussen de oorzaak waar geen bean-definitie werd gevonden en deze - waar verschillende definities in de context worden gevonden.

Vóór deze wijziging was de bovenstaande uitzondering:

Veroorzaakt door: org.springframework.beans.factory.NoSuchBeanDefinitionException: er is geen kwalificerende bean van het type [com.baeldung.packageB.IBeanB] gedefinieerd: verwachte enkele overeenkomende bean maar gevonden 2: beanB1, beanB2

een oplossing voor dit probleem is om de @Kwalificatie annotatie om precies de naam te specificeren van de boon die we willen bedraden:

@Component openbare klasse BeanA {@Autowired @Qualifier ("beanB2") privé IBeanB-afhankelijkheid; ...}

Nu heeft de lente genoeg informatie om te beslissen welke boon moet worden geïnjecteerd - Boon B1 of BeanB2 (de standaardnaam van BeanB2 is beanB2).

5. Oorzaak: er is geen bonen met de naam […] gedefinieerd

EEN NoSuchBeanDefinitionException kan ook worden gegooid als een boon die niet is gedefinieerd, is op naam aangevraagd uit de lentecontext:

@Component openbare klasse BeanA implementeert InitializingBean {@Autowired privé ApplicationContext-context; @Override public void afterPropertiesSet () {context.getBean ("someBeanName"); }}

In dit geval is er geen bean-definitie voor "someBeanName", wat leidt tot de volgende uitzondering:

Veroorzaakt door: org.springframework.beans.factory.NoSuchBeanDefinitionException: er is geen bean met de naam 'someBeanName' gedefinieerd

Nogmaals, Spring geeft duidelijk en beknopt de reden voor het falen aan: "Er is geen boon met de naam X gedefinieerd“.

6. Oorzaak: Proxied Beans

Als een bean in de context een proxy gebruikt met behulp van het JDK Dynamic Proxy-mechanisme, dan de proxy verlengt de doelboon niet (het zal echter dezelfde interfaces implementeren).

Daarom, als de bean wordt geïnjecteerd door een interface, wordt deze correct aangesloten. Als de bean echter wordt geïnjecteerd door de werkelijke klasse, zal Spring geen bean-definitie vinden die overeenkomt met de klasse - aangezien de proxy dat niet doet breid de klas uit.

Een veel voorkomende reden waarom de boon proxy kan zijn, is de Transactionele ondersteuning in de lente - namelijk bonen die zijn geannoteerd met @Transactional.

Als Service A. injecteert Service B., en beide services zijn transactionele, injecteren volgens de klassendefinitie zal niet werken:

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

Dezelfde twee services, dit keer correct injecteren door de interface, zal goed komen:

@Service @Transactional openbare klasse ServiceA implementeert IServiceA {@Autowired privé IServiceB serviceB; ...} @Service @Transactional public class ServiceB implementeert IServiceB {...}

7. Conclusie

In deze tutorial werden voorbeelden besproken van de mogelijke oorzaken van de common NoSuchBeanDefinitionException - met de nadruk op hoe deze uitzonderingen in de praktijk kunnen worden aangepakt.

De implementatie van al deze uitzonderingsvoorbeelden is te vinden in het GitHub-project - dit is een op Eclipse gebaseerd project, dus het moet gemakkelijk te importeren en uit te voeren zijn zoals het is.

Tenslotte, de volledige lijst met uitzonderingen en oplossingen in het voorjaar is misschien een goede bron om te bookmarken.


$config[zx-auto] not found$config[zx-overlay] not found