Jarná výnimka NoSuchBeanDefinitionException
1. Prehľad
V tomto článku diskutujeme o Jar org.springframework.beans.factory.NoSuchBeanDefinitionException - toto je bežná výnimka vyvolaná BeanFactory pri pokuse o vyriešenie fazuľa, ktorá jednoducho nie je definovaná v kontexte jari.
Ukážeme možné príčiny tohto problému a dostupné riešenia.
A samozrejme, výnimky sa stávajú, keď to najmenej čakáte; na jar sa pozrite na celý zoznam výnimiek a riešení.
2. Príčina: Pre závislosť sa nenašiel žiadny kvalifikačný znak typu […]
Najbežnejšou príčinou tejto výnimky je jednoducho pokus o injekciu fazule, ktorá nie je definovaná. Napríklad - BeanB zapojí spolupracovníka - BeanA:
@ Komponent verejná trieda BeanA {@Autowired súkromná závislosť BeanB; // ...}
Teraz, ak závislosť - BeanB - nie je definovaný v jarnom kontexte, bootstrap proces zlyhá s žiadna taká výnimka z definície fazule:
org.springframework.beans.factory.NoSuchBeanDefinitionException: Pre závislosť sa nenašiel žiadny kvalifikačný fazuľa typu [com.baeldung.packageB.BeanB]: očakáva sa minimálne 1 fazuľa, ktorá sa kvalifikuje ako kandidát autowire pre túto závislosť. Poznámky k závislosti: {@ org.springframework.beans.factory.annotation.Autowired (required = true)}
Dôvod jasne naznačuje jar: „očakáva sa minimálne 1 fazuľa, ktorá sa kvalifikuje ako kandidát autowire pre túto závislosť”
Jeden dôvod BeanB nemusí v tomto kontexte existovať - ak fazuľa vyberá automaticky skenovanie triedy, A keď BeanB je správne anotovaný ako fazuľa (@ Komponent, @Úložisko, @Služba, @ Kontrolór, atď.) - je, že to môže byť definované v balík, ktorý Spring neskenuje:
balíček com.baeldung.packageB; @ Komponent verejnej triedy BeanB {...}
Zatiaľ čo skenovanie cesty k triede je možné nakonfigurovať nasledovne:
@Configuration @ComponentScan ("com.baeldung.packageA") verejná trieda ContextWithJavaConfig {...}
Ak fazuľa nie je automaticky skenovaná podľa definované manuálnepotom BeanB v súčasnom jarnom kontexte jednoducho nie je definovaný.
3. Príčina: Pole […] v poli […] vyžadovalo fazuľu typu […], ktorú nebolo možné nájsť
V aplikácii Spring Boot pre vyššie uvedený scenár dostaneme inú správu.
Zoberme si rovnaký príklad, kde BeanB je zapojený v BeanA ale nie je to definované:
@ Komponent verejná trieda BeanA {@Autowired súkromná závislosť BeanB; // ...}
Ak sa pokúsime spustiť túto jednoduchú aplikáciu, ktorá sa pokúsi načítať BeanA:
@SpringBootApplication verejná trieda NoSuchBeanDefinitionDemoApp {public static void main (String [] args) {SpringApplication.run (NoSuchBeanDefinitionDemoApp.class, args); }}
Aplikáciu sa nepodarí spustiť s chybovým hlásením:
**************************** APLIKÁCIA SA SPUSTILA ******************* ******** Popis: Závislosť poľa v com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA vyžadovala fazuľu typu 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB', ktorú nemožno nájsť. Akcia: Zvážte vo svojej konfigurácii definíciu fazule typu „com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB“.
Tu, com.baeldung.springbootmvc.nosuchbeandefinitionexception je balík pre BeanA, BeanB a NoSuchBeanDefinitionDemoApp.
Útržok tohto príkladu nájdete v tomto projekte Github.
4. Príčina: Nie je definovaný žiadny kvalifikačný znak typu […]
Ďalšou príčinou výnimky je existencia dvoch definícií fazule v kontexte, namiesto jednej. Napríklad, ak rozhranie - IBeanB je implementovaný dvoma fazuľami - BeanB1 a BeanB2:
@ Verejná trieda komponentu BeanB1 implementuje IBeanB {//} @ Verejná trieda komponentu BeanB2 implementuje IBeanB {//}
Teraz, ak BeanA autowires toto rozhranie, Spring nebude vedieť, ktorú z dvoch implementácií vložiť:
@ Komponent public class BeanA {@Autowired súkromná závislosť IBeanB; ...}
Výsledkom bude opäť a NoSuchBeanDefinitionException je vyhodený BeanFactory:
Spôsobené: org.springframework.beans.factory.NoUniqueBeanDefinitionException: Nie je definovaný žiadny kvalifikačný fazuľa typu [com.baeldung.packageB.IBeanB]: očakáva sa jedno vyhovujúca fazuľa, ale našla sa 2: beanB1, beanB2
Podobne Spring jasne naznačuje dôvod poruchy vedenia: „Očakávaný jeden zodpovedajúci fazuľa, ale našiel sa 2“.
Všimnite si však, že v takom prípade presná výnimka nie je hodená NoSuchBeanDefinitionException ale podtrieda - the NoUniqueBeanDefinitionException. Táto nová výnimka bola zavedená na jar 3.2.1, a to práve z tohto dôvodu - aby sa rozlíšila príčina, pri ktorej sa nenašla definícia fazule, a táto - v kontexte sa nachádza niekoľko definícií.
Pred touto zmenou bola vyššie uvedená výnimka:
Spôsobené: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nie je definovaný žiadny kvalifikovaný fazuľa typu [com.baeldung.packageB.IBeanB]: očakáva sa, že sa zhoduje jedna fazuľa, ale našla sa 2: beanB1, beanB2
Jeden riešením tohto problému je použitie @Qualifier anotácia presne určiť názov fazule, ktorú chceme spojiť:
@Component public class BeanA {@Autowired @Qualifier ("beanB2") súkromná závislosť IBeanB; ...}
Teraz má jar dostatok informácií na to, aby sa rozhodlo, ktorej fazuľke podať injekciu - BeanB1 alebo BeanB2 (predvolený názov BeanB2 je beanB2).
5. Príčina: Nie je definovaný žiadny fazuľa s názvom [...]
A NoSuchBeanDefinitionException sa môže hodiť, aj keď fazuľa, ktorá nie je definovaná, je požadované podľa mena z jarného kontextu:
@ Komponenta verejná trieda BeanA implementuje InitializingBean {@Autowired súkromný kontext ApplicationContext; @Override public void afterPropertiesSet () {context.getBean ("someBeanName"); }}
V tomto prípade neexistuje definícia fazule pre názov „someBeanName“, čo vedie k nasledujúcej výnimke:
Spôsobené: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nie je definovaná žiadna fazuľa s názvom „someBeanName“
Jar opäť jasne a výstižne naznačuje dôvod neúspechu: „Nie je definovaná žiadna fazuľa s názvom X“.
6. Príčina: Proxy fazuľa
Keď je fazuľa v kontexte proxyovaná pomocou mechanizmu JDK Dynamic Proxy, potom server proxy nerozšíri cieľový fazuľa (bude však implementovať rovnaké rozhrania).
Z tohto dôvodu, ak je fazuľa vložená rozhraním, bude správne zapojená. Ak je však fazuľa vložená skutočnou triedou, potom Spring nenájde definíciu fazule, ktorá by zodpovedala triede - pretože proxy server v skutočnosti rozšíriť triedu.
Veľmi častým dôvodom, prečo môže byť fazuľa splnomocnená, je Jarná transakčná podpora - a to fazuľa, ktorá je označená @ Transakčné.
Napríklad ak SlužbaA vstrekuje Služba B.a obe služby sú transakčné, vstrekovanie podľa definície triedy nebudem pracovať:
@Service @Transactional public class ServiceA implementuje IServiceA {@Autowired private ServiceB serviceB; ...} @Service @Transactional public class ServiceB implementuje IServiceB {...}
Rovnaké dve služby, tentokrát správne vstrekovanie rozhraním, bude ok:
@Service @Transactional public class ServiceA implementuje IServiceA {@Autowired private IServiceB serviceB; ...} @Service @Transactional public class ServiceB implementuje IServiceB {...}
7. Záver
V tomto výučbe sa diskutovalo o príkladoch možných príčin spoločného výskytu NoSuchBeanDefinitionException - so zameraním na to, ako tieto výnimky v praxi riešiť.
Implementáciu všetkých týchto príkladov výnimiek nájdete v projekte GitHub - jedná sa o projekt založený na Eclipse, takže by malo byť ľahké ho importovať a spustiť tak, ako je.
Nakoniec celý zoznam výnimiek a riešení na jar môže byť dobrým zdrojom na uloženie záložiek.