启动顺序主要针对SpringApplication.run()方法的梳理
一 SpringApplication类的实例化
-
ApplicationContextInitializer 实现类的资源配置文件读取以及实现相关类的实例化
1).加载 ApplicationContextInitializer 实现类 ,由 SpringFactoriesLoader 类加载定义在 META-INF/spring.factories 文件夹下的配置文件Resource 初始化资源列表 Map<ClassLoader, MultiValueMap<String, String>>
2).加载实例化ApplicationContextInitializer 的实现类 -
ApplicationListener 接口类的资源配置文件的读取以及实例化
1).加载 ApplicationListener 实现类 ,由 SpringFactoriesLoader 类加载定义在 META-INF/spring.factories 文件夹下的配置文件Resource 初始化资源列表 Map<ClassLoader, MultiValueMap<String, String>>
2) ApplicationListener 的实现类
二 SpringApplication.run()启动方法
- SpringApplicationRunListeners的实例化以及相关实现类的调用
1).实例化 SpringApplicationRunListeners,启动 SpringApplicationRunListeners的监听
由 SpringFactoriesLoader 类加载 SpringApplicationRunListeners 实现类 ,定义在 META-INF/spring.factories 文件夹下的配置文件Resource 初始化资源列表 Map<ClassLoader, MultiValueMap<String, String>>
2).遍历调用所有SpringApplicationRunListeners的starting方法,实现实现类接口的初始化 - 实例化 ConfigurableEnvironment ,由listeners,bootstrapContext,applicationArguments设置启动springboot启动的环境配置信息
- 打印Banner
- 创建ConfigurableApplicationContext类
- 创建加载SpringBootExceptionReporter
1).加载 创建加载SpringBootExceptionReporter 实现类 ,定义在 META-INF/spring.factories 文件夹下的配置文件Resource 初始化资源列表 Map<ClassLoader, MultiValueMap<String, String>>
2).创建加载SpringBootExceptionReporter 的实现类 - 初始化容器prepareContext
根据初始化的ConfigurableApplicationContext、ConfigurableEnvironment、SpringApplicationRunListeners、ApplicationArguments、Banner 准备初始化上下文context
1) 设置实现ApplicationContextInitializer 的实现类的context属性
2) 设置listener的context属性
3)设置beanFactory 的属性 ,加载bean的时候是否循环依赖allowCircularReferences
4) 设置beanFactory的属性 ,加载bean 时候是否允许同名bean的覆盖属性allowBeanDefinitionOverriding,springboot默认false
5) 设置context 属性 lazyInitialization ,配置是否延迟加载懒加载的bean。
6) 创建加载bean的BeanDefinitionLoader。和定义bean 加载时候的resourceLoader,environment
懒加载的bean配合@Lazy注解使用。懒加载好处:
节省资源:当应用程序中存在大量的 bean 时,立即初始化所有 bean 可能会占用大量的内存和处理时间。通过延迟初始化,只有在需要使用 bean 时才会进行初始化,可以避免不必要的资源消耗。
加快启动时间:延迟初始化可以减少应用程序启动时间,因为只有在需要时才会加载和初始化
bean。对于那些在应用程序启动时可能不会使用的较大或复杂的 bean,延迟初始化可以显著加快启动时间。
解决循环依赖: Spring 容器可以管理bean之间的依赖关系。当存在循环依赖时,延迟初始化可以帮助解决这个问题。通过延迟初始化,Spring
容器可以在运行时逐个解析和满足 bean 之间的依赖,而不是在初始化阶段发现无法解决的循环依赖。
- 更新上下文 refreshContext
1) 通过registerShutdownHook 钩子方法判断容器是进行开启还是关闭
2) 给beanFactory进行refresh()
(1) 设置BeanFactory的后置处理器,实现了BeanFactoryPostProcessor接口
(2)设置bean的后置处理器,实现了BeanPostProcessor接口
(3) 初始化国际化资源,实现了HierarchicalMessageSource接口
(4)初始化spring容器实践,实现了ApplicationEventMulticaster接口
(5)onRefresh() 更新主题资源,实现了HierarchicalThemeSource接口, 创建ServletContext
(6)注册监监听事件ApplicationListener事件,获取ApplicationListener实现接口集合,执行广播监听(ApplicationEventMulticaster接口实现类),执行对应的excute方法;执行 listener.onApplicationEvent(event)方法;
(7)加载通过字节码载入字节码文件时动态织入Aspect切面,LoadTimeWeaverAware接口
(8) 加载实例化LifecycleProcessor接口,调用start/stop相关接口
在Spring中还提供了Lifecycle接口,Lifecycle接口中包含start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在Spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,如启动后一直运行(如对MQ进行轮询等)。而ApplicationContext的初始化最后一步就是保证了这一功能的实现。
(9) 调用ContextRefreshedEvent 事件机制,实现ApplicationContextEvent实现ApplicationEvent 抽象类 - 打印启动日志 logStartupInfo
- 执行接口事件、ApplicationRunner、CommandLineRunner接口事件集合
springboot 启动流程图
springboot 创建上下文 createApplicationContext 过程
springboot 扩展点详解
参考:https://blog.csdn.net/fox9916/article/details/129101918