服务启动堪称Spring源码设计的答案;

一、背景说明

初学SpringBoot框架时,第一次启动服务,直呼什么鬼?只需要简单的几步配置,几个核心的注解,就可以快速实现工程的搭建和运行;

虽然从Spring框架迁移到SpringBoot框架,在初期会有很多的不适应,但是更好用的框架会快速得到认可,从而成为主流的技术选型;

对于大多数的框架或者组件来说,如果使用起来越是简便,那么其内部的封装策略就越是复杂;

比如在Spring框架更新到SpringBoot版本时,其用法的简便与内部封装的复杂性已经形成强烈的对比;再到SpringCloud微服务框架时,其封装逻辑复杂到离谱;

对于服务端的开发来说,绕不开对Spring框架的深度学习,如果单纯站在源码阅读的角度,建议先熟读SpringBoot启动流程,然后再适当扩展其他源码块;

二、SpringBoot工程

首先聊一聊阅读源码的基本思路,从一个极简的案例开始,围绕案例中的核心API作为切入点,通过对源码逻辑的断点调试,从而体会其设计的原理;

阅读SpringBoot的源码,可以从服务启动方法作为切入点,然后不断的分析启动过程涉及到的核心API和设计原理,再基于具体的启动日志去分析抽象的加载逻辑;

在看具体的源码之前,还需要说下分析思路,Spring项目中,要注意每个API所属工程与层级,然后再去分析API之间关系,核心的构造、属性、方法等;

在SpringBoot的启动类中,有两个核心的切入点,一个是类的构造方法,完成一列的初始化动作;一个是启动方法,实现应用上下文的创建和装载;

构造方法

启动方法

需要说明的是,由于SpringBoot服务启动过程涉及源码过多,所以上面的源码中只是罗列部分的核心切入点,然后围绕这些关键流程展开,分析一些常见的源码设计;

另外说明一点,以下源码的核心版本:JDK-1.8spring-5.2.4spring-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

从SpringBoot启动,阅读源码设计的更多相关文章

  1. SpringBoot启动tomcat源码解读

    一.SpringBoot自动拉起Tomcat 原文链接:http://www.studyshare.cn/blog-front/blog/details/1136 SpringBoot框架是当前比较流 ...

  2. 带着萌新看springboot源码11(springboot启动原理 源码上)

    通过前面这么多讲解,springboot原理应该也大概有个轮廓了,一些基本的配置,从客户端url到controller(配置一些要用的组件,servlet三大组件,处理器映射器,拦截器,视图解析器这些 ...

  3. SpringBoot启动注解源码流程学习总结

  4. Zookeeper_阅读源码第一步_在 IDE 里启动 zkServer(集群版)

    上篇文章Zookeeper_阅读源码第一步_在 IDE 里启动 zkServer(单机版)讲了在 idea 里以单机的方式启动zookeeper,这篇介绍一下以集群的方式启动. 集群方式启动,才会真正 ...

  5. 基于SpringBoot的Environment源码理解实现分散配置

    前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...

  6. 【转】使用 vim + ctags + cscope + taglist 阅读源码

    原文网址:http://my.oschina.net/u/554995/blog/59927 最近,准备跟学长一起往 linux kernel 的门里瞧瞧里面的世界,虽然我们知道门就在那,但我们还得找 ...

  7. Spring源码解析——如何阅读源码(转)

    最近没什么实质性的工作,正好有点时间,就想学学别人的代码.也看过一点源码,算是有了点阅读的经验,于是下定决心看下spring这种大型的项目的源码,学学它的设计思想. 手码不易,转载请注明:xingoo ...

  8. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

  9. Spring源码解析——如何阅读源码

    最近没什么实质性的工作,正好有点时间,就想学学别人的代码.也看过一点源码,算是有了点阅读的经验,于是下定决心看下spring这种大型的项目的源码,学学它的设计思想. 手码不易,转载请注明:xingoo ...

随机推荐

  1. 二重循环中的break与continue

    二重循环中的break和continue用于控制本层循环,注意其不会影响外层循环的执行,这边和C中的break和continue的作用范围是一样的,也符合逻辑 example: 点击查看代码 for ...

  2. 计算机二级Python(第一阶段)

    介绍   本篇文章主要针对于计算机二级考试的崽崽,当然想了解Python和学习Python的崽崽也是可以看本篇文章的:毕竟,手机和电脑都可以运行Python:本篇我文章虽然是笔记,但是也纯靠手打,希望 ...

  3. BufferedWriter字符缓冲输出流和BufferedReader字符缓冲输入流

    package com.yang.Test.BufferedStudy; import java.io.BufferedWriter; import java.io.FileWriter; impor ...

  4. 只会Excel想做图表可视化,让数据动起来?可以,快来围观啦(附大量模板下载)

    前言 之前我们分享过基于echarts 的数据可视化展示,很多朋友就说,不会软件开发,可不可以直接用Excel进行数据化的展示. 答案是肯定的,确实有这种方案,百度查询一查一大推,各种解决方案各种模板 ...

  5. Windows高效开发环境配置(一)

    更多精彩内容,欢迎关注公众号:逻魔代码 前言 用了多年的 MacOS 做开发,一系列诸如 Alfred.Item2.Oh-my-zsh 之类的工具,大大地提升了工作的效率和使用舒适度.新工作不给配 M ...

  6. Axure RP 8 实现 圆角文本框 圆角带筛选的下拉列表框 可自动显示滚动条

    刚开始用Axure 会发现 Axure 元件库并不是很齐全,很多元件需要自己想办法解决 或者去网上去找.其实个人建议网上有现成的元件可以就下载就不必花时间去折腾.除非你也想练练手,原型这种东西除非高保 ...

  7. LuoguP1922 女仆咖啡厅桌游吧 (树形动态规划)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  8. 慢SQL,压垮团队的最后一根稻草!

    一.什么是慢 SQL 什么是慢SQL?顾名思义,运行时间较长的 SQL 语句即为慢 SQL! 那问题来了,多久才算慢呢? 这个慢其实是一个相对值,不同的业务场景下,标准要求是不一样的. 我们都知道,我 ...

  9. Web 前端模块出现的原因,以及 Node.js 中的模块

    模块出现原因 简单概述 随着 Web 2.0 时代的到来,JavaScript 不再是以前的小脚本程序了,它在前端担任了更多的职责,也逐渐地被广泛运用在了更加复杂的应用开发的级别上. 但是 JavaS ...

  10. 【漏洞分析】KaoyaSwap 安全事件分析

    相关信息 KaoyaSwap 是 BSC 链上的一个自动做市商 AMM.然后,现在他们的官网 https://www.kaoyaswap.com/ 已经打不开了(如果我打开方式没错的话).所以就直接进 ...