BeanDefinitionOverrideException v Spring Boot

1. Úvod

Aktualizácia Spring Boot 2.1 prekvapila niekoľkých ľudí neočakávanými výskytmi BeanDefinitionOverrideException. To môže niektorých vývojárov zmiasť a prinútiť ich zamyslieť sa nad tým, čo sa stalo s prvoradým správaním fazule na jar.

V tomto tutoriáli tento problém rozlúskneme a uvidíme, ako ho najlepšie vyriešiť.

2. Maven závislosti

Pre náš príklad projektu Maven musíme pridať závislosť Spring Boot Starter:

 org.springframework.boot spring-boot-starter 2.3.3. UVOĽNENIE 

3. Prepísanie fazule

Jarné bôby sú identifikované podľa svojich mien v rámci ApplicationContext.

Teda bean overriding je predvolené správanie, ktoré sa stane, keď definujeme fazuľu v rámci ApplicationContext ktorá má rovnaké meno ako iná fazuľa. Funguje to tak, že v prípade konfliktu mien jednoducho nahradíte pôvodnú fazuľu.

Od jari 5.1 BeanDefinitionOverrideException bolo zavedené s cieľom umožniť vývojárom automaticky vyvolať výnimku, aby sa zabránilo neočakávanému prepísaniu fazule. V predvolenom nastavení je pôvodné správanie stále k dispozícii, čo umožňuje prepísanie fazule.

4. Zmena konfigurácie pre Spring Boot 2.1

Spring Boot 2.1 predvolene deaktivoval funkciu fazule ako obranný prístup. Hlavným účelom je vopred si všimnite duplicitné názvy fazule, aby ste zabránili náhodnému prepísaniu fazule.

Preto, ak sa naša aplikácia Spring Boot spolieha na prepísanie fazule, je veľmi pravdepodobné, že narazíte na BeanDefinitionOverrideException po aktualizácii verzie Spring Boot na verziu 2.1 a novšiu.

V ďalších častiach sa pozrieme na príklad, kde BeanDefinitionOverrideException by došlo, a potom prediskutujeme niektoré riešenia.

5. Identifikácia fazule v konflikte

Vytvorme dve rôzne jarné konfigurácie, každú s a testBean () metódou výroby BeanDefinitionOverrideException:

@ Konfigurácia verejná trieda TestConfiguration1 {trieda TestBean1 {súkromný názov reťazca; // štandardní vyhľadávači a nastavovatelia} @Bean public TestBean1 testBean () {vrátiť nový TestBean1 (); }} 
@ Konfigurácia verejná trieda TestConfiguration2 {trieda TestBean2 {súkromný názov reťazca; // štandardní vyhľadávači a nastavovatelia} @Bean public TestBean2 testBean () {vrátiť nový TestBean2 (); }} 

Ďalej vytvoríme našu testovaciu triedu Spring Boot:

@RunWith (SpringRunner.class) @SpringBootTest (classes = {TestConfiguration1.class, TestConfiguration2.class}) verejná trieda SpringBootBeanDefinitionOverrideExceptionIntegrationTest {@Test public void whenBeanOverridingAllowed_thenTestBean2OverridesBest2> assertThat (testBean.getClass ()). isEqualTo (TestConfiguration2.TestBean2.class); }} 

Spustenie testu vytvorí a BeanDefinitionOverrideException. Výnimka nám však poskytuje niekoľko užitočných informácií:

Neplatná definícia fazule s názvom „testBean“ definovaná v ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2 ... Nie je možné zaregistrovať definíciu fazule [... definované v ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2] pre fazuľa 'testBean' ... Už je [... definované v ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration1] viazané. 

Všimnite si, že výnimka odhaľuje dve dôležité informácie.

Prvý je konfliktný názov fazule, testBean:

Neplatná definícia fazule s názvom 'testBean' ... 

A druhý nám ukazuje úplnú cestu ovplyvnených konfigurácií:

... com.baeldung.beandefinitionoverrideexception.TestConfiguration2 ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration1 ... 

Vo výsledku môžeme vidieť, že dve rôzne fazule sú identifikované ako testBean spôsobujúci konflikt. Okrem toho sú fazuľa obsiahnutá vo vnútri konfiguračných tried TestConfiguration1 a TestConfiguration2.

6. Možné riešenia

V závislosti od našej konfigurácie majú Spring Beans predvolené názvy, pokiaľ ich nenastavíme výslovne.

Prvým možným riešením je preto premenovanie našej fazule.

Existuje niekoľko bežných spôsobov, ako nastaviť názvy fazule na jar.

6.1. Zmena názvov metód

Predvolene, Jar berie názvy anotovaných metód ako názvy fazúľ.

Preto, ak máme v konfiguračnej triede definované boby, ako je to v našom príklade, jednoduchá zmena názvov metód zabráni znaku BeanDefinitionOverrideException:

@Bean public TestBean1 testBean1 () {vrátiť nový TestBean1 (); } 
@Bean public TestBean2 testBean2 () {vrátiť nový TestBean2 (); } 

6.2. @Bean Anotácia

Jarné @Bean anotácia je veľmi častý spôsob definovania fazule.

Ďalšou možnosťou je teda nastavenie názov majetok @Bean anotácia:

@Bean ("testBean1") public TestBean1 testBean () {vrátiť nový TestBean1 (); } 
@Bean ("testBean2") public TestBean1 testBean () {vrátiť nový TestBean2 (); } 

6.3. Poznámky o stereotype

Ďalším spôsobom, ako definovať fazuľu, sú stereotypné anotácie. S jarnými @ComponentScan povolená funkcia, môžeme definovať naše názvy fazule na úrovni triedy pomocou @ Komponent anotácia:

@Component ("testBean1") trieda TestBean1 {súkromný názov reťazca; // štandardné getre a setre} 
@Component ("testBean2") trieda TestBean2 {súkromný názov reťazca; // štandardné getre a setre} 

6.4. Fazuľa pochádzajúca z knižníc tretích strán

V niektorých prípadoch, je možné naraziť na konflikt mien spôsobený fazuľami pochádzajúcimi z jarných knižníc tretích strán.

Keď k tomu dôjde, mali by sme sa pokúsiť identifikovať, ktorá konfliktná fazuľa patrí do našej aplikácie, aby sme zistili, či je možné použiť ktorékoľvek z vyššie uvedených riešení.

Ak však nemôžeme zmeniť žiadnu z definícií beanov, riešením môže byť konfigurácia Spring Boot, ktorá umožňuje prepísanie beanov.

Ak chcete povoliť prepísanie fazule, nastavíme spring.main.allow-bean-definícia-prvoradý majetok do pravda v našom application.properties spis:

spring.main.allow-bean-definition-overriding = true 

Týmto povieme Spring Boot, aby umožnil prepísanie fazule bez akejkoľvek zmeny v definíciách fazule.

Na záver by sme si mali byť vedomí je ťažké odhadnúť, ktorá fazuľa bude mať prioritu, pretože poradie vytvorenia fazule je určené vzťahmi závislostí, ktoré sú väčšinou ovplyvnené za behu. Preto povolenie prepísania fazule môže spôsobiť neočakávané správanie, pokiaľ dostatočne nepoznáme hierarchiu závislostí našich fazúľ.

7. Záver

V tomto návode sme vysvetlili, čo BeanDefinitionOverrideException znamená na jar, prečo sa to zrazu objaví a ako to vyriešiť po aktualizácii Spring Boot 2.1.

Kompletný zdrojový kód tohto článku nájdete ako vždy na serveri GitHub.


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