我将列举其他方法来初始化 bean,我将这些方法分为标准方法和 Spring Boot 方法。
标准方法
-
@PostConstruct: 只是创建bean后触发方法的注解,不允许输入参数。
-
@Bean(init-method="somInitMehotd"):此方法与 Spring bean 生命周期完全相关,在 bean 创建后调用,如果您使用带有 @PostConstruct 注释的其他方法,则将首先调用 @PostConstruct。这种方法不允许输入参数。
-
ApplicationListener:该接口允许监听与上下文生命周期相关的标准事件,也可以监听自定义事件。例如:创建一个类MyAppListener 并实现ApplicationListener<ContextRefreshedEvent> 在这种情况下MyAppListener 将实现一个接收ContextRefreshedEvent 的onApplicationEvent 方法
Spring Boot 方法
运行者:有两个非常有用的接口CommandLineRunner 和ApplicationRunner 在创建ApplicationContext 后都会运行它们都允许注入bean 作为输入参数。
Spring 启动侦听器:Spring 应用程序提供了一些额外的事件,而不是来自应用程序上下文的标准事件。其中一个事件是ApplicationReadyEvent,它在应用程序准备好接收请求时触发。为了侦听此事件,只需使用ApplicationReadyEvent 作为通用实现ApplicationListener。
示例如下:
MyBean 类有不同的方法,上面列出的每种方法都会被调用,每个方法都会调用一个 print 方法,并且该方法有一个 Thread.sleep 以验证调用每个侦听器的顺序。
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<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
contextRefreshedEvent.getApplicationContext().getBean(MyBean.class).contextInit();
}
}
BootListener 将接收来自 Spring 应用程序的 ApplicationReadyEvent。
public class MyBootListener implements ApplicationListener<ApplicationReadyEvent> {
@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调用的。