1、静态run方法受限创建一个SpringApplication实例,然后调用其run方法
SpringApplication实例化,会做:
·根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型,还是应该创建一个标准Standalone应用使用的使用的ApplicationContext类型,还是应该创建一个标准Standalone应用使用的ApplicationContext类型。
·使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
·使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
·推断并设置main方法的定义类
2、run方法执行开始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener,调用它们的started()方法
3、创建并配置当前SpringBoot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4、遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法
5、如果SpringApplication的showBanner属性被设置为true,则打印banner
6、根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。
7、ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8、遍历调用所有SpringApplicationRunListener的contextPrepared()方法
9、最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10、遍历调用所有SpringApplicationRunListener的contextLoaded()方法
11、调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12、查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13、正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
去除事件通知点后,整个流程如下:

SpringApplicationRunListener
SpringApplicationRunListener是一个只有SpringBoot应用的main方法执行过程中接收不同执行时点事件通知的监听者。基本没什么常见的场景需要自己实现一个Spring-ApplicationRunListener,即使SpringBoot默认也只是实现了一个org.spring-framework.boot.context.event.EventPublishingRunListener,用于在SpringBoot启动的不同时点发布不同的应用事件类型(ApplicationEvent)
ApplicationListener
Spring框架对Java中实现的监听者模式的一种框架实现,这里唯一值得着重强调的是,对于初次接触SpringBoot,但对Spring框架本身又没有过多接触的开发者来说,可能会将这个名字与SpringApplicationRunListener混淆
如果我们要为SpringBoot应用添加自定义的ApplicationListener,有两种方式:
1)通过SpringApplication.addListeners(..)或者SpringApplication.setListeners(..)方法添加一个或者多个自定义的ApplicationListener;
2)借助SpringFactoriesLoader机制,在META-INF/spring.factories文件添加配置
ApplicationContextInitializer
ApplicationContextInitializer也是Spring框架原有的概念,这个类的主要目的就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContext做refresh之前,允许我们对ConfigurableApplicationContext的实例做进一步的设置或者处理
一般情况下我们基本不会需要自定义一个ApplicationContext-Initializer,即使SpringBoot框架默认也只是注册了三个实现。如果我们真的需要自定义一个ApplicationContextInitializer,那么只要像上面这样,通过SpringFactoriesLoader机制进行配置,或者通过SpringApplication.addInitializers(..)设置即可
CommandLineRunner
属于SpringBoot应用特定的回调扩展接口
需要大家关注的其实就两点:
1)所有CommandLineRunner的执行时点在SpringBoot应用的Application-Context完全初始化开始工作之后(可以认为是main方法执行完成之前最后一步)。
2)只要存在于当前SpringBoot应用的ApplicationContext中的任何Command-LineRunner,都会被加载执行(不管你是手动注册这个CommandLineRunner到IoC容器,还是自动扫描进去的)
与其他几个扩展点接口类型相似,建议CommandLineRunner的实现类使用@org.springframework.core.annotation.Order进行标注或者实现org.springframework.core.Ordered接口,便于对它们的执行顺序进行调整,这其实十分重要,我们不希望顺序不当的CommandLineRunner实现类阻塞了后面其他CommandLineRunner的执行。
CommandLineRunner是很好的扩展接口,大家可以重点关注
本文详细解析了Spring Boot应用程序启动的具体流程,从SpringApplication实例化到ApplicationContext的创建、配置及刷新全过程,并介绍了关键组件如SpringApplicationRunListener、ApplicationContextInitializer的作用。

2万+

被折叠的 条评论
为什么被折叠?



