SpringBoot启动过程
阶段一:SpringApplication 构造
- 记录 BeanDefinition 源
- 推断应用类型
- 记录 ApplicationContext 初始化器
- 记录监听器
- 推断主启动类
阶段二:执行 run 方法
- 得到 SpringApplicationRunListeners,名字取得不好,实际是事件发布器
- 发布 application starting 事件
- 封装启动 args
- 准备 Environment 添加命令行参数
- ConfigurationPropertySources 处理
- 发布 application environment 已准备事件
- 通过 EnvironmentPostProcessorApplicationListener 进行 env 后处理
- application.properties,由 StandardConfigDataLocationResolver 解析
- spring.application.json
- 绑定 spring.main 到 SpringApplication 对象
- 打印 banner
- 创建容器
- 准备容器
- 发布 application context 已初始化事件
- 加载 bean 定义
- 发布 application prepared 事件
- refresh 容器
- 发布 application started 事件
- 执行 runner
- 发布 application running 事件
- 这其中有异常,发布 application failed 事件
SpringBoot自动配置
- SpringBoot 的自动配置注解是 @EanbleAutoConfiguration
- SpringBoot 启动类上使用的 @SpringbootApplication,包含了@EanbleAutoConfiguration 注解,它又包含了@Import 注解,导入了一个类 AutoConfigurationImportSelector,该类中使用 SelectorImport 方法,这个方法扫描所有 jar 下的 spring.factories 中注册的各种 AutoConfiguration 类,满足 @Conditional 注解的条件,就实例化该 AutoConfiguration 类中定义的 Bean,并注入到Spring容器中
- 自动配置类本质上就是一个配置类而已,只是用 META-INF/spring.factories 管理,与应用配置类解耦
- @Enable 打头的注解本质是利用了 @Import
- @Import 配合 DeferredImportSelector 即可实现导入,selectImports 方法的返回值即为要导入的配置类名
- DeferredImportSelector 的导入会在最后执行,为的是让其它配置优先解析
@Indexed原理
- 在编译时就根据 @Indexed 生成 META-INF/spring.components 文件
- 扫描时
- 如果发现 META-INF/spring.components 存在, 以它为准加载 bean definition
- 否则, 会遍历包下所有 class 资源 (包括 jar 内的)
- 解决的问题,在编译期就找到 @Component 组件,节省运行期间扫描 @Component 的时间
|