应用程序启动后在Spring上下文中初始化bean的最佳方法是什么?

我需要在应用程序启动后在Spring上下文中初始化bean; 目前,我使用注释@Configuration在类中初始化bean,如下所示:

@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 --- } } 

但是我需要在应用程序启动后初始化一些bean,所以我的方法是创建一个类,在Spring中监听ApplicationReadyEvent事件,并将代码初始化为该类中的bean。

 @Configuration class ApplicationStartingListener implements ApplicationListener{ ---- Code to init bean here ---- @Override public void onApplicationEvent(ApplicationReadyEvent event) { --- If I put init bean code in here, is it correct? ---- } } 

这是最好的方法吗? 还是有其他更好的解决方案?

我将枚举其他方法以初始化bean,我将方法分为标准方法和Spring Boot方法。

标准方法

  1. @PostConstruct :它只是一个在创建bean后触发方法的注释,它不允许输入参数。
  2. @Bean(init-method="somInitMehotd") :这种方法与Spring bean生命周期完全相关,并且在bean创建之后调用它,如果你使用带有@PostConstruct注释的另一个方法,那么将首先调用@PostConstruct 。 此方法不允许输入参数。
  3. ApplicationListener :此接口允许侦听与Context Lifecycle相关的标准事件,也可以侦听自定义事件。 例如:创建一个类MyAppListener并实现ApplicationListener MyAppListener ApplicationListener在这种情况下, MyAppListener将实现一个接收onApplicationEvent方法

春靴方法

  1. 运行者:有两个非常有用的接口CommandLineRunnerApplicationRunner ,它们都将在创建ApplicationContext后运行,它们都允许将bean作为输入参数注入。

  2. Spring引导侦听器:Spring Application提供了一些额外的事件,而不是来自Application Context的标准事件。 其中一个事件是ApplicationReadyEvent ,当应用程序准备好接收请求时它就会触发。 为了监听此事件,只需使用ApplicationReadyEvent作为通用实现ApplicationListener

这是一个例子:

MyBean类有不同的方法,将为上面列出的每种方法调用,每个方法都会调用一个print方法,并且该方法有一个Thread.sleep,以validation每个监听器的调用顺序。

 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(); } } } 

这是ContextRefreshListener类,它将监听ContextRefreshedEvent并处理它。

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

BootListener将接收来自Spring Application的ApplicationReadyEvent。

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

最后是Spring 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(); }; } } 

输出是:

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

Post init called输出来自

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

Bean init called来自initMethod

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

Context init called来自ContextRefreshedEvent

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

Runner init called来自CommandLineRunner

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

Boot init called来自ApplicationReadyEvent

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

所有列出的场景都是由Spring触发的,我没有直接调用任何事件,所有这些都是由Spring Framework调用的。