BeanDefinitionOverrideException i Spring Boot

1. Introduktion

Spring Boot 2.1-opgraderingen overraskede flere mennesker med uventede forekomster af BeanDefinitionOverrideException. Det kan forvirre nogle udviklere og få dem til at undre sig over, hvad der skete med bønnens overordnede adfærd i foråret.

I denne vejledning løser vi dette problem op og ser, hvordan vi bedst kan løse det.

2. Maven-afhængigheder

For vores eksempel på Maven-projekt skal vi tilføje Spring Boot Starter-afhængighed:

 org.springframework.boot spring-boot-starter 2.3.3.RELEASE 

3. Bønneoverstyring

Spring bønner identificeres ved deres navne inden for en ApplicationContext.

Dermed, tilsidesættelse af bønner er en standardadfærd, der sker, når vi definerer en bønne inden for en ApplicationContext som har samme navn som en anden bønne. Det fungerer ved blot at erstatte den tidligere bønne i tilfælde af en navnekonflikt.

Fra og med foråret 5.1 BeanDefinitionOverrideException blev introduceret for at give udviklere mulighed for automatisk at smide undtagelsen for at forhindre enhver uventet tilsidesættelse af bønner. Som standard er den oprindelige adfærd stadig tilgængelig, som muliggør tilsidesættelse af bønner.

4. Konfigurationsændring for Spring Boot 2.1

Spring Boot 2.1 deaktiveret bønneoverstyring som standard som en defensiv tilgang. Hovedformålet er at bemærk de duplikerede bønnenavne på forhånd for at forhindre tilsidesættelse af tilsidesatte bønner.

Derfor, hvis vores Spring Boot-applikation er afhængig af tilsidesættelse af bønner, er det meget sandsynligt, at den støder på BeanDefinitionOverrideException efter at vi opgraderer Spring Boot-versionen til 2.1 og nyere.

I de næste sektioner ser vi på et eksempel, hvor BeanDefinitionOverrideException ville forekomme, og så vil vi diskutere nogle løsninger.

5. Identificering af bønner i konflikt

Lad os oprette to forskellige fjederkonfigurationer, hver med en testBean () metode til at producere BeanDefinitionOverrideException:

@Configuration offentlig klasse TestConfiguration1 {klasse TestBean1 {privat strengnavn; // standard getters and setters} @Bean public TestBean1 testBean () {returner ny TestBean1 (); }} 
@Configuration offentlig klasse TestConfiguration2 {klasse TestBean2 {privat strengnavn; // standard getters and setters} @Bean public TestBean2 testBean () {returner ny TestBean2 (); }} 

Dernæst opretter vi vores Spring Boot testklasse:

@RunWith (SpringRunner.class) @SpringBootTest (klasser = {TestConfiguration1.class, TestConfiguration2.class}) offentlig klasse SpringBootBeanDefinitionOverrideExceptionIntegrationTest {@Test offentlig ugyldig, når BeanOverridingAllowed_thenTestBean2OverridesTest_TestBeanBest_Test_Bean2OverridesTest_TestBean2OverridesTest_TestBean2OverreanTestTest_TestBean2OverridesTest assertThat (testBean.getClass ()). er EqualTo (TestConfiguration2.TestBean2.class); }} 

At køre testen giver en BeanDefinitionOverrideException. Undtagelsen giver os dog nogle nyttige oplysninger:

Ugyldig bønnedefinition med navnet 'testBean' defineret i ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2 ... Kan ikke registrere bean definition [... defineret i ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2] for bean 'testBean' ... Der er allerede [... defineret i ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration1] bundet. 

Bemærk, at undtagelsen afslører to vigtige oplysninger.

Den første er det modstridende bønnenavn, testBønne:

Ugyldig bønnedefinition med navnet 'testBean' ... 

Og det andet viser os den fulde sti for de berørte konfigurationer:

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

Som et resultat kan vi se, at to forskellige bønner identificeres som testBønne forårsager en konflikt. Derudover er bønnerne indeholdt i konfigurationsklasser Testkonfiguration 1 og Testkonfiguration2.

6. Mulige løsninger

Afhængigt af vores konfiguration har Spring Beans standardnavne, medmindre vi indstiller dem eksplicit.

Derfor er den første mulige løsning at omdøbe vores bønner.

Der er nogle almindelige måder at indstille bønnenavne om foråret.

6.1. Ændring af metodenavne

Som standard, Spring tager navnet på de bemærkede metoder som bønnenavne.

Derfor, hvis vi har defineret bønner i en konfigurationsklasse, som vores eksempel, så vil det bare forhindre, at du ændrer metodens navne BeanDefinitionOverrideException:

@Bean offentlig TestBean1 testBean1 () {returner ny TestBean1 (); } 
@Bean offentlig TestBean2 testBean2 () {returner ny TestBean2 (); } 

6.2. @Bønne Kommentar

Forårets @Bønne kommentar er en meget almindelig måde at definere en bønne på.

Således er en anden mulighed at indstille navn ejendom af @Bønne kommentar:

@Bean ("testBean1") offentlig TestBean1 testBean () {returner ny TestBean1 (); } 
@Bean ("testBean2") offentlig TestBean1 testBean () {returner ny TestBean2 (); } 

6.3. Stereotype bemærkninger

En anden måde at definere en bønne på er med stereotype kommentarer. Med forårets @ComponentScan funktion aktiveret, kan vi definere vores bønnenavne på klasseniveau ved hjælp af @Komponent kommentar:

@Komponent ("testBean1") klasse TestBean1 {privat strengnavn; // standard getters og setter} 
@Component ("testBean2") klasse TestBean2 {privat strengnavn; // standard getters og setter} 

6.4. Bønner, der kommer fra tredjepartsbiblioteker

I nogle tilfælde, det er muligt at støde på en navnekonflikt forårsaget af bønner, der stammer fra 3. parts fjederstøttede biblioteker.

Når dette sker, skal vi forsøge at identificere, hvilken modstridende bønne der hører til vores applikation, for at afgøre, om nogen af ​​ovenstående løsninger kan bruges.

Men hvis vi ikke er i stand til at ændre nogen af ​​bønnedefinitionerne, kan det være en løsning at konfigurere Spring Boot til at tillade bønneoverstyring.

For at aktivere tilsidesættelse af bønner, lad os indstille spring.main.allow-bean-definition-overriding ejendom til rigtigt i vores application.properties fil:

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

Ved at gøre dette fortæller vi Spring Boot om at tillade tilsidesættelse af bønner uden ændringer i bønnedefinitioner.

Som en sidste meddelelse skal vi være opmærksom på det det er vanskeligt at gætte, hvilken bønne der vil have prioritet, fordi ordren til oprettelse af bønner bestemmes af afhængighedsforhold, der for det meste er påvirket i løbetid. Derfor kan tilladelse af bønne tilsidesættes uventet adfærd, medmindre vi kender afhængighedshierarkiet af vores bønner godt nok.

7. Konklusion

I denne vejledning forklarede vi hvad BeanDefinitionOverrideException betyder i foråret, hvorfor det pludselig vises, og hvordan man adresserer det efter Spring Boot 2.1-opgraderingen.

Som altid kan den komplette kildekode til denne artikel findes på GitHub.


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