2017-08-18 16 views
5

Muszę zainicjować fasolę w kontekście Spring po rozpoczęciu mojej aplikacji; Aktualnie zainicjować fasoli w klasie z dopiskiem @Configuration tak:Najlepszy sposób na zainicjowanie fasoli w kontekście Spring po uruchomieniu aplikacji?

@Configuration 
public class AppConfig { 
    @Inject 
    @Bean 
    public BeanA init(param1, param2, etc...) { 
     --- Code to construct bean A --- 
    } 

    @Inject 
    @Bean 
    public BeanB init(param1, param2, etc...) { 
     --- Code to construct bean B --- 
    } 
} 

Ale niektóre ziarna muszę zainicjować po uruchomieniu aplikacji, więc moje podejście jest utworzyć klasę słuchać ApplicationReadyEvent zdarzeń w Spring i wstaw kod do inicjowania fasoli w tej klasie.

@Configuration 
class ApplicationStartingListener implements ApplicationListener<ApplicationReadyEvent>{ 
    ---- Code to init bean here ---- 

    @Override 
    public void onApplicationEvent(ApplicationReadyEvent event) { 
     --- If I put init bean code in here, is it correct? ---- 
    } 
} 

Czy to najlepszy sposób? Czy istnieją inne lepsze rozwiązania?

+0

Spróbuj z @PostConstruct –

+0

@DanielC. Ten błąd występuje, gdy dodaję adnotację PostConstruct: java.lang.IllegalStateException: Adnotacja metody cyklu życia wymaga metody no-arg: –

+0

Istnieją pewne linki, które pomagają osiągnąć pożądane rezultaty. Mam nadzieję, że to pomogłoby. [link1] (http://learningviacode.blogspot.com/2012/07/spring-and-events-and-listeners.html) [link2] (http://www.naturalprogrammer.com/run-code-spring- boot-application-startup /) [link3] (https://stackoverflow.com/questions/38206676/contextstartedevent-not-broadcasted-on-spring-boot) – Tehmina

Odpowiedz

3

Wymienię inne podejścia w celu zainicjowania fasoli, zgrupowałem podejście w podejściu standardowym i wiosennym.

Podejście Standardowe

  1. @PostConstruct: to jest tylko adnotacja, że ​​wywołuje metodę po fasola jest tworzyć, nie pozwala parametrów wejściowych.
  2. @Bean(init-method="somInitMehotd"): To podejście jest całkowicie powiązane z cyklem życia komponentu Spring bean i jest wywoływane po utworzeniu komponentu bean, jeśli używasz innej metody z adnotacją @PostConstruct, wówczas nazwa @PostConstruct zostanie wywołana jako pierwsza. Takie podejście nie pozwala na wprowadzanie parametrów.
  3. ApplicationListener: ten interfejs pozwala na odsłuch standardowych zdarzeń związanych z cyklem życia kontekstu, a także może słuchać dostosowanych zdarzeń. Na przykład tworzyć klasy MyAppListener i realizuje ApplicationListener<ContextRefreshedEvent> w tym przypadku MyAppListener będzie stanowić metodę onApplicationEvent który odbiera podejście ContextRefreshedEvent

Wiosna rozruchu

  1. runners: są dwa bardzo użyteczne interfejsy: oba z nich będą działały po utworzeniu ApplicationContext, a oba z nich pozwalają na wprowadzenie fasoli jako parametrów wejściowych.

  2. Słuchacze rozruchu sprężynowego: aplikacja Spring daje dodatkowe zdarzenia niż zdarzenia standardów, które pochodzą z kontekstu aplikacji. Jednym z wydarzeń jest ApplicationReadyEvent i jest on uruchamiany, gdy aplikacja jest gotowa do odebrania żądania. Aby odsłuchać te zdarzenia, implementuje się jako ApplicationListener przy użyciu standardu ApplicationReadyEvent.

Oto przykład:

MyBean klasa ma różne metody, które będą wywoływane dla każdego podejścia, wymienionych powyżej, każda metoda będzie wywołać metodę drukowania i ta metoda ma Thread.Sleep w celu sprawdzenia kolejność, w której każdy słuchacz jest wywoływany.

import javax.annotation.PostConstruct; 
public class MyBean { 

    private String myVar=""; 

    public MyBean(){ 

    } 

    @PostConstruct 
    public void postConstructInit(){ 

     this.myVar="Post init called"; 
     print(); 

    } 

    public void beanInit(){ 

     this.myVar="Bean init called"; 
     print(); 
    } 

    public void contextInit(){ 

     this.myVar="Context init called"; 
     print(); 
    } 

    public void runnerInit(){ 

     this.myVar="Runner init called"; 
     print(); 
    } 

    public void bootListenerInit(){ 

     this.myVar="Boot init called"; 
     print(); 
    } 



    public void print(){ 
     System.out.println(this.myVar); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Oto klasa ContextRefreshListener że będą słuchać ContextRefreshedEvent i poradzić.

public class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> { 
    @Override 
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { 
     contextRefreshedEvent.getApplicationContext().getBean(MyBean.class).contextInit(); 

    } 
} 

I to jest BootListener że otrzyma ApplicationReadyEvent która pochodzi z wiosennej Aplikacji.

public class MyBootListener implements ApplicationListener<ApplicationReadyEvent> { 
    @Override 
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 
     applicationReadyEvent.getApplicationContext().getBean(MyBean.class).bootListenerInit(); 
    } 
} 

I wreszcie Zastosowanie Wiosna Boot

@SpringBootApplication 
public class StackoverflowBootApplication { 


    public static void main(String[] args) { 

     SpringApplication.run(StackoverflowBootApplication.class, args); 

    } 

    @Bean(name = "myBean", initMethod = "beanInit") 
    public MyBean getMyBean(){ 
     return new MyBean(); 
    } 


    @Bean 
    public ContextRefreshListener getContextRefreshedListener(){return new ContextRefreshListener();} 


    @Bean 
    public MyBootListener getBootListener(){return new MyBootListener();} 

    @Bean 
    public CommandLineRunner getRunner(ApplicationContext ctx){ 
     return (args) -> { 
      ctx.getBean(MyBean.class).runnerInit(); 
     }; 
    } 

} 

Wyjście jest:

Post init called 
Bean init called 
Context init called 
Runner init called 
Boot init called 

Post init called wyjściowy pochodzi z

@PostConstruct 
public void init(){ 
    this.initByPostconstruct="Post init called"; 

Bean init called pochodzi fro m WARTOŚĆ initMethod

@Bean(name = "myBean", initMethod = "beanInit") 
public MyBean getMyBean(){ 
    return new MyBean(); 
} 
} 

Context init called pochodzi ContextRefreshedEvent

public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { 
    contextRefreshedEvent.getApplicationContext().getBean(MyBean.class).contextInit(); 

} 

Runner init called pochodzi CommandLineRunner

@Bean 
public CommandLineRunner getRunner(ApplicationContext ctx){ 
    return (args) -> { 
     ctx.getBean(MyBean.class).runnerInit(); 
    }; 
} 

Boot init called pochodzi ApplicationReadyEvent

public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { 
     applicationReadyEvent.getApplicationContext().getBean(MyBean.class).bootListenerInit(); 
    } 

Wszystkie wymienione scenariusze zostały wywołane przez Spring, nie wywołałem żadnego z wydarzeń bezpośrednio, wszystkie zostały wywołane przez Spring Framework.

+0

Dzięki za wyjaśnienie. –