Guide til å kjøre logikk ved oppstart våren
1. Introduksjon
I denne artikkelen vil vi fokusere på hvordan du gjør det kjør logikk ved oppstart av en Spring-applikasjon.
2. Kjører logikk ved oppstart
Å kjøre logikk under / etter oppstarten av Spring-applikasjonen er et vanlig scenario, men en som forårsaker flere problemer.
For å dra nytte av Inverse of Control, må vi naturlig gi avkall på delvis kontroll over applikasjonens flyt til beholderen - det er grunnen til at instantiering, oppsettlogikk ved oppstart osv. Trenger spesiell oppmerksomhet.
Vi kan ikke bare inkludere logikken vår i bønnenes konstruktører eller anropsmetoder etter instantiering av noe objekt; vi har rett og slett ikke kontroll under disse prosessene.
La oss se på det virkelige eksemplet:
@Komponent offentlig klasse InvalidInitExampleBean {@Autowired private Environment env; public InvalidInitExampleBean () {env.getActiveProfiles (); }}
Her prøver vi å få tilgang til en autotråd felt i konstruktøren. Når konstruktøren kalles, er ikke vårbønnen ennå fullstendig initialisert. Dette er problematisk fordi å ringe ennå ikke initialiserte felt vil selvfølgelig resultere i NullPointerExceptions.
Våren gir oss noen måter å håndtere denne situasjonen på.
2.1. De @PostConstruct Kommentar
Javax's @PostConstruct kommentar kan brukes til å kommentere en metode som skal kjøres en gang umiddelbart etter bønnens initialisering. Husk at den merkede metoden vil bli utført av Spring, selv om det ikke er noe å injisere.
Her er @PostConstruct i aksjon:
@Component public class PostConstructExampleBean {private static final Logger LOG = Logger.getLogger (PostConstructExampleBean.class); @Autowired private Environment miljø; @PostConstruct public void init () {LOG.info (Arrays.asList (environment.getDefaultProfiles ())); }}
I eksemplet ovenfor kan du se at Miljø tilfellet ble trygt injisert og deretter kalt inn @PostConstruct kommentert metode uten å kaste a NullPointerException.
2.2. De InitialisererBønne Grensesnitt
De InitialisererBønne tilnærming fungerer ganske likt den forrige. I stedet for å kommentere en metode, må du implementere InitialisererBønne grensesnitt og afterPropertiesSet () metode.
Her kan du se forrige eksempel implementert ved hjelp av InitialisererBønne grensesnitt:
@Component public class InitializingBeanExampleBean implementerer InitializingBean {private static final Logger LOG = Logger.getLogger (InitializingBeanExampleBean.class); @Autowired private Environment miljø; @Override public void afterPropertiesSet () kaster unntak {LOG.info (Arrays.asList (environment.getDefaultProfiles ())); }}
2.3. An ApplicationListener
Denne tilnærmingen kan brukes til kjører logikk etter at vårkonteksten er initialisert, så vi fokuserer ikke på noen spesiell bønne, men venter på at alle skal initialiseres.
For å oppnå dette må du lage en bønne som implementerer ApplicationListener grensesnitt:
@Komponent offentlig klasse StartupApplicationListenerExample implementerer ApplicationListener {privat statisk slutt Logger LOG = Logger.getLogger (StartupApplicationListenerExample.class); offentlig statisk teller; @Override public void onApplicationEvent (ContextRefreshedEvent event) {LOG.info ("Increment counter"); teller ++; }}
De samme resultatene kan oppnås ved å bruke den nylig introduserte @EventListener kommentar:
@Component public class EventListenerExampleBean {private static final Logger LOG = Logger.getLogger (EventListenerExampleBean.class); offentlig statisk teller; @EventListener offentlig tomrom påApplicationEvent (ContextRefreshedEvent event) {LOG.info ("Increment counter"); teller ++; }}
I dette eksemplet valgte vi ContextRefreshedEvent. Sørg for å velge et passende arrangement som passer dine behov.
2.4. De @Bønne Initmethod Attribute
De initMethod egenskap kan brukes til å utføre en metode etter initialisering av en bønne.
Slik ser en bønne ut:
public class InitMethodExampleBean {private static final Logger LOG = Logger.getLogger (InitMethodExampleBean.class); @Autowired private Environment miljø; offentlig ugyldig init () {LOG.info (Arrays.asList (environment.getDefaultProfiles ())); }}
Du kan legge merke til at det ikke er implementert spesielle grensesnitt eller spesielle merknader.
Deretter kan vi definere bønnen ved hjelp av @Bønne kommentar:
@Bean (initMethod = "init") offentlig InitMethodExampleBean initMethodExampleBean () {returner ny InitMethodExampleBean (); }
Og slik ser en bønnedefinisjon ut i en XML-konfigurasjon:
2.5. Constructor Injection
Hvis du injiserer felt ved hjelp av Constructor Injection, kan du ganske enkelt inkludere logikken din i en konstruktør:
@Component public class LogicInConstructorExampleBean {private static final Logger LOG = Logger.getLogger (LogicInConstructorExampleBean.class); privat slutt Miljømiljø; @Autowired offentlig LogicInConstructorExampleBean (miljømiljø) {this.environment = miljø; LOG.info (Arrays.asList (environment.getDefaultProfiles ())); }}
2.6. Vårstøvel CommandLineRunner
Vårstøvel gir en CommandLineRunner grensesnitt med tilbakeringing løpe() metode som kan påkalles ved oppstart av applikasjonen etter at vårapplikasjonskonteksten er instantiert.
La oss se på et eksempel:
@Component offentlig klasse CommandLineAppStartupRunner implementerer CommandLineRunner {privat statisk slutt Logger LOG = LoggerFactory.getLogger (CommandLineAppStartupRunner.class); offentlig statisk teller; @ Override public void run (String ... args) kaster unntak {LOG.info ("Increment counter"); teller ++; }}
Merk: Som nevnt i dokumentasjonen, flere CommandLineRunner bønner kan defineres i samme applikasjonskontekst og kan bestilles ved hjelp av @Bestilt grensesnitt eller @Rekkefølge kommentar.
2.7. Vårstøvel ApplicationRunner
Lik CommandLineRunner, Vårstøvel gir også en ApplicationRunner grensesnitt med en løpe() metoden som skal påberopes ved oppstart av applikasjonen. Imidlertid i stedet for rå String argumenter overført til tilbakeringingsmetoden, har vi en forekomst av SøknadArgumenter klasse.
De SøknadArgumenter grensesnittet har metoder for å få argumentverdier som er alternativer og vanlige argumentverdier. Et argument som er foran - - er et alternativargument.
La oss se på et eksempel:
@Component offentlig klasse AppStartupRunner implementerer ApplicationRunner {private static final Logger LOG = LoggerFactory.getLogger (AppStartupRunner.class); offentlig statisk teller; @Override public void run (ApplicationArguments args) kaster Unntak {LOG.info ("Application started with option names: {}", args.getOptionNames ()); LOG.info ("Inkrement counter"); teller ++; }}
3. Kombinere mekanismer
For å oppnå full kontroll over bønnene dine, vil du kanskje kombinere de ovennevnte mekanismene sammen.
Rekkefølgen er som følger:
- Konstruktøren
- de @PostConstruct merkede metoder
- InitializingBean's afterPropertiesSet () metode
- initialiseringsmetoden spesifisert som init-metode i XML
La oss lage en vårbønne som kombinerer alle mekanismer:
@Component @Scope (value = "prototype") offentlig klasse AllStrategiesExampleBean implementerer InitializingBean {private static final Logger LOG = Logger.getLogger (AllStrategiesExampleBean.class); offentlig AllStrategiesExampleBean () {LOG.info ("Constructor"); } @Override public void afterPropertiesSet () kaster unntak {LOG.info ("InitializingBean"); } @ PostConstruct offentlig ugyldig postConstruct () {LOG.info ("PostConstruct"); } offentlig ugyldig init () {LOG.info ("init-metode"); }}
Hvis du prøver å instantiere denne bønnen, vil du kunne se logger som samsvarer med rekkefølgen spesifisert ovenfor:
[main] INFO o.b.startup.AllStrategiesExampleBean - Constructor [main] INFO o.b.startup.AllStrategiesExampleBean - PostConstruct [main] INFO o.b.startup.AllStrategiesExampleBean - InitializingBean [main] INFO o.b.startup.AllStrateg
4. Konklusjon
I denne artikkelen illustrerte vi flere måter å utføre logikk på når Spring starter applikasjonen.
Kodeeksempler finner du på GitHub.