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.