Proljeće NoSuchBeanDefinitionException

1. Pregled

U ovom članku raspravljamo o Proljeće org.springframework.beans.factory.NoSuchBeanDefinitionException - ovo je uobičajena iznimka koju baca BeanFactory pri pokušaju rješavanja grah koji jednostavno nije definiran u proljetnom kontekstu.

Ilustrirat ćemo moguće uzroke ovog problema i dostupna rješenja.

I naravno, iznimke se događaju kada ih najmanje očekujete; pogledajte puni popis iznimaka i rješenja u proljeće.

2. Uzrok: Nije pronađen kvalificirani grah tipa […] za ovisnost

Najčešći uzrok ove iznimke je jednostavno pokušavanje ubrizgavanja graha koji nije definiran. Na primjer - BeanB ožičenje u suradniku - BeanA:

@Component javna klasa BeanA {@Automobilna privatna ovisnost BeanB-a; // ...}

Sad, ako ovisnost - BeanB - nije definirano u proljetnom kontekstu, postupak pokretanja neće uspjeti s nema takve iznimke definicije graha:

org.springframework.beans.factory.NoSuchBeanDefinitionException: Nije pronađen kvalificirani grah tipa [com.baeldung.packageB.BeanB] za ovisnost: očekuje se najmanje 1 grah koji se kvalificira kao kandidat automatskog povezivanja za ovu ovisnost. Bilješke o ovisnosti: {@ org.springframework.beans.factory.annotation.Autowired (obavezno = true)}

Razlog jasno ukazuje Spring: “očekuje se najmanje 1 grah koji se kvalificira kao kandidat za automatsku ožičenje za ovu ovisnost

Jedan razlog BeanB možda ne postoji u kontekstu - ako grah automatski pokupi skeniranje staze, i ako BeanB je ispravno označeno kao grah (@Komponenta, @ Repozitorij, @Servis, @Controller, itd.) - jest da to može biti definirano u paket koji Proljeće ne skenira:

paket com.baeldung.packageB; @Component javna klasa BeanB {...}

Iako se skeniranje staze može konfigurirati na sljedeći način:

@Configuration @ComponentScan ("com.baeldung.packageA") javna klasa ContextWithJavaConfig {...}

Ako se grah ne automatski automatski skenira definirano ručno, onda BeanB jednostavno nije definiran u trenutnom proljetnom kontekstu.

3. Uzrok: Polje […] u […] Potrebno je zrno tipa […] koje nije bilo moguće pronaći

U aplikaciji Spring Boot za gornji scenarij dobivamo drugačiju poruku.

Uzmimo isti primjer gdje BeanB je ožičen GrahA ali nije definirano:

@Component javna klasa BeanA {@Automobilna privatna ovisnost BeanB-a; // ...}

Ako pokušamo pokrenuti ovu jednostavnu aplikaciju, koja se pokušava učitati GrahA:

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

Aplikacija se neće pokrenuti s porukom o pogrešci:

*************************** PRIJAVA NIJE USPELA ******************* ******** Opis: Ovisnost polja u com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA zahtijevao je grah tipa 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' koji nije moguće pronaći. Akcija: Razmislite o definiranju graha tipa 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' u svojoj konfiguraciji.

Ovdje, com.baeldung.springbootmvc.nosuchbeandefinitionexception je paket za GrahA, BeanB i NoSuchBeanDefinitionDemoApp.

Isječak za ovaj primjer može se naći u ovom Github projektu.

4. Uzrok: Nije definiran kvalificirani grah tipa […]

Drugi uzrok iznimke je postojanje dviju definicija zrna u kontekstu, umjesto jedne. Na primjer, ako sučelje - IBeanB provode dva graha - GrahB1 i GrahB2:

@Component javna klasa BeanB1 implementira IBeanB {//} @Component javna klasa BeanB2 implementira IBeanB {//}

Sad, ako GrahA automatski poveže ovo sučelje, Spring neće znati koju od dvije implementacije ubrizgati:

@Component javna klasa BeanA {@Autowired private IBeanB zavisnost; ...}

I opet, ovo će rezultirati a NoSuchBeanDefinitionException bacajući ih BeanFactory:

Uzrok: org.springframework.beans.factory.NoUniqueBeanDefinitionException: Nije definiran kvalificirani grah tipa [com.baeldung.packageB.IBeanB]: očekuje se jedno podudaranje graha, ali pronađeno 2: beanB1, beanB2

Slično tome, Spring jasno ukazuje na razlog kvara ožičenja: “Očekuje se jedan grah koji se podudara, ali pronađen 2”.

Međutim, primijetite da u ovom slučaju točna izuzetak nije NoSuchBeanDefinitionException ali podrazred - the NoUniqueBeanDefinitionException. Ova nova iznimka uvedena je u proljeće 3.2.1. Upravo iz tog razloga - kako bi se napravila razlika između uzroka kod kojeg nije pronađena definicija zrna i ovog - gdje se u kontekstu nalazi nekoliko definicija.

Prije ove promjene, gornja iznimka bila je:

Uzrok: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nije definiran kvalificirani grah tipa [com.baeldung.packageB.IBeanB]: očekuje se jedno podudaranje graha, ali pronađeno 2: beanB1, beanB2

Jedan rješenje ovog problema je korištenje @Kvalifikator bilješka kako bismo točno odredili naziv graha koji želimo povezati:

@Component javna klasa BeanA {@Autowired @Qualifier ("beanB2") privatna ovisnost o IBeanB-u; ...}

Sad Proljeće ima dovoljno informacija da donese odluku koji zrno treba ubrizgati - GrahB1 ili GrahB2 (zadani naziv GrahB2 je grahB2).

5. Uzrok: Nije definiran grah s imenom […]

A NoSuchBeanDefinitionException također se može baciti kada je grah koji nije definiran traženo po imenu iz proljetnog konteksta:

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

U ovom slučaju, ne postoji definicija graha za „someBeanName“ - što dovodi do sljedeće iznimke:

Uzrok: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nije definiran grah pod nazivom 'someBeanName'

Ponovno, Spring jasno i sažeto ukazuje na razlog neuspjeha: “Nije definiran nijedan grah s imenom X“.

6. Uzrok: grah s profilom

Kada je grah u kontekstu proksiran pomoću mehanizma JDK Dynamic Proxy, tada proxy neće produžiti ciljni grah (međutim, implementirat će ista sučelja).

Zbog toga, ako zrno ubrizgava sučelje, bit će ispravno spojeno. Ako, međutim, zrno ubrizga stvarna klasa, tada Spring neće pronaći definiciju zrna koja odgovara klasi - jer proxy zapravo ne produžiti razred.

Vrlo čest razlog zbog kojeg grah može biti proksiran je Proljetna podrška za transakcije - naime grah koji je označen s @Transational.

Na primjer, ako UslugaA ubrizgava UslugaB, a obje usluge su transakcijske, ubrizgavanje prema definiciji klase neće raditi:

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

Iste dvije usluge, ovaj put ispravno ubrizgavanje putem sučelja, biti će u redu:

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

7. Zaključak

U ovom su vodiču razmatrani primjeri mogućih uzroka zajedničkog NoSuchBeanDefinitionException - s naglaskom na to kako riješiti ove iznimke u praksi.

Primjena svih ovih primjera iznimki može se naći u projektu GitHub - ovo je projekt zasnovan na Eclipseu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.

Konačno, cjelokupni popis iznimaka i rješenja u proljeće bi mogao biti dobar izvor za označavanje.