main方法启动时,springBoot启动流程的各个生命周期会以事件通知的方式,把事件告知其他程序
前期通过spring-spi获取所有监听事件的类   
- spring启动的大体流程为以下的几个方法    1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75public class EventPublishingRunListener implements SpringApplicationRunListener { 
 ...
 private final SimpleApplicationEventMulticaster initialMulticaster = new SimpleApplicationEventMulticaster();
 public EventPublishingRunListener(SpringApplication application, String[] args) {
 // 通过springSPI获取所有的ApplicationListener,并添加到initialMulticaster字段中
 for (ApplicationListener<?> listener : application.getListeners()) {
 this.initialMulticaster.addApplicationListener(listener);
 }
 }
 
 // 1 开始
 
 public void starting() {
 this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
 }
 
 // 2 环境准备
 
 public void environmentPrepared(ConfigurableEnvironment environment) {
 this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
 }
 
 /**
 protected void applyInitializers(ConfigurableApplicationContext context) {
 for (ApplicationContextInitializer initializer : getInitializers()) {
 ...
 initializer.initialize(context);
 }
 }
 */
 // contextPrepared之前 会调用SpringApplication 内置的 initialize,如上面的注释的代码
 // 3 上下文准备
 
 public void contextPrepared(ConfigurableApplicationContext context) {
 this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
 }
 
 // 4 上下文已加载
 
 public void contextLoaded(ConfigurableApplicationContext context) {
 for (ApplicationListener<?> listener : this.application.getListeners()) {
 if (listener instanceof ApplicationContextAware) {
 ((ApplicationContextAware) listener).setApplicationContext(context);
 }
 context.addApplicationListener(listener);
 }
 this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
 }
 // contextLoaded之后 会调用 [context.refresh](/posts/springbeanfactory流程解析),会实例化所有的bean(单例的、notLazy的)
 // 在refresh阶段后,context的事件会通过context发出,context持有beanFactory, beanFactory在refresh期间会扫描所有的listener。
 // 5 启动完成
 
 public void started(ConfigurableApplicationContext context) {
 context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
 AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
 }
 // 6 运行中
 
 public void running(ConfigurableApplicationContext context) {
 // 通过context发出事件,context持有beanFactory,beanFactory会扫描所有的ApplicationListener。
 context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
 AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
 }
 
 public void failed(ConfigurableApplicationContext context, Throwable exception) {
 ...
 }
 ...
 }
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
启动流程
1. starting(ApplicationStartingEvent)
正在进行时、代表容器刚开始运行了---发出程序开始事件
springDevTools就是用到了此事件,把类加载器给换了一下,起到了热部署的作用,后期咱们会有详细的分析
2. environmentPrepared(ApplicationEnvironmentPreparedEvent)
配置环境变量加载配置文件资源等---发出环境配置已就绪事件
nacos和springCloud远程加载配置文件就是用到了此事件,后期咱们会有详细的分析  
事件发出之后,马上就要实例化ApplicationContext了,不同的WebApplicationType,context实例不同
不管什么样的context,都会持有beanFactory,并且都会向beanFactory注册一个非常重要的bean:ConfigurationClassPostProcessor
注册代码
AnnotationConfigUtils#registerAnnotationConfigProcessors在beanFactory执行后置处理时,会调用此类
它的作用是:扫描beanFactory所有的bean,符合条件的生成beanDefinition并注册到beanFactory,然后继续扫描
如处理@PropertySources、@ComponentScans、@Component、@Import、@Configuration等注解实例化完context后会发布事件通知,会调用ApplicationContextInitializer的initialize
3. contextPrepared(ApplicationContextInitializedEvent)
触发此事件之前会触发contextInitializer的initialize
容器准备---发出应用程序上下文初始化事件
contextPrepared之后会把main方法所在的启动类注册到beanFactory中,这样该类上的注解ComponentScan等,就会被ConfigurationClassPostProcessor处理  
4. contextLoaded(ApplicationPreparedEvent)
容器已加载完毕---发出应用程序已准备就绪事件
contextLoaded之后 会调用 context.refresh,会实例化所有的bean(单例的、notLazy的)
refresh阶段比较复杂,基本上都是操作beanFactory完成bean的扫描、组装、初始化等逻辑
beanFactory可参考springBeanFactory流程解析
5. started(ApplicationStartedEvent)
发出应用程序已启动事件
6. running(ApplicationReadyEvent)
运行中---发出程序已做完事件
failed(ApplicationFailedEvent)
启动失败时的事件处理器,spring默认就是打印日志。
我们可以实现此事件的监听,项目启动失败之后直接报警等
总结
ApplicationContext这个是spring的容器(非常重要),启动的流程基本上都是围绕着他展开。
从各个事件的通知事件我们不难看出。从最开始的starting、environmentPrepared都是为applicationContext做准备。
根据不同的WebType实例化不同的applicationContext,之后context会持有environment,environment包含了所有的配置文件
然后再以context为中心进行initialize事件的触发、然后contextPrepared、contextLoaded、context.refresh
refresh工作比较复杂也是beanFactory的核心,具体可参考springBeanFactory流程解析
最后在做结尾的工作started和running
