Spring @Import Annotation
1. Oversigt
I denne vejledning lærer vi hvordan man bruger foråret @Importere kommentar, mens du afklarer, hvordan den adskiller sig fra @ComponentScan.
2. Konfiguration og bønner
Før du forstår @Importere bemærkning, vi skal vide, hvad en Spring Bean er, og have en grundlæggende viden om @Konfiguration kommentar.
Begge emner er uden for denne tutorials omfang. Alligevel kan vi lære om dem i vores Spring Bean-artikel og i Spring-dokumentationen.
Lad os antage, at vi allerede har forberedt os tre bønner - Fugl, Katog Hund - hver med sin egen konfigurationsklasse.
Så kan vi give vores sammenhæng med disse Konfig klasser:
@ExtendWith (SpringExtension.class) @ContextConfiguration (klasser = {BirdConfig.class, CatConfig.class, DogConfig.class}) klasse ConfigUnitTest {@Autowired ApplicationContext kontekst; @Test ugyldigt givenImportedBeans_whenGettingEach_shallFindIt () {assertThatBeanExists ("hund", Dog.class); assertThatBeanExists ("kat", kat.klasse); assertThatBeanExists ("fugl", Bird.class); } privat ugyldighed assertThatBeanExists (String beanName, Class beanClass) {Assertions.assertTrue (context.containsBean (beanName)); Assertions.assertNotNull (context.getBean (beanClass)); }}
3. Gruppering af konfigurationer med @Importere
Der er ikke noget problem med at erklære alle konfigurationer. Men forestil dig besværet med at kontrollere snesevis af konfigurationsklasser inden for forskellige kilder. Der burde være en bedre måde.
Det @Importere annotering har en løsning ved dens evne til at gruppere Konfiguration klasser:
@Configuration @Import ({DogConfig.class, CatConfig.class}) klasse MammalConfiguration {}
Nu skal vi bare huske pattedyr:
@ExtendWith (SpringExtension.class) @ContextConfiguration (klasser = {MammalConfiguration.class}) klasse ConfigUnitTest {@Autowired ApplicationContext kontekst; @Test ugyldigt givenImportedBeans_whenGettingEach_shallFindOnlyTheImportedBeans () {assertThatBeanExists ("hund", Dog.class); assertThatBeanExists ("kat", kat.klasse); Assertions.assertFalse (context.containsBean ("fugl")); } privat ugyldighed assertThatBeanExists (String beanName, Class beanClass) {Assertions.assertTrue (context.containsBean (beanName)); Assertions.assertNotNull (context.getBean (beanClass)); }}
Vi glemmer sandsynligvis vores Fugl snart, så lad os gøre en gruppe mere til at inkludere alle dyr konfigurationsklasser:
@Configuration @Import ({MammalConfiguration.class, BirdConfig.class}) klasse AnimalConfiguration {}
Endelig blev ingen efterladt, og vi skal bare huske en klasse:
@ExtendWith (SpringExtension.class) @ContextConfiguration (klasser = {AnimalConfiguration.class}) klasse AnimalConfigUnitTest {// samme test, der bekræfter, at alle bønner er tilgængelige i konteksten}
4. @Importere vs. @ComponentScan
Inden du fortsætter med @Importere eksempler, lad os stoppe hurtigt og sammenligne det med @ComponentScan.
4.1. Ligheder
Begge kommentarer kan accepter nogen @Komponent eller @Konfiguration klasse.
Lad os tilføje en ny @Komponent ved brug af @Importere:
@Configuration @Import (Bug.class) klasse BugConfig {} @Component (value = "bug") klasse Bug {}
Nu, den Insekt bønne fås ligesom enhver anden bønne.
4.2. Konceptuel forskel
Kort sagt, vi kan nå det samme resultat med begge kommentarer. Så er der nogen forskel mellem dem?
For at besvare dette spørgsmål, lad os huske, at Spring generelt fremmer fremgangsmåden med konvention-over-konfiguration.
At lave en analogi med vores kommentarer, @ComponentScan er mere som konvention, mens @Importere ligner konfiguration .
4.3. Hvad der sker i rigtige applikationer
Vi starter typisk vores applikationer ved brug af @ComponentScan i en rodpakke så det kan finde alle komponenter til os. Hvis vi bruger Spring Boot, så @SpringBootApplication inkluderer allerede @ComponentScan, og vi er gode til at gå. Dette viser konventionens magt.
Lad os forestille os, at vores ansøgning vokser meget. Nu skal vi håndtere bønner fra alle forskellige steder, som komponenter, forskellige pakkestrukturer og moduler bygget af os selv og tredjeparter.
I dette tilfælde risikerer det at starte konflikter om, hvilken bønne der skal bruges, hvis du tilføjer alt i konteksten. Derudover får vi muligvis en langsom opstartstid.
På den anden side, vi ønsker ikke at skrive en @Importere for hver ny komponent fordi det er kontraproduktivt at gøre det.
Tag for eksempel vores dyr. Vi kunne faktisk skjule importen fra konteksterklæringen, men vi skal stadig huske @Importere for hver Konfig klasse.
4.4. Arbejde sammen
Vi kan sigte mod det bedste fra begge verdener. Lad os forestille os, at vi kun har en pakke til vores dyr. Det kan også være en komponent eller et modul og beholde den samme idé.
Så kan vi have en @ComponentScan bare for vores dyr pakke:
pakke com.baeldung.importannotation.animal; // import ... @Configuration @ComponentScan offentlig klasse AnimalScanConfiguration {}
Og en @Importere tilhold kontrol over, hvad vi tilføjer til konteksten:
pakke com.baeldung.importannotation.zoo; // import ... @Configuration @Import (AnimalScanConfiguration.class) klasse ZooApplication {}
Endelig vil enhver ny bønne, der føjes til dyrepakken, automatisk blive fundet i vores sammenhæng. Og vi har stadig eksplicit kontrol over de konfigurationer, vi bruger.
5. Konklusion
I denne hurtige vejledning lærte vi, hvordan man bruger @Importere at organisere vores konfigurationer.
Det lærte vi også @Importere er meget svarende til @ComponentScan, bortset fra det faktum, at @Importere har en eksplicit tilgang, mens @ComponentScan bruger en implicit .
Vi så også på mulige vanskeligheder med at kontrollere vores konfigurationer i rigtige applikationer, og hvordan vi skal håndtere disse ved at kombinere begge kommentarer.
Som sædvanlig er den komplette kode tilgængelig på GitHub.