文章目录
- 【README】
- 【1】springboot应用启动主要步骤
- 【1.1】springboot应用启动主要步骤总结
- 【2】springboot应用启动先后发布事件
- 【2.1】springboot启动先后发布事件代码实践
- 【2.1.1】自定义监听器
- 【2.1.2】自定义SpringApplicationRunListener
- 【2.1.3】springboot运行日志
- 【3】补充:springboot自带的spring.factories
【README】
1)本文总结了springboot应用启动主要步骤;
2)springboot应用启动详细分析,参见: springboot应用启动过程源码分析
3)本文使用的springboot版本为3.3.5;
【1】springboot应用启动主要步骤
springboot启动主要步骤概述:
-
step1)new SpringApplication(primarySources): 实例化初始化器与监听器;
- 1.1 数据源=META-INF/spring.factories ,通过反射实例化;
- 1.2 初始化器包括 BootstrapRegistryInitializer实现类,ApplicationContextInitializer实现类,监听器包括ApplicationListener实现类;
-
step2)createBootstrapContext():创建默认启动容器,并使用 BootstrapRegistryInitializer 对其初始化;
- 2.1 类型=DefaultBootstrapContext,
-
step3)SpringApplicationRunListeners listeners = getRunListeners(args): 实例化spring应用运行监听器
- 3.1 数据源=META-INF/spring.factories , 通过反射实例化;
- 3.2 类型=SpringApplicationRunListeners, 初始时只有1个: EventPublishingRunListener
-
stpe4)listeners.starting(bootstrapContext, this.mainApplicationClass):【发布事件:事件名=应用开始启动,事件类型=ApplicationStartingEvent】
- 4.1 调用SpringApplicationRunListeners-starting()方法;订阅者是ApplicationListener监听器;
-
step5)ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, …): 实例化并初始化环境Environment
-
5.1 创建环境实例,类型=ApplicationServletEnvironment
-
5.2 配置环境,包括配置属性,配置profiles
-
5.3 listeners.environmentPrepared(bootstrapContext, environment); 【发布事件: 事件名=环境初始化完成, 事件类型=ApplicationEnvironmentPreparedEvent】
-
5.4 绑定环境实例到SpringApplication
-
5.5 补充:【发布事件: 事件名=环境初始化完成,事件类型=ApplicationEnvironmentPreparedEvent】
-
5.5.1 订阅者是 ApplicationListener 监听器;其中有1个监听器=EnvironmentPostProcessorApplicationListener,接收到环境初始化完成事件后会实例化EnvironmentPostProcessor的实现类(数据源为spring.factories);
-
5.5.2 并调用这些环境PostProcessor的postProcessEnvironment()方法;
-
5.5.3 其中一个EnvironmentPostProcessor是 SystemEnvironmentPropertySourceEnvironmentPostProcessor ,用于做属性变量替换;
-
step6)context = createApplicationContext():创建spring容器;
- 6.1 类型=AnnotationConfigServletWebServerApplicationContext
-
step7) prepareContext(bootstrapContext, context, environment, listeners, …): 初始化容器;
-
7.1 装配environment到context
-
7.2 postProcessApplicationContext(context):后置处理应用容器,包括注册BeanName生成器,设置资源加载器(classpath资源),设置类加载器,设置转换服务;
-
7.3 使用初始化器初始化context,初始化器类型=ApplicationContextInitializer,数据源=META-INF/spring.factories,参见step1;
-
7.4 listeners.contextPrepared(context); 【发布事件: 事件名=容器初始化完成,事件类型=ApplicationContextInitializedEvent】
-
7.5 【发布事件:事件名=启动容器关闭,事件类=BootstrapContextClosedEvent 】
-
7.6 设置BeanFactory允许循环依赖,允许BeanDefinition重写;
-
7.7 添加PropertySourceOrderingBeanFactoryPostProcessor
-
7.8 获取资源列表,并加载BeanDefinition到容器,包括注解类,Resource文件,package资源;
-
7.9 把 ApplicationListener 监听器添加到容器,监听器列表参见step1;
-
7.10 【发布事件: 事件名=应用初始化完成,事件类型=ApplicationPreparedEvent】
-
-
step8) refreshContext(context): 刷新容器
-
8.1 shutdownHook.registerApplicationContext(context): 注册容器关闭钩子; 注册ApplicationContextClosedListener监听器,监听ContextClosedEvent
-
8.2 refresh(context): 刷新容器;大致思想是根据BeanDefinition实例化bean;
-
参见 spring容器启动源码解读 章节【3.1】
-
bean实例化主要步骤总结【非常重要,常见spring面试题】 :
步骤1) 实例化bean; (instantiateBean方法, 使用BeanDefinition+反射技术,工具方法-BeanUtils.instantiateClass) 步骤2) 填充bean属性;(populateBean方法,如Autowire自动装配依赖,属性变量替换); 步骤3) 初始化bean; (initializeBean方法) 调用Aware装配方法; (如BeanNameAware,BeanClassLoaderAware, BeanFactoryAware) 用BeanPostProcessor的初始化前置方法; (postProcessBeforeInitialization方法) 调用初始化方法() ; (调用InitializingBean#afterPropertiesSet方法,调用配置的init方法) 调用BeanPostProcessor的初始化后置方法; (postProcessAfterInitialization方法) 步骤4)注册可销毁bean; 调用registerDisposableBeanIfNecessary(), 可销毁bean=DisposableBean ; 步骤5) 调用SmartInitializingSingleton敏捷初始化单例的afterSingletonsInstantiated() 若bean实现SmartInitializingSingleton接口;
-
-
-
step9) afterRefresh(context, applicationArguments): 默认空,子类可以实现
-
step10) listeners.started(context, startup.timeTakenToStarted()):
- 10.1 【发布事件: 事件名=应用启动完成, 事件类型=ApplicationStartedEvent】
- 10.2 【发布事件: 事件名=可用性变更, 事件类型=AvailabilityChangeEvent,可用性状态=LivenessState.CORRECT 即存活状态正确】
-
step11)callRunners(context, applicationArguments): 调用运行器Bean;类型包括ApplicationRunner,CommandLineRunner
-
stpe12) listeners.ready(context, startup.ready())
- 12.1 【发布事件: 事件名=应用就绪, 事件类型=ApplicationReadyEvent】
- 12.2 【发布事件: 事件名=可用性变更, 事件类型=AvailabilityChangeEvent,可用性状态=ReadinessState.ACCEPTING_TRAFFIC 即就绪状态可以接收流量】
【1.1】springboot应用启动主要步骤总结
【2】springboot应用启动先后发布事件
1)springboot应用启动时先后发布的事件如下:
- 【发布事件:事件名=应用开始启动,事件类型=ApplicationStartingEvent 】
- 【发布事件: 事件名=环境初始化完成, 事件类型=ApplicationEnvironmentPreparedEvent 】
- 【发布事件: 事件名=容器初始化完成,事件类型=ApplicationContextInitializedEvent 】
- 【发布事件:事件名=启动容器关闭,事件类=BootstrapContextClosedEvent 】
- 【发布事件: 事件名=应用初始化完成,事件类型=ApplicationPreparedEvent 】
- 【发布事件: 事件名=应用启动完成, 事件类型=ApplicationStartedEvent 】
- 【发布事件: 事件名=可用性变更, 事件类型=AvailabilityChangeEvent,可用性状态=LivenessState.CORRECT 即存活状态正确 】
- 【发布事件: 事件名=应用就绪, 事件类型=ApplicationReadyEvent 】
- 【发布事件: 事件名=可用性变更, 事件类型=AvailabilityChangeEvent,可用性状态=ReadinessState.ACCEPTING_TRAFFIC 即就绪状态可以接收流量 】
2)发布事件时间线总结 :
- 先实例化及初始化环境;
- 然后实例化及初始化容器;
- 接着实例化及初始化应用;
- 应用初始化完成事件;
- 根据BeanDefinition实例化Bean 【非常重要】 ; 思考题: BeanDefinition从哪里来?
- 应用启动完成事件;
- 最后应用就绪,发布 ACCEPTING_TRAFFIC(=接收流量) 可用性变更事件;
3)为什么我们这么关注事件:因为springboot脚手架通过事件通知订阅者执行自定义业务逻辑,达到功能扩展的目的(如初始化或替换环境变量);
【2.1】springboot启动先后发布事件代码实践
【FirstSpringbootApplication】springboot启动入口
@SpringBootApplication
public class FirstSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(FirstSpringbootApplication.class, args);
}
}
【2.1.1】自定义监听器
自定义监听器并添加到META-INF/spring.factories,以便springboot应用启动时读取并实例化监听器
每个监听器监听(订阅)不同事件; 当发布者发布事件时,监听器接收事件;
// 监听 ApplicationContextInitializedEvent
public class TomApplicationContextInitializedEventListener implements ApplicationListener<ApplicationContextInitializedEvent> {
@Override
public void onApplicationEvent(ApplicationContextInitializedEvent event) {
System.out.println("事件名=容器初始化完成,事件类型=ApplicationContextInitializedEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听ApplicationEnvironmentPreparedEvent
public class TomApplicationEnvironmentPreparedEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
System.out.println("事件名=环境初始化完成, 事件类型=ApplicationEnvironmentPreparedEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听ApplicationPreparedEvent
public class TomApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
System.out.println("事件名=应用初始化完成,事件类型=ApplicationPreparedEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听 ApplicationReadyEvent
public class TomApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("事件名=容器就绪, 事件类型=ApplicationReadyEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听 ApplicationStartedEvent
public class TomApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("事件名=容器启动完成, 事件类型=ApplicationStartedEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听 ApplicationStartingEvent
public class TomApplicationStartingEventListener implements ApplicationListener<ApplicationStartingEvent> {
@Override
public void onApplicationEvent(ApplicationStartingEvent event) {
System.out.println("事件名=应用开始启动,事件类型=ApplicationStartingEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听 AvailabilityChangeEvent
public class TomAvailabilityChangeEventListener implements ApplicationListener<AvailabilityChangeEvent> {
@Override
public void onApplicationEvent(AvailabilityChangeEvent event) {
System.out.println("事件名=可用性变更, 事件类型=AvailabilityChangeEvent, event.getState()=" + event.getState());
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
// 监听 BootstrapContextClosedEvent
public class TomBootstrapContextClosedEventListener implements ApplicationListener<BootstrapContextClosedEvent> {
@Override
public void onApplicationEvent(BootstrapContextClosedEvent event) {
System.out.println("事件名=启动容器关闭,事件类=BootstrapContextClosedEvent");
}
@Override
public boolean supportsAsyncExecution() {
return false;
}
}
【spring.factories】
org.springframework.context.ApplicationListener=\
com.tom.springnote.chapter03.listener.TomApplicationContextInitializedEventListener,\
com.tom.springnote.chapter03.listener.TomApplicationEnvironmentPreparedEventListener,\
com.tom.springnote.chapter03.listener.TomApplicationPreparedEventListener,\
com.tom.springnote.chapter03.listener.TomApplicationReadyEventListener,\
com.tom.springnote.chapter03.listener.TomApplicationStartedEventListener,\
com.tom.springnote.chapter03.listener.TomApplicationStartingEventListener,\
com.tom.springnote.chapter03.listener.TomAvailabilityChangeEventListener,\
com.tom.springnote.chapter03.listener.TomBootstrapContextClosedEventListener
【2.1.2】自定义SpringApplicationRunListener
1)一般不自定义SpringApplicationRunListener,因为监听范围太大,本文只做测试用;
【TomSpringAppRunListener01】
public class TomSpringAppRunListener01 implements SpringApplicationRunListener {
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("TomSpringAppRunListener01 starting");
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("TomSpringAppRunListener01 environmentPrepared");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("TomSpringAppRunListener01 contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("TomSpringAppRunListener01 contextLoaded");
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("TomSpringAppRunListener01 started");
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("TomSpringAppRunListener01 ready");
}
}
【spring.factories】配置TomSpringAppRunListener01
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
com.tom.springnote.chapter03.springapprunlistener.TomSpringAppRunListener01
【2.1.3】springboot运行日志
1)springboot应用启动时的事件发布日志
事件名=应用开始启动,事件类型=ApplicationStartingEvent
TomSpringAppRunListener01 starting
--------------------
事件名=环境初始化完成, 事件类型=ApplicationEnvironmentPreparedEvent
TomSpringAppRunListener01 environmentPrepared
--------------------
事件名=容器初始化完成,事件类型=ApplicationContextInitializedEvent
TomSpringAppRunListener01 contextPrepared
--------------------
事件名=应用初始化完成,事件类型=ApplicationPreparedEvent
TomSpringAppRunListener01 contextLoaded
--------------------
事件名=应用启动完成, 事件类型=ApplicationStartedEvent
TomSpringAppRunListener01 started
--------------------
事件名=可用性变更, 事件类型=AvailabilityChangeEvent, event.getState()=CORRECT
--------------------
事件名=应用就绪, 事件类型=ApplicationReadyEvent
TomSpringAppRunListener01 ready
--------------------
事件名=可用性变更, 事件类型=AvailabilityChangeEvent, event.getState()=ACCEPTING_TRAFFIC
补充:ACCEPTING_TRAFFIC 表示接收流量 ;
事件名=可用性变更, 事件类型=AvailabilityChangeEvent, event.getState()=REFUSING_TRAFFIC
补充:REFUSING_TRAFFIC表示拒绝流量 ;
【3】补充:springboot自带的spring.factories
1)spring.factories 文件在 spring-boot jar包下;文件中的内容配置了bean的全限定类型,用于springboot自动配置; 【当然其他jar包也有,本文不展开】
2)spring.factories主要内容如下;
# Logging Systems 【日志系统】
org.springframework.boot.logging.LoggingSystemFactory=\
org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory,\
org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory,\
org.springframework.boot.logging.java.JavaLoggingSystem.Factory
# PropertySource Loaders 【属性源加载器】
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
# ConfigData Location Resolvers 【配置数据位置解析器】
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver
# ConfigData Loaders 【配置数据加载器】
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader
# Application Context Factories 【应用容器工厂】
org.springframework.boot.ApplicationContextFactory=\
org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContextFactory,\
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContextFactory
# Run Listeners 【运行时监听器,用于发布springboot应用的启动事件】
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers
# Application Context Initializers 【容器初始化器】
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
# Application Listeners 【应用监听器,用于监听springboot启动事件】
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
# Environment Post Processors 【环境后置处理器, 用于装配环境变量】
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.ReactorEnvironmentPostProcessor
# Failure Analyzers 【略过】
# Failure Analysis Reporters 【略过】
# Database Initializer Detectors 【初始化器检测器】
org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector=\
org.springframework.boot.flyway.FlywayDatabaseInitializerDetector,\
org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializerDetector,\
org.springframework.boot.liquibase.LiquibaseDatabaseInitializerDetector,\
org.springframework.boot.orm.jpa.JpaDatabaseInitializerDetector,\
org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializerDetector
# Depends On Database Initialization Detectors 【初始化器检测器】
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector,\
org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector,\
org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector
# Resource Locator Protocol Resolvers 【资源定位协议解析器】
org.springframework.core.io.ProtocolResolver=\
org.springframework.boot.io.Base64ProtocolResolver