1、初始化SpringApplication
:获取webApplicationType
,值为REACTIVE
/SERVLET
2、通过扫描META-INF/spring.factories
下BootstrapRegistryInitializer
的配置,然后返回BootstrapRegistryInitializer
的实现集合
3、通过扫描META-INF/spring.factories
下ApplicationContextInitializer
的配置,然后返回ApplicationContextInitializer
的实现集合
4、通过扫描META-INF/spring.factories下ApplicationListener
的配置,然后返回ApplicationListener
的实现集合
5、执行SpringApplication#run
方法:
DefaultBootstrapContext
对象,然后调BootstrapRegistryInitializer#initialize
方法对DefaultBootstrapContext
初始化SpringApplicationRunListeners
对象,该对象包含了SpringApplicationRunListener
的实现类集合,默认元素为EventPublishingRunListener
的对象,主要作用是作为SpringBoot 的一个广播器,在EventPublishingRunListener
对象里包含了一个SimpleApplicationEventMulticaster
对象,该SimpleApplicationEventMulticaster
对象里面包含了第4部加载出来的所有ApplicationListener
对象SpringApplicationRunListeners#starting
方法发布应用启动监听事件,此方法最后会调到第4步加载的所有ApplicationListener
对象的ApplicationListener#onApplicationEvent
方法进行应用启动监听 准备环境变量:
webApplicationType
类型创建对应的ConfigurableEnvironment
对象。ConfigurableEnvironment
对象添加一个conversionService
对象,该对象的作用是用于类型转换,比如字符串转时间的转换,特别是在通过@ConfigurationProperties
注解读取配置文件值时很有用,可以将配置文件中的字符串配置转换成我们想要的类型。configurePropertySources(environment, args)
和configureProfiles(environment, args)
对环境变量进行扩展。ConfigurationPropertySource
支持附加到指定的环境,将环境管理的每个PropertySource
适配为一个ConfigurationPropertySource
。listeners.environmentPrepared(bootstrapContext, environment)
发布环境准备监听事件,具体监听由第4步加载的监听器来执行,重点关注EnvironmentPostProcessorApplicationListener
,LoggingApplicationListener
这两个监听器,EnvironmentPostProcessorApplicationListener
监听器中调用EnvironmentPostProcessor#postProcessEnvironment
进行环境变量后置处理,解析application.yaml
文件到环境变量就是在ConfigDataEnvironmentPostProcessor#postProcessEnvironment
中做的,postProcessEnvironment
方法最终会调到ConfigDataEnvironment#applyToEnvironment
方法,其中applyToEnvironment
方法中的applyContributor
方法进行具体的文件解析。环境变量加载中Binder
的使用参考https://www.jianshu.com/p/4feab6df384eApplicationContext
对象,创建ApplicationContext
对象时会根据webApplicationType
判断一下,创建相应的ApplicationContext
对象,在创建ApplicationContext
对象时,会创建DefaultListableBeanFactory
对象,用于IOC容器存放Spring创建的Bean对象准备上下文:
ApplicationContext
上下文设置环境变量;ApplicationContext
上下文设置ConversionService
对象;ApplicationContextInitializer#initialize
方法来刷新ApplicationContext
上下文,包括给ApplicationContext
上下文添加监听器,添加各种BeanFactoryPostProcessor
等;ApplicationContextInitializedEvent
事件,具体详细的处理参考源码;BootstrapContextClosedEvent
事件;DefaultListableBeanFactory
容器的Bean是否允许循环引用和是否允许Bean覆盖;LazyInitializationBeanFactoryPostProcessor
添加到ApplicationContext
上下文;BeanDefinitionLoader
对象,然后进行启动类Bean的注册;SpringApplicationRunListeners#contextLoaded
方法,然后在EventPublishingRunListener#contextLoaded
中会将广播器里面的所有监听器添加到ApplicationContext
上下文的监听器里面去,然后通过第4步加载出来的监听器发布ApplicationPreparedEvent
事件,具体监听器做了啥需要参考源码刷新上下文:
首先会添加RuntimeShutdownHook
,然后给ApplicationContext
上下文中添加ApplicationContextClosedListener
监听器;
进行ApplicationContext
上下文刷新,主要是做Bean的创建:
x
1//记录启动时间、状态,web容器初始化其property,复制listener
2prepareRefresh();
3
4//这里返回的是context的BeanFactory
5ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
6
7//beanFactory注入一些标准组件,例如ApplicationContextAwareProcessor,ClassLoader等
8prepareBeanFactory(beanFactory);
9
10try {
11 //给实现类留的一个钩子,例如注入BeanPostProcessors,这里是个空方法
12 postProcessBeanFactory(beanFactory);
13
14 // 调用切面方法,这一步会将所有的beanDefinitionMap扫描出来,扫描beanDefinitionMap的放法ConfigurationClassParser#doProcessConfigurationClass
15 invokeBeanFactoryPostProcessors(beanFactory);
16
17 // 注册切面bean
18 registerBeanPostProcessors(beanFactory);
19
20 // Initialize message source for this context.
21 initMessageSource();
22
23 // bean工厂注册一个key为applicationEventMulticaster的广播器
24 initApplicationEventMulticaster();
25
26 // 给实现类留的一钩子,可以执行其他refresh的工作,创建WebServer就是在这一步
27 onRefresh();
28
29 // 将listener注册到广播器中
30 registerListeners();
31
32 // 实例化bean
33 //1、如果是代理bean则是通过初始化bean的时候在applyBeanPostProcessorsAfterInitialization方法中来调用BeanPostProcessor#postProcessAfterInitialization方法来判断是否需要代理,如果需要代理则创建代理bean
34 //2、如果存在循环依赖,则通过三级缓存来解决,一级缓存存单例成品bean,二级缓存存第三级缓存生成的半成品bean,三级缓存是单例bean工厂,该工厂可能生成原始bean对象,也可能生成被AOP后代理对象,由于AOP后的代理对象每次生成的时候都是新的对象,由于是单例bean,所以需要一个二级缓存来存单例bean工厂生成的代理对象
35 finishBeanFactoryInitialization(beanFactory);
36
37 // 清理缓存,注入DefaultLifecycleProcessor,并启动服务,发布ContextRefreshedEvent
38 finishRefresh();
39}
发布启动完成事件ApplicationStartedEvent
;
在启动完成后需要执行ApplicationRunner
、CommandLineRunner
的就从IOC容器里面拿到相应的Bean来执行