Tavaszi NoSuchBeanDefinitionException
1. Áttekintés
Ebben a cikkben a Tavaszi org.springframework.beans.factory.NoSuchBeanDefinitionException - ez egy gyakori kivétel, amelyet a BeanFactory amikor megpróbálja megoldani egy bab, amely egyszerűen nincs meghatározva a tavaszi kontextusban.
Bemutatjuk a probléma lehetséges okait és a rendelkezésre álló megoldásokat.
És természetesen akkor történnek kivételek, amikor a legkevésbé számítasz rájuk; vessen egy pillantást a kivételek és megoldások teljes listájára tavasszal.
2. Ok: Nem találtak […] típusú minősítő babot függőség miatt
Ennek a kivételnek a leggyakoribb oka egyszerűen egy nem definiált bab beadása. Például - BeanB beköt egy együttműködőt - BeanA:
@ Component public class BeanA {@Autowired private BeanB dependency; // ...}
Ha a függőség - BeanB - nincs meghatározva a tavaszi kontextusban, a rendszerindítási folyamat sikertelen lesz a nincs ilyen babdefiníció kivétel:
org.springframework.beans.factory.NoSuchBeanDefinitionException: A [com.baeldung.packageB.BeanB] típusú minősítő bab nem található függőségre: várhatóan legalább 1 bab, amely jogosultnak minősül ennek a függőségnek. Függőségi jelölések: {@ org.springframework.beans.factory.annotation.Autowired (kötelező = igaz)}
Az okot Spring egyértelműen jelzi:várhatóan legalább 1 bab, amely e függőség automatikus jelöltjének minősül”
Egy ok BeanB nem létezhet a kontextusban - ha a babot automatikusan felszedi osztályút szkennelés, és ha BeanB helyesen van jelölve babként (@Összetevő, @Raktár, @Szolgáltatás, @Vezérlőstb.) - az, hogy meghatározható egy csomag, amelyet Spring nem vizsgál be:
csomag com.baeldung.packageB; @ Component public class BeanB {...}
Míg az osztályút keresése a következőképpen konfigurálható:
@Configuration @ComponentScan ("com.baeldung.packageA") nyilvános osztály ContextWithJavaConfig {...}
Ha a babot nem automatikusan beolvassa manuálisan definiálva, azután BeanB egyszerűen nincs meghatározva a jelenlegi tavaszi kontextusban.
3. Ok: A […] mezőben a […] mezőben olyan […] típusú babra volt szükség, amely nem található
A fenti forgatókönyv Spring Boot alkalmazásában egy másik üzenetet kapunk.
Vegyük ugyanazt a példát, ahol BeanB be van vezetve BeanA de nincs meghatározva:
@ Component public class BeanA {@Autowired private BeanB dependency; // ...}
Ha megpróbáljuk futtatni ezt az egyszerű alkalmazást, az megpróbál betöltődni BeanA:
@SpringBootApplication public class NoSuchBeanDefinitionDemoApp {public static void main (String [] args) {SpringApplication.run (NoSuchBeanDefinitionDemoApp.class, args); }}
Az alkalmazás nem indul el a hibaüzenettel:
************************************************************************************************************************************* ******** Leírás: A mezőfüggőség a com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA mezőben megkövetelte a 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' típusú babot, amely nem található. Művelet: Fontolja meg a konfigurációban a „com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB” típusú bab definiálását.
Itt, com.baeldung.springbootmvc.nosuchbeandefinitionexception a csomag a BeanA, BeanB és NoSuchBeanDefinitionDemoApp.
A példa kivonata ebben a Github projektben található.
4. Ok: Nincs meghatározva a […] típusú minősítő bab
A kivétel másik oka az, hogy két babdefiníció létezik a kontextusban, egy helyett. Például, ha egy interfész - IBeanB két bab hajtja végre - BabB1 és BabB2:
@Bomponent public class BeanB1 implementál IBeanB {//} @Component public class BeanB2 implementates IBeanB {//}
Most ha BeanA automatikusan bekapcsolja ezt a felületet, Spring nem fogja tudni, hogy a két megvalósítás közül melyiket kell injektálnia:
@ Component public class BeanA {@Autowired private IBeanB dependency; ...}
És ez megint azt eredményezi, hogy a NoSuchBeanDefinitionException hogy dobja a BeanFactory:
Okozta: org.springframework.beans.factory.NoUniqueBeanDefinitionException: Nincs meghatározva [com.baeldung.packageB.IBeanB] típusú bab: várható egyetlen egyező bab, de 2 talált: beanB1, beanB2
Hasonlóképpen, a Spring egyértelműen jelzi a vezeték meghibásodásának okát: „Várható egyező bab, de találtak 2-et”.
Figyelje meg azonban, hogy ebben az esetben a kivetett pontos kivétel nem az NoSuchBeanDefinitionException hanem egy alosztály - a NoUniqueBeanDefinitionException. Ezt az új kivételt a 3.2.1. Tavasszal vezették be pontosan ezen okból - annak érdekében, hogy különbséget tegyenek az ok között, ahol nem találtak babdefiníciót, és ezektől -, ahol több definíció található az összefüggésben.
E változás előtt a fenti kivétel a következő volt:
Okozta: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nincs meghatározva egy [com.baeldung.packageB.IBeanB] típusú bab: várható egyetlen egyező bab, de 2 talált: beanB1, beanB2
Egy megoldás erre a problémára a @ Minősítő annotáció hogy pontosan meghatározzuk annak a babnak a nevét, amelyet be akarunk kapcsolni:
@ Component public class BeanA {@Autowired @Qualifier ("beanB2") private IBeanB dependency; ...}
Most tavasszal elegendő információ áll rendelkezésre ahhoz, hogy eldöntse, melyik babot adja be - BabB1 vagy BabB2 (alapértelmezett neve BabB2 van babB2).
5. Ok: Nincs meghatározva a […] nevű bab
A NoSuchBeanDefinitionException akkor is dobható, ha a nem definiált bab név szerint kérik a tavaszi kontextusból:
@Component public class BeanA megvalósítja az InitializingBean {@Autowired private ApplicationContext kontextust; @Orride public void afterPropertiesSet () {context.getBean ("someBeanName"); }}
Ebben az esetben nincs babdefiníció a „someBeanName” kifejezésre, ami a következő kivételhez vezet:
Okozta: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nincs meghatározva a „someBeanName” nevű bab.
Tavasz ismét egyértelműen és tömören jelzi a kudarc okát: „Nincs meghatározva X nevű bab“.
6. Ok: Közeli bab
Ha a kontextusban lévő babot a JDK Dynamic Proxy mechanizmus segítségével proxybe helyezi, akkor a proxy nem fogja meghosszabbítani a cél babot (ugyanakkor ugyanazokat az interfészeket fogja megvalósítani).
Emiatt, ha a babot egy interfész injektálja, akkor azt megfelelően bekötik. Ha azonban a babot a tényleges osztály injektálja, akkor Spring nem találja az osztálynak megfelelő babdefiníciót - mivel a proxy valójában nem kiterjessze az osztályt.
Nagyon gyakori oka, hogy a bab meghatalmazottja a Tavaszi tranzakciós támogatás - mégpedig olyan babok, amelyekkel fel van jegyezve @ Tranzakció.
Például, ha SzolgáltatásA injektál SzolgáltatásB, és mindkét szolgáltatás tranzakciós, injekció az osztálydefiníció szerint nem fog működni:
@Service @Transactional public class ServiceA valósítja meg az IServiceA {@Autowired private ServiceB serviceB szolgáltatást; ...} @Service @Transactional nyilvános osztály A ServiceB megvalósítja az IServiceB szolgáltatást {...}
Ugyanaz a két szolgáltatás, ezúttal helyesen injekció az interfészen keresztül, rendben lesz:
@Service @Transactional public class ServiceA megvalósítja az IServiceA {@Autowired private IServiceB serviceB szolgáltatást; ...} @Service @Transactional nyilvános osztály A ServiceB megvalósítja az IServiceB szolgáltatást {...}
7. Következtetés
Ez az oktatóanyag bemutatta a közös ok lehetséges példáit NoSuchBeanDefinitionException - arra összpontosítva, hogy ezeket a kivételeket hogyan lehet a gyakorlatban kezelni.
Mindezen kivételi példák megvalósítása megtalálható a GitHub projektben - ez egy Eclipse alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.
Végül, a kivételek és megoldások teljes listája tavasszal jó forrás lehet a könyvjelzők megjelölésére.