springboot版本3.1.4
jdk17
package com.example.demo.config;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import java.time.Duration;
/**
* 自定义应用程序监听器
*/
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("应用程序正在启动");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("环境变量准备完毕");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("ioc容器准备完毕");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("ioc容器加载中");
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("应用程序启动完成,启动耗时:"+timeTaken.getSeconds()+"秒");
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("准备就绪,启动耗时:"+timeTaken.getSeconds()+"秒");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("应用程序启动失败,失败原因:"+exception.getMessage());
}
}
在resources下创建\META-INF\spring.factories
org.springframework.boot.SpringApplicationRunListener=\ com.example.demo.config.MySpringApplicationRunListener
进入源码
在下面的方法中会读取META-INF/spring.factories文件的信息
org.springframework.core.io.support.SpringFactoriesLoader#forDefaultResourceLocation(java.lang.ClassLoader)
进入下面的方法,找到自己的监听器,并进入starting方法
org.springframework.boot.SpringApplication#run(java.lang.String...)
然后进入
org.springframework.boot.SpringApplication#prepareEnvironment
当执行了listeners.environmentPrepared就会进入我们自定义的环境变量准备完毕方法
这个方法就是把配置文件的参数都放入到了环境变量中,但是ioc容器还没有创建
然后进入下面的方法
org.springframework.boot.SpringApplication#prepareContext
当执行了listeners.contextPrepared,就会进入我们自定义的上下文准备完毕方法,也就是ioc容器准备完毕
ioc容器虽然创建好了,但是主配置类没有加载,组件都还没创建
当执行了listeners.contextLoaded,就会进入我们自定义的ioc容器加载中方法
这时候主配置类已经加载进去了,但是ioc容器还没有刷新,就是bean还没有创建
当执行了listeners.started,那么就会进入我们自定义的启动完毕方法
这个时候ioc容器刷新了,也就是创建完成所有的bean,但是runner还没有调用
当ioc容器是已经创建完毕,并且正常运行的,那么调用listeners.ready
就会进入我们自定义的准备就绪方法
这个方法就是ioc容器创建完了所有bean,所有的runner也调用完了
你可以执行你的controller代码进行调用了
我们模拟下项目启动失败,A,B互相引用
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
在项目启动失败的时候,会进入catch的this.handleRunFailure方法,然后进入
进入下面的方法
org.springframework.boot.SpringApplication#handleRunFailure
在这里会调用listeners.failed,然后进入我们自定义的项目启动失败方法
项目启动失败,程序直接结束
runner不明白的,可以参考下面的文章