springboot版本,1.4.3.RELEASE
流水账,纯记录。
TL;DR.
- 创建并初始化SpringBoot实例
- 判断是否是web应用 : 通过是否存在Web应用相关的类来判断,
javax.servlet.Servlet
org.springframework.web.context.ConfigurableWebApplicationContext
- 从
META-INF/spring.factories
中加载ApplicationContextInitializer
的实现类,为之创建实例,并按照注解Order
来排序存储,getSpringFactoriesInstances
- 从
META-INF/spring.factories
中加载ApplicationListener
的实现类,为之创建实例,并按照注解Order
来排序存储,getSpringFactoriesInstances
- 判断应用程序主类 : 分析当前调用栈,找到含有
main
方法的类。不过这里只检查了方法名,若是还有其他名为main
的方法,容易出现错误。
- 判断是否是web应用 : 通过是否存在Web应用相关的类来判断,
- 调用
SpringApplication#run(String... args)
启动应用程序 :- 从
META-INF/spring.factories
中加载SpringApplicationRunListener
的实现类,为之创建实例,并按照注解Order
来排序存储,然后在启动加载的实例SpringApplicationRunListeners#started
- 从
- 处理命令行参数,
DefaultApplicationArguments
- 按照是否带有前缀
--
来区分是否是参数选项,分别存储到CommandLineArgs
的optionArgs
和nonOptionArgs
中,参见SimpleCommandLineArgsParser#parse
- 按照是否带有前缀
- 准备应用程序的执行环境,
prepareEnvironment
- 创建
Environment
实例,若是Web应用程序,则使用StandardServletEnvironment
实例,否则使用StandardEnvironment
实例。在实例化Environment
时,会获取到系统变量和环境变量,放置到属性列表中。 - 配置创建好的
Environment
实例,将命令行参数中的配置项加入到属性列表中,配置profile信息,找出处理active状态的profile - 调用注册的
SpringApplicationRunListeners
,处理environmentPrepared
事件 - 若创建的
Environment
实例是ConfigurableWebEnvironment
,但前面通过deduceWebEnvironment
方法判断的不是Web应用,则会将ConfigurableWebEnvironment
实例转换为普通Environment
实例。
- 创建
- 在控制台打印banner文字
- 创建
ApplicationContext
容器,对于Web应用程序,容器实例是AnnotationConfigEmbeddedWebApplicationContext
。容器有两个属性,AnnotatedBeanDefinitionReader
和ClassPathBeanDefinitionScanner
,分别用来根据注解和类路径来加载Bean。注意,这时候还没有加载Bean。 - 准备容器
ApplicationContext
- 将
ApplicationContext
与Environment
相关联:context.setEnvironment(environment);
- 处理
ApplicationContext
实例,注册BeanBeanNameGenerator
和ResourceLoader
- 应用初始化器
ApplicationContextInitializer
,对ApplicationContext
实例,初始化器是在初始化SpringBoot实例时加载的 - 调用注册的
SpringApplicationRunListeners
,处理contextPrepared
事件 - 向容器
ApplicationContext
中注册BeanApplicationArguments
和Banner
- 加载应用程
- 调用注册的
SpringApplicationRunListeners
,处理contextLoaded
事件
- 将
- 刷新容器
ApplicationContext
- 准备刷新
- 清空容器属性
ClassPathBeanDefinitionScanner
的缓存 - 调用父类,执行基础准备工作
- 重置容器启动时间,将关闭状态置为
false
,将活动状态置为true
- 初始化属性源,若当前是Web应用,则使用
GenericWebApplicationContext
来初始化属性源,GenericWebApplicationContext#initPropertySources
- 校验必要属性是否设置
- 重置容器启动时间,将关闭状态置为
- 清空容器属性
- 刷新
BeanFactory
,这里其实啥也没做 - 准备
BeanFactory
,做各项基础配置 BeanFactory
后续处理,这里除了做常规的后续处理之外,还会使用实例ClassPathBeanDefinitionScanner
和AnnotatedBeanDefinitionReader
来加载应用程序的Bean- 调用
BeanFactoryPostProcessor
- 注册
BeanPostProcessor
- 初始化
MessageSource
- 初始化事件广播器
ApplicationEventMulticaster
- 初始化特殊Bean
- 注册
ApplicationListener
,如果有早期事件的话,就会广播出去 - 实例化单例Bean
- 广播相关事件
- 准备刷新
- 刷新容器后的后续处理,这里主要是调用
ApplicationRunner
和CommandLineRunner
完成各自的任务 - 调用注册的
SpringApplicationRunListeners
,处理finished
事件