从main方法的SpringApplication.run()开始,这里是使用类名调用静态方法,这是启动的入口
contrl+b进入源码,看到这个run方法,在这里面这个静态run方法的实现分为两步骤,第一先初始化实例SpringApplication,然后再调用SpringApplication的run方法
2.1 在new SpringApplication中,是通过构造函数进行初始化
在这里SpringBoot会推断web应用类型,是reactive/servlet/none
this.properties.setWebApplicationType(WebApplicationType.deduce());之后加载 Initializers 和 Listeners: Spring Boot 会从META-INF/spring.factories(在 Spring Boot 3.x 中,主要迁移到了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,但spring.factories依然为了兼容性而存在)文件中,加载ApplicationContextInitializer和ApplicationListener接口的实现类
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));2.2 run方法核心步骤讲解
Startup机制计时
在SpringBoot2.3及以前,run方法一开始就启动StopWatch来计时,但是现在使用了Startup机制来计时,为什么换了,原因如下?
StopWatch太简单了,只能记录“总耗时”。而在 Spring Boot 3.x 中,开发者需要更细粒度的监控(比如:Environment 准备花了多久?Bean 初始化花了多久?Tomcat 启动花了多久?)。Startup机制引入了一个名为ApplicationStartup的接口,它支持记录启动过程中的每一个步骤(Step),功能比StopWatch强大得多
Evironment准备:
prepareEnvironment()方法在容器创建之前执行,负责创建Environment并加载所有配置源。加载顺序(优先级从低到高,后加载的覆盖先加载的)如下:
application.yml/application.properties:最低优先级。操作系统环境变量:高于配置文件。
JVM 系统属性(
-D参数):高于环境变量。命令行参数(
--server.port=9090):最高优先级
创建 ApplicationContext:根据 Web 类型选择
Spring Boot 会根据之前在new Application中推断的WebApplicationType,在createApplicationContext()方法中创建对应的容器。
| Web 应用类型 | 创建的 ApplicationContext 实现 |
| SERVLET | AnnotationConfigServletWebServerApplicationContext |
| REACTIVE | AnnotationConfigReactiveWebServerApplicationContext |
| NONE | AnnotationConfigApplicationContext |
refreshContext()这里标志着Spring IOC的正式初始化和启动,内部完成了大量工作,会扫描创建装配所有Bean
refresh完成后,整个应用就启动完毕了,run方法return ApplicationContext容器