SpringBoot启动过程
核心组件:
● Application Events and Listeners
ApplicationContextInitializer
ApplicationListener
SpringApplicationRunListener
● ApplicationRunner 与 CommandLineRunner
1、创建 SpringApplication
判断当前应用程序类型是servlet还是响应式编程
bootstrapRegistryInitializers:初始启动引导器(List),去spring.factories文件中找 org.springframework.boot.Bootstrappe
initializers:初始化器(List<ApplicationContextInitializer<?>>),去spring.factories找 ApplicationContextInitializer
listeners:应用监听器(List<ApplicationListener<?>>),去spring.factories找 ApplicationListener
2、运行 SpringApplication的run方法
创建引导上下文(Context环境),获取到所有之前的 bootstrapRegistryInitializers挨个执行 intitialize() 来完成对引导启动器上下文环境设置
获取所有 RunListener(运行监听器),去spring.factories找 SpringApplicationRunListener.
准备环境
调用prepareEnvironment()方法
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
//返回或者创建基础环境信息对象。StandardServletEnvironment
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
//配置环境信息对象,读取所有的配置源的配置属性值。
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
//绑定环境信息
ConfigurationPropertySources.attach((Environment)environment);
//监听器调用 listener.environmentPrepared(),通知所有的监听器当前环境准备完成
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = this.convertEnvironment((ConfigurableEnvironment)environment);
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
通过createApplicationContext()方法创建IOC容器(),它会根据项目类型(Servlet)创建对应的容器(AnnotationConfigServletWebServerApplicationContext)。
通过prepareContext()会准备ApplicationContext IOC容器的基本信息
● IOC容器的后置处理流程。
● 遍历所有的 ApplicationContextInitializer 。调用 initialize.。来对ioc容器进行初始化扩展功能
● 遍历所有的 listener 调用 contextPrepared。EventPublishRunListenr;通知所有的监听器contextPrepared
所有的监听器 调用 contextLoaded。通知所有的监听器 contextLoaded;
核心代码,通过refreshContext()
方法刷新IOC容器。 创建容器中的所有组件
(Spring注解)。
通过callRunners()方法调用所有runners
获取容器中的 ApplicationRunner 和CommandLineRunner
遍历所有的runner。调用 run 方法
调用所有监听器的 ready()方法 , 通知所有的监听器程序正在运行。
自定义监听事件组件
1、编写核心组件类
MyApplicationContextInitializer
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("MyApplicationContextInitializer.class...initialize()");
}
}
MyApplicationListener
public class MyApplicationListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("MyApplicationListener.class...onApplicationEvent()");
}
}
MySpringApplicationRunListener
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
private final SpringApplication application;
public MySpringApplicationRunListener(SpringApplication application, String[] args) {
this.application = application;
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("MySpringApplicationRunListener.class...starting()");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("MySpringApplicationRunListener.class...environmentPrepared()");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener.class...contextPrepared()");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("MySpringApplicationRunListener.class...contextLoaded()");
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("MySpringApplicationRunListener.class...started()");
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("MySpringApplicationRunListener.class...ready()");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("MySpringApplicationRunListener.class...failed()");
}
}
2、把两个runner加入到容器中,可以按照@Order进行排序
MyApplicationRunner
@Order(2)
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("MyApplicationRunner.class...run()");
}
}
MyCommandLineRunner
@Order(1)
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner.class...run()");
}
}
3、编写配置文件
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
com.example.demo.listen.MyApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
com.example.demo.listen.MyApplicationListener
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
com.example.demo.listen.MySpringApplicationRunListener