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:

  1. Konstruktøren
  2. de @PostConstruct merkede metoder
  3. InitializingBean's afterPropertiesSet () metode
  4. 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.