给你一份超详细Spring Boot知识清单
作者:网友投稿 时间:2018-10-10 16:30

因而 Spring Boot 应用本质上就是一个基于 Spring 框架的应用,它是 Spring 对“约定优先于配置”理念的最佳实践产物,它能够帮助开发者更快速高效地构建基于 Spring 生态圈的应用。
那 Spring Boot 有何魔法?自动配置、起步依赖、Actuator、命令行界面(CLI) 是 Spring Boot 最重要的 4 大核心特性。
其中 CLI 是 Spring Boot 的可选特性,虽然它功能强大,但也引入了一套不太常规的开发模型,因而这个系列的文章仅关注其他 3 种特性。
本文将为你打开 Spring Boot 的大门,重点为你剖析其启动流程以及自动配置实现原理。要掌握这部分核心内容,理解一些 Spring 框架的基础知识,将会让你事半功倍。
抛砖引玉:探索 Spring IOC 容器
如果有看过 SpringApplication.run() 方法的源码,Spring Boot 冗长无比的启动流程一定会让你抓狂。
透过现象看本质,SpringApplication 只是将一个典型的Spring应用的启动流程进行了扩展,因此,透彻理解 Spring 容器是打开 Spring Boot 大门的一把钥匙。
Spring IOC 容器
可以把 Spring IOC 容器比作一间餐馆,当你来到餐馆,通常会直接招呼服务员:点菜!至于菜的原料是什么?如何用原料把菜做出来?可能你根本就不关心。
IOC 容器也是一样,你只需要告诉它需要某个 bean,它就把对应的实例(instance)扔给你,至于这个 bean 是否依赖其他组件,怎样完成它的初始化,根本就不需要你关心。
作为餐馆,想要做出菜肴,得知道菜的原料和菜谱,同样地,IOC 容器想要管理各个业务对象以及它们之间的依赖关系,需要通过某种途径来记录和管理这些信息。
BeanDefinition 对象就承担了这个责任:容器中的每一个 bean 都会有一个对应的 BeanDefinition 实例。
该实例负责保存 bean 对象的所有必要信息,包括 bean 对象的 class 类型、是否是抽象类、构造方法和参数、其他属性等等。
当客户端向容器请求相应对象时,容器就会通过这些信息为客户端返回一个完整可用的 bean 实例。
原材料已经准备好(把 BeanDefinition 看做原料),开始做菜吧,等等,你还需要一份菜谱。
BeanDefinitionRegistry 和 BeanFactory 就是这份菜谱,BeanDefinitionRegistry 抽象出 bean 的注册逻辑。
而 BeanFactory 则抽象出了 bean 的管理逻辑,而各个 BeanFactory 的实现类就具体承担了 bean 的注册以及管理工作。
它们之间的关系就如下图:

BeanFactory、BeanDefinitionRegistry 关系图(来自:Spring 揭秘)
DefaultListableBeanFactory 作为一个比较通用的 BeanFactory 实现,它同时也实现了 BeanDefinitionRegistry 接口,因此它就承担了 bean 的注册管理工作。
从图中也可以看出,BeanFactory 接口中主要包含 getBean、containBean、getType、getAliases 等管理 bean 的方法。
而 BeanDefinitionRegistry 接口则包含 registerBeanDefinition、removeBeanDefinition、getBeanDefinition 等注册管理 BeanDefinition 的方法。
下面通过一段简单的代码来模拟 BeanFactory 底层是如何工作的:

这段代码仅为了说明 BeanFactory 底层的大致工作流程,实际情况会更加复杂。
比如 bean 之间的依赖关系可能定义在外部配置文件(XML/Properties)中、也可能是注解方式。
Spring IoC 容器的整个工作流程大致可以分为两个阶段:
①容器启动阶段
容器启动时,会通过某种途径加载 ConfigurationMetaData。除了代码方式比较直接外,在大部分情况下,容器需要依赖某些工具类。
比如:BeanDefinitionReader,它会对加载的 ConfigurationMetaData 进行解析和分析,并将分析后的信息组装为相应的 BeanDefinition。
最后把这些保存了 bean 定义的 BeanDefinition,注册到相应的 BeanDefinitionRegistry,这样容器的启动工作就完成了。
这个阶段主要完成一些准备性工作,更侧重于 bean 对象管理信息的收集,当然一些验证性或者辅助性的工作也在这一阶段完成。
来看一个简单的例子吧,过往,所有的 bean 都定义在 XML 配置文件中,下面的代码将模拟 BeanFactory 如何从配置文件中加载 bean 的定义以及依赖关系:

②Bean 的实例化阶段
经过第一阶段,所有 bean 定义都通过 BeanDefinition 的方式注册到 BeanDefinitionRegistry 中。



