Springboot 启动过程

今天我们来看一下Springboot的启动过程

准备阶段

SpringApplication.run静态方法是最常用的启动入口,我们就从这个方法开始

WebApplicationType.deduceFromClasspath();将识别出应用的类型,传统的Servlet web应用、Reactor web应用、非web应用

第2步则是加载BootstrapRegistryInitializerApplicationContextInitializerApplicationListener

他们都是通过扫描classpath下各个jar包META-INF/spring.factories文件中所配置的类名称加载和过滤得到的

因此我们自定义配置的也会被加载进来

第3步deduceMainApplicationClass();因则是使用栈信息推断出启动类,即栈信息中最近的main方法所在的类,一般我们命名都是XxxApplication的类

接下来开始执行成员方法run

我们先来看run方法中的getRunListeners(args);

它将从META-INF/spring.factories加载出所有的SpringApplicationRunListener它并封装到SpringApplicationRunListeners

Spring内置的listeners有EventPublishingRunListener

这个Listener是用来向所有ApplicationListener发送各种ApplicationEvent的,例如ApplicationStartingEvent

我们继续看run方法中的listeners.starting(bootstrapContext, this.mainApplicationClass);

这里会触发所有SpringApplicationRunListenerstarting方法,其中EventPublishingRunListener的starting就会发送ApplicationStartingEvent

准备Environment

我们继续看run方法中的ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);

这里第1步将根据webApplicationType创建对应的ConfigurableEnvironment

ServletWebServerApplicationContextFactory创建ApplicationServletEnvironment

ReactiveWebServerApplicationContextFactory创建ApplicationReactiveWebEnvironment

第2步则触发所有SpringApplicationRunListenerenvironmentPrepared,其中包括EventPublishingRunListener发送ApplicationEnvironmentPreparedEvent

我们继续看run方法中的context = createApplicationContext();

这里同样将根据webApplicationType创建对应的ConfigurableApplicationContext

ServletWebServerApplicationContextFactory创建ServletWebServerApplicationContext

ReactiveWebServerApplicationContextFactory创建ReactiveWebServerApplicationContext

准备Context

我们继续看run方法中的prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

applyInitializers将会触发所有ApplicationContextInitializer. initialize(context);

listeners.contextPrepared(context); 将会触发所有SpringApplicationRunListenercontextPrepared,其中包括EventPublishingRunListener发送ApplicationContextInitializedEvent

bootstrapContext.close(context); 将会向所有ApplicationListener发送BootstrapContextClosedEvent

context.addBeanFactoryPostProcessor则向context增加BeanFactoryPostProcessor

最后listeners.contextLoaded(context); 将会触发所有SpringApplicationRunListenercontextLoaded,其中包括EventPublishingRunListener发送ApplicationPreparedEvent

我们继续看run方法中的refreshContext(context);

这里把context注册到优雅停机Hook

接下来就进入到spring-context范畴的启动过程了

我们来看refresh方法中的prepareBeanFactory(beanFactory);

这里给beanFactory加入了几个BeanPostProcessor

ApplicationContextAwareProcessor将会给实现各种Aware接口的bean触发相应的setXxx方法,例如applicationContextAware.setApplicationContext

ApplicationListenerDetector将会把ApplicationListener添加给applicationContext

我们来看refresh方法中的postProcessBeanFactory(beanFactory);

这里如果context类型是ServletWebServerApplicationContext就会执行以下步骤

这里给beanFactory加入了类型是WebApplicationContextServletContextAwareProcessorBeanPostProcessor

WebApplicationContextServletContextAwareProcessor将会给实现ServletContextAwareServletConfigAware接口的bean触发相应的setXxx方法

我们来看refresh方法中的invokeBeanFactoryPostProcessors(beanFactory);

这里面将按PriorityOrdered@Order顺序触发所有的BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor

部分代码

我们来看refresh方法中的registerBeanPostProcessors(beanFactory);

这里面将按PriorityOrdered@Order顺序向beanFactory添加BeanPostProcessor

部分代码

启动Server

我们来看refresh方法中的onRefresh();

这里ServletWebServerApplicationContextReactiveWebServerApplicationContext有各自的实现,而非web则是默认的空实现

ServletWebServerApplicationContext的实现

createWebServer(里面创建server之后将会启动起来,例如tomcat的 this.tomcat.start();

这里的ServletWebServerFactory有多种实现

使用哪一种是由依赖的servlet容器jar包决定的,看ServletWebServerFactoryConfiguration的代码就可以知道

在这里已经根据环境决定了ServletWebServerFactory

再来看ReactiveWebServerApplicationContext的实现

这里的ReactiveWebServerFactory有多种实现

使用哪一种是由依赖的jar包决定的,看ReactiveWebServerFactoryConfiguration的代码就可以知道

在这里已经根据环境决定了ReactiveWebServerFactory

另外在上面this.serverManager = new WebServerManager(this, webServerFactory, this::getHttpHandler, lazyInit); 时内部就创建了WebServer

初始化Bean

我们来看refresh方法中的finishBeanFactoryInitialization(beanFactory);

这里主要是初始化初始化所有non-lazy singleton beans和触发所有SmartInitializingSingletonafterSingletonsInstantiated

需要特别说明的是getBean(beanName); 的深层处将会触发BeanPostProcessorpostProcessBeforeInitialization方法和postProcessAfterInitialization方法

这个过程在AbstractAutowireCapableBeanFactory属于spring-beans范畴,来看中间的invokeInitMethods(beanName, wrappedBean, mbd);

如果bean是实现了InitializingBean则将执行afterPropertiesSet,如果具有init方法 或 方法具有注解@ PostConstruct则将执行对应的初始化方法

我们来看refresh方法中的finishRefresh();

这里getLifecycleProcessor().onRefresh();将触发所有Lifecycle这bean的start方法

Note:我们通过 

Springcloud 服务注册与发现是怎么工作的_springcloud服务注册和发现如何实现的_icodegarden的博客-CSDN博客

篇章知道springboot启动阶段的服务注册是在Lifecycle的start中触发的,因此首次注册服务发生在WebServer启动之后

publishEvent(new ContextRefreshedEvent(this)); 向所有ApplicationListener发送ContextRefreshedEvent

refresh方法到此结束主要流程

我们继续看run方法中的listeners.started(context, timeTakenToStartup);

这里会触发所有SpringApplicationRunListenerstarted方法,其中EventPublishingRunListener的started就会发送ApplicationStartedEvent和内容是LivenessState.CORRECT (liveness已正常)的AvailabilityChangeEvent(可用性变更时间)

我们继续看run方法中的callRunners(context, applicationArguments);

这里将触发所有ApplicationRunnerCommandLineRunner

我们继续看run方法中的listeners.ready(context, timeTakenToReady);

这里会触发所有SpringApplicationRunListenerready方法,其中EventPublishingRunListener的ready就会发送ApplicationReadyEvent和内容是ReadinessState.ACCEPTING_TRAFFIC(readness已正常)的AvailabilityChangeEvent(可用性变更时间)

到此Springboot就启动完毕了

最后补充一点Springboot的变更,从Springboot3开始META-INF/spring.factories的org.springframework.boot.autoconfigure.EnableAutoConfiguration 部分变更为配置在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值