簡體   English   中英

Spring Controller中的init方法(注釋版)

[英]Init method in Spring Controller (annotation version)

我正在將 controller 轉換為較新的注釋版本。 在舊版本中,我曾經使用以下方法在 springmvc-servlet.xml 中指定 init 方法:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

如何使用注釋版本指定 init 方法?

您可以使用

@PostConstruct
public void init() {
   // ...
}

或者,您可以讓您的類實現InitializingBean接口,以提供一個回調函數( afterPropertiesSet() ),ApplicationContext將在構造bean時調用該函數。

有幾種方法可以攔截Spring中的初始化過程。 如果你必須初始化所有bean並自動裝配/注入它們,我至少有兩種方法可以確保這一點。 我只測試了第二個,但我相信兩個都是一樣的。

如果你正在使用@Bean,你可以通過initMethod引用,就像這樣。

@Configuration
public class BeanConfiguration {

  @Bean(initMethod="init")
  public BeanA beanA() {
    return new BeanA();
  }
}

public class BeanA {

  // method to be initialized after context is ready
  public void init() {
  }

} 

如果您正在使用@Component,可以像這樣使用@EventListener進行注釋。

@Component
public class BeanB {

  @EventListener
  public void onApplicationEvent(ContextRefreshedEvent event) {
  }
}

在我的情況下,我有一個遺留系統,我現在正在使用IoC / DI,其中Spring Boot是選擇框架。 舊系統為表帶來了許多循環依賴,因此我必須使用setter-dependency。 這給了我一些頭痛,因為我無法信任@PostConstruct,因為setter的自動裝配/注射還沒有完成。 順序是構造函數,@ PostConstruct然后是自動裝配的setter。 我用@EventListener注釋解決了這個問題,這個注釋將最后運行並且在所有bean的“相同”時間運行。 該示例顯示了InitializingBean的實現。

我有兩個相互依賴的類(@Component)。 出於本示例的目的,這些類看起來相同,只顯示其中一個。

@Component
public class BeanA implements InitializingBean {
  private BeanB beanB;

  public BeanA() {
    log.debug("Created...");
  }

  @PostConstruct
  private void postConstruct() {
    log.debug("@PostConstruct");
  }

  @Autowired
  public void setBeanB(BeanB beanB) {
    log.debug("@Autowired beanB");
    this.beanB = beanB;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    log.debug("afterPropertiesSet()");
  }

  @EventListener
  public void onApplicationEvent(ContextRefreshedEvent event) {
    log.debug("@EventListener");
  } 
}

這是日志輸出,顯示容器啟動時的調用順序。

2018-11-30 18:29:30.504 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : Created...
2018-11-30 18:29:30.509 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : Created...
2018-11-30 18:29:30.517 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @Autowired beanA
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @PostConstruct
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : afterPropertiesSet()
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @Autowired beanB
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @PostConstruct
2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : afterPropertiesSet()
2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @EventListener
2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @EventListener

如您所見,@ EventListener在一切准備就緒並配置完成后運行。

@PostConstruct、implement InitializingBean、指定init-method他們有調用順序。 所以你不能用它們來代替 init-method。 你可以試試這個:

@Bean(initMethod = "init")
public MyBean mybean() {
    return new MyBean();
}



class MyBean {
public void init() {
    System.out.println("MyBean init");
}

}

在您的 class 中,您可以聲明一個名為 init() 的方法。

參考: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#:~:text=Multiple%20lifecycle%20mechanisms%20configured%20for%20the%20same%20bean% 2C%20with%20different%20initialization%20methods%2C%20are%20called%20as%20follows%3A

public class InitHelloWorld implements BeanPostProcessor {

   public Object postProcessBeforeInitialization(Object bean,
             String beanName) throws BeansException {
       System.out.println("BeforeInitialization : " + beanName);
       return bean;  // you can return any other object as well
   }

   public Object postProcessAfterInitialization(Object bean,
             String beanName) throws BeansException {
       System.out.println("AfterInitialization : " + beanName);
       return bean;  // you can return any other object as well
   }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM