SpringBoot启动类注解构成:
- 需要一个添加了
@SpringBootApplication
注解的启动类。 - 该注解由
@EnableAutoConfiguration
、@SpringBootConfiguration
、@ComponentScan
三个注解构成。 @EnableAutoConfiguration
是最为核心的,启动时会导入"自动配置"AutoConfigurationImportSelector
类,这个类会将所有符合条件的@Configuration配置都进行加载。@SpringBootConfiguration
等同于@Configuration
,将这个类标记为配置类,会被加载到容器中。@ComponentScan
会自动扫描并加载符合条件的Bean。- 如果启动类中不需要增加配置内容,也不需要指定扫描路径,使用
@EnableAutoConfiguration
替代@SpringBootApplication
,也可以完成启动。 - 注解完成后,运行起点就是
SpringApplication
的run方法。
run方法启动后会经历如下四个阶段:
-
服务构建
- 首先把传入的"资源加载器、主方法类"记录在内存中,然后逐一判断对应的服务类是否存在,来确定Web服务的类型。默认是servlet,即基于Servlet的web服务,如tomcat,还有响应式非阻塞服务reactive,如
spring-webflux
,什么都不是则是用的none。- 确定了选择哪个web服务后,开始加载初始化类。通过读取所有META-INF/
spring.factories
文件中的"注册初始化"、“上下文初始化”、"监听器"这三类配置,即BootStrapRegistryInitalizer
、ApplicationContextInitializer
和ApplicationListenter
。 - spring-boot和spring-boot-autoconfigure这两个工程中配置了7个"上下文初始化"和8个"监听器",这些配置信息会在后续的启动流程中使用到。
- 程序员可以自定义这三个配置,将其放到工程中的spring factories文件中,项目就会将其一并加载进来。
- 接下来会通过"运行栈"
stackTrace
判断main方法所在的类,大概率就是启动类本身,此时spring服务SpringApplication
就构造完成了。
- 确定了选择哪个web服务后,开始加载初始化类。通过读取所有META-INF/
- 首先把传入的"资源加载器、主方法类"记录在内存中,然后逐一判断对应的服务类是否存在,来确定Web服务的类型。默认是servlet,即基于Servlet的web服务,如tomcat,还有响应式非阻塞服务reactive,如
-
环境准备
- 先通过
createBootstrapContext
方法创建一个"启动上下文"BootstrapContext
,同时逐一调用刚刚加载的"启动注册初始化器"BootstrapRegistryInitializer
中的初始化initialize方法。 - 然后启动"运行监听器"
SpringApplicationRunListeners
,同时发布"启动"事件,获取并加载spring-boot工程spring factories配置文件中的EventPublishingRunListener
,启动时,也会将服务构建时的8个监听器ApplicationListener
都引入进来,程序员便可以通过监听这些事件,然后在启动流程中加入自定义逻辑了。 - 接下来通过
prepareEnvironment
方法"组装启动参数"。- 首先构造一个"可配置环境"
ConfigurableEnvironment
,根据不同的Web服务类型会构造不同的环境,同样默认是Servlet,构造之后会加载很多诸如"系统环境变量"systemEnvironment
、"jvm系统属性"systemProperties
等在内的4组配置信息,把这些配置信息都加载到propertySources
的内存集合中,后续使用到这些信息就无须重新加载了。 - 通过"配置环境"
configureEnvironment
方法将启动时传入的环境参数args
进行设置,例如启动时传入的诸如"开发/生产"环境配置等都会在这一步进行加载。 - 在
propertySources
集合的首个位置添加一个值为空的配置内容configurationProperties。
- 发布"环境准备完成"这个事件,刚加载进来的8个Listener会监听到这个事件,其中的部分监听器会进行相应处理,诸如"环境配置后处理监听器"
EnvironmentPostProcessorApplicationListener
会去加载spring.factories
配置文件中"环境配置后处理器"EnvironmentPostProcessor
,这里监听器通过观察者模式设计,是逐一"串行"执行的,而不是异步"并行",需要等待所有监听器都处理完成之后,才会继续执行后续逻辑。 - 由于刚创建的"可配置环境"在一系列过程中可能会有变化,通过二次更新保证匹配。
- 将
spring.beaninfo.ignore
设为true,表示不加载Bean的元数据信息,同时打印Banner图,环境准备阶段完成。
- 首先构造一个"可配置环境"
- 先通过
-
容器创建
容器:各种属性、集合及配套功能的结构体
ApplicationContext
即"上下文"。- 通过
createApplicationContext
来创建容器- 首先根据服务类型创建容器
ConfigurableApplicationContext
,默认的服务类型是servlet,创建的是"注解配置的Servlet-Web服务容器",即AnnotationConfigServletWebServerApplicationContext
,在这个过程中会构造诸如:存放和生产bean实例的"Bean工厂"DefaultListableBeanFactory
,用来解析@Component
、@ComponentScan
等注解的"配置类后处理器"ConfigurationClassPostProcessor
、用来解析@Autowired
、@Value
、@Inject
等注解的"自动注解Bean后处理器"AutowiredAnnotationBeanPostProcessor
等在内的属性对象,并把它们都放入容器。 - 通过
prepareContext
方法对容器中的部分属性进行初始化,先用postProcessApplicationContext
方法设置"Bean名称生成器"、“资源加载器”、"类型转换器"等,接着执行之前加载进来的"上下文初始化"ApplicationContextInitializer
,默认加载7个,容器ID、警告日志处理、日志监听都是在这里实现的,发布"容器准备完成"监听事件。 - 陆续为容器注册"启动参数"、“Banner”、"Bean引用策略"和"懒加载策略"等等。
- 通过Bean定义加载器将"启动类"在内的资源加载到"Bean定义池"
BeanDefinitionMap
中,以便后续根据Bean定义创建"Bean对象",然后发布"资源加载完成"事件, 容器就创建完成了。
- 首先根据服务类型创建容器
- 通过
-
填充容器
- 生产自身提供的和程序员自定义的所有Bean对象,并存放在上一步创建好的容器中,这个过程被称为"自动装配"。
- Bean生命周期管理,构造和启动一个Web服务器如tomcat。
- 发布"启动完成"事件,回调程序员自定义实现的Runner接口,来处理一些执行后定制化需求,启动流程结束。