服务启动堪称 Spring 源码设计的答案;
一、背景阐明
初学 SpringBoot 框架时,第一次启动服务,直呼什么鬼?只须要简略的几步配置,几个外围的注解,就能够疾速实现工程的搭建和运行;
尽管从 Spring 框架迁徙到 SpringBoot 框架,在初期会有很多的不适应,然而更好用的框架会疾速失去认可,从而成为支流的技术选型;
对于大多数的框架或者组件来说,如果应用起来越是简便,那么其外部的封装策略就越是简单;
比方在 Spring 框架更新到 SpringBoot 版本时,其用法的简便与外部封装的复杂性曾经造成强烈的比照;再到 SpringCloud 微服务框架时,其封装逻辑简单到离谱;
对于服务端的开发来说,绕不开对 Spring 框架的深度学习,如果单纯站在源码浏览的角度,倡议先熟读 SpringBoot 启动流程,而后再适当扩大其余源码块;
二、SpringBoot 工程
首先聊一聊浏览源码的基本思路,从一个极简的案例开始,围绕案例中的外围 API 作为切入点,通过对源码逻辑的断点调试,从而领会其设计的原理;
浏览 SpringBoot 的源码,能够从服务启动办法作为切入点,而后一直的剖析启动过程波及到的外围 API 和设计原理,再基于具体的启动日志去剖析形象的加载逻辑;
在看具体的源码之前,还须要说下剖析思路,Spring 我的项目中,要留神每个 API 所属工程与层级,而后再去剖析 API 之间关系,外围的结构、属性、办法等;
在 SpringBoot 的启动类中,有两个外围的切入点,一个是类的构造方法,实现一列的初始化动作;一个是启动办法,实现利用上下文的创立和装载;
构造方法:
启动办法:
须要阐明的是,因为 SpringBoot 服务启动过程波及源码过多,所以下面的源码中只是列举局部的外围切入点,而后围绕这些要害流程开展,剖析一些常见的源码设计;
另外阐明一点,以下源码的外围版本:JDK-1.8
,spring-5.2.4
,spring-boot-2.2.5
,在不同的版本下源码会存在差别;
三、利用上下文
服务启动时,依据利用类型判断创立的上下文,此处启动的是基于 servlet 的 web 利用,所以也依赖相应的 web 服务器,默认为 Tomcat;
启动办法的外围在于对利用上下文的创立、筹备、刷新,利用上下文是一个非常形象的形容,能够了解为利用运行的整体环境,其中波及到资源加载,配置文件拆卸,运行服务的治理等,后续的源码剖析都围绕该 API 开展;
ApplicationContext:利用上下文外围接口,在该接口中所有的办法都是只读模式,即只能通过 Get 办法进行拜访;
ConfigurableApplicationContext:上下文配置扩大接口,提供了利用上下文的配置能力,生命周期的保护,以及在敞开之后的相干资源开释;
AbstractApplicationContext:上下文接口形象实现,外围的 API,对利用上下文中的公共能力做了实现;
ConfigurableWebApplicationContext:Web 利用上下文配置扩大接口,提供了 Web 利用的上下文配置能力;
WebServerApplicationContext:Web 服务上下文,创立并治理 Web 利用的服务器,在该流程中嵌入的是 Tomcat 服务;
依据利用上下文几个外围的 API 设计,领会 Spring 源码的设计思路,从顶级的接口开始,一直向下扩大并且新增办法,了解形象实现类的逻辑,以及服务运行时所依赖的具体 API;
四、资源加载
什么是资源,能够是各种类型的文件和配置,字节输出流的转换,也能够是 URL 资源定位,Spring 框架在运行的过程中,须要依赖 Resource 接口实现对底层资源的拜访;
Resource:资源形容的顶级接口,提供了一系列的办法,继承 InputStreamSource 接口,反对将资源转换为流的模式操作;
AbstractResource:资源拜访的形象实现类,这里的设计原理与 AbstractApplicationContext 相似,提供资源拜访办法的根底实现;
ResourceLoader:资源加载的封装接口,利用下文须要依赖该接口实现资源的获取与拜访;
针对不同利用场景需要,Resource 接口的实现类有如下几个:FileSystemResource 文件系统资源,ClassPathResource 类门路下资源,InputStreamResource 输出流资源等;
五、应用环境
对于 Property 和 Environment 源码设计体系,参考上述的源码模块,在思路上是类似的,此处不多形容;
应用程序的属性和环境波及到的参数形容十分多,比拟间接的伎俩是通过 System 类中的办法输入,至于信息如何加载,在 StandardEnvironment 类中提供了办法,能够断点查看;
六、Bean 对象
基于 Spring 框架的应用程序中,由 Spring 容器负责创立,拆卸,设置属性,进而治理整个生命周期的对象,称为 Bean 对象;Bean 的生命周期非常复杂,过程大抵如下:实例化,属性加载,初始化前后治理,销毁;
BeanFactory:工厂类,Spring 框架的外围能力,Bean 容器的顶级接口,提供了一系列 Bean 对象的拜访办法,是 IOC 思维和依赖注入的根底撑持;
ConfigurableBeanFactory:Bean 容器可配置化接口,该扩大接口只是为了容许框架外部的即插即用和拜访 bean 工厂的配置办法;
AbstractBeanFactory:Bean 治理的形象实现类,能够查看其外部 doGetBean 办法,提供 Bean 实例对象的获取逻辑,如果无奈获取则执行创立逻辑;
七、Tomcat 服务
首次启动 SpringBoot 工程时,最大的疑难就是可见 Tomcat 启动日志,然而没有显式的做服务器拆卸,间接启动 JAR 包即可,这在流程上简化了一大步;
WebServer:Web 应用服务器接口,比方罕用的 Tomcat,Jetty,Netty 等,依据利用类型抉择,只提供了启动、进行、获取端口三个办法,通过 WebServerApplicationContext 与利用上下文相关联;
TomcatWebServer:SpringBoot 框架治理内置 Tomcat 服务的外围类,对 Tomcat 生命周期的治理提供了一层包装;
Tomcat:Apache 组件中轻量级 Tomcat 启动器,提供了 Tomcat 根底配置,比方默认的 Port 和 HostName,以及生命周期治理的办法,TomcatWebServer 类中调用的就是该 API 中的具体方法;
八、事件模型
事件驱动模型是简单流程中的罕用解耦伎俩,即通过事件发送和监听两个拆解动作,实现流程的分步执行,这在 SpringBoot 启动流程和上下文装载中更是施展的酣畅淋漓;
ApplicationEvent:利用事件根底抽象类,继承自 JDK 中 EventObject 类,具体事件会继承该类,外部申明了事件源和产生工夫两个外围属性;
ApplicationEventMulticaster:利用事件播送的顶级接口,能够将指定的利用事件播送给适宜的监听器;
SimpleApplicationEventMulticaster:利用事件播送接口的简略实现,能够断点该类的 multicastEvent 办法,查看播送时利用事件和其相应的监听器;
ApplicationListener:利用事件监听器接口,继承自 JDK 中 EventListener 接口,Spring 中扩大了多种具体的事件监听器,以实现各种不同的场景需要,比方最常见的 ConfigFileApplicationListener 配置文件监听器;
九、配置加载
SpringBoot 工程中,配置文件的管理策略非常复杂,有外部程序执行加载配置,也有内部集成的组件配置,当然最外围的就是工程的自定义配置;
ConfigFileApplicationListener.Loader:配置文件监听器的外部类,实现对工程中的配置源加载,其外围逻辑在 Loader.load 办法中实现,具体逻辑由相干的实现类实现;
PropertySourceLoader:配置加载的策略接口,在 Spring 工程中反对多种类型的文件配置,比方 yml、yaml、properties、xml,须要通过文件的扩展名抉择相应的加载实现类;
YamlPropertySourceLoader:加载 .yml
或者 .yaml
类型的文件,SpringBoot 工程中罕用的配置文件类型,最终转换成 Name 和 Value 的属性源汇合,即通过 PropertySource 抽象类来形容;
十、数据库集成
Spring 框架的弱小之处还在于可能和其余组件进行简略疾速的集成,比方罕用的数据库、缓存、音讯队列等各种类型的组件,剖析外部的集成逻辑,会发现很多原理上的相似性,尤其在 SpringBoot 框架中,约定大于配置;
DataSourceAutoConfiguration:SpringBoot 工程中数据库的自动化配置类,在配置中 Hikari 是默认抉择的连接池,也是号称速度最快的;
DataSourceProperties:数据源配置相干的根底类,在 DataSourceConfiguration 配置类中,会基于参数去创立数据源对象;
HikariDataSource:Hikari 连接池组件中的数据源 API,形容数据源的具体信息,例如配置、连接池、状态等,具体的数据库连贯逻辑是在该组件外部实现的;
基于 SpringBoot 集成数据库的原理,能够扩展性的看看:Redis 组件的 RedisAutoConfiguration 配置类;Kafka 组件的 KafkaAutoConfiguration 配置类,Elasticsearch 组件的 RestClientAutoConfiguration 配置类,在设计原理上都有殊途同归之妙;
写在最初
从集体教训来看,想要浏览 Spring 框架的源码设计,须要基于利用流程先构建一个大的轮廓构造,了解设计中的罕用策略和原理,而后再深刻单个模块的细节逻辑,这样容易找到浏览节奏;
本文并没有波及源码中过多的细节逻辑,只是从服务启动作为切入点,整顿与开发关联性较为间接的源码模块,形容集体对于 Spring 源码浏览的根底思路。
十一、参考源码
利用仓库:https://gitee.com/cicadasmile/butte-flyer-parent
组件封装:https://gitee.com/cicadasmile/butte-frame-parent