springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点

手稿做题图

本文所有讲解图均属原创,转载请注明出处。

文章原意为一次讲解准备,以图片为主。

主要讲的内容:从jar包包装、fat jar如何被加载执行,到SpringBootApplication的生命周期,上下文的概念和引入节点,到重点讲Bean自动装载自动配置的核心主线(调用链)。内容旨在提纲挈领,希望能为初学者消除代码黑洞恐惧,为进阶者拨开迷雾

本文算是一种面向切面讲解,只抽取了SpringBoot体系中Bean自动装配生命周期涉及到的核心调用链切面进行介绍。涉及到的类和函数相对于整个SpringBoot源代码数量上只是冰山一角,但从开发者角度和Spring设计理念来讲,这条线却是最为精粹。

每一个函数都对应着具体关键路径,每条路径都是经过很久的源码和材料的阅读、断点不断的试错摸索确认出来的。聚焦主流程,稍有不相干的都已经剔除,避免干扰。希望真正想了解自动装配原理的小伙伴一定仔细跟一遍。

图中表达约定ClassName#functionName

讲解对应SpringBoot 2.3.4,其他2.*版本会有细微差别,1.*版本则完全不同。

准备前提

本文想讲的不是第一次Helloworld,以下需要准备的内容默认已有、会用。

1、java 1.8/8

2、maven3.3以上

3、Idea

4、最快的获取一个SpringbootApplication的方式是:

https://start.spring.io/​start.spring.io

SpringBoot上下游关系

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第1张图片
SpringBoot在整个Spring体系中上下游关系

SpringBoot应用分类

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第2张图片
当前SpringBoot应用的概要分类

Reactive Web是以后的方向,是对Spring体系下,对整个前后台的编程思维和手法带来一次革新,此处安利一本书Hands-On Reactive Programming in Spring5。

流程部分总图

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第3张图片
本文后续内容流程总图

SpringBoot应用部署包及启动原理

讲***.jar.original更改后缀解压后,其实它就是原jar包,大小很小,只包含程序中新建源代码编译后的内容。

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第4张图片
original为原包,jar为包装后FAT包

内部组织结构与源码组织结构一样。

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第5张图片
与源码结构吻合

***.jar包是SpringBoot包装后的jar包,包装的意义是:

1、加入标准jar包启动类,让java在无感知的情况下可以直接启动。

2、打包springframework-boot-loader核心启动类

3、打包当前应用独立运行不可或缺的各种依赖

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第6张图片
FAT JAR 包含标准jar启动入口配置文件MANIFEST.MF

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第7张图片
java并不知道这是个特殊的jar包

现在我们开始打通从Main-Class到Start-Class这段流程,需要先通过添加依赖引入Main-Class:中包含的org.springframework.boot.loader.JarLauncher类。(这里与JarLauncher对应的还有一个WarLauncher兼容WAR包部署)


			

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第8张图片
从JarLauncher到Start-Class

到这里咱们的SpringBoot应用从工程角度就跑起来了,如果看懂了以上部分,跟原来一脸懵逼的看着各种眼花缭乱的命令行往外蹦不一样,这次跑起来你知道它是打哪来,准备往哪去了。

SpringBoot应用生命周期

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第9张图片
进了main函数就进了SpringBoot的应用

Bean生命周期(自动装配)获取Bean定义集合

Bean生命周期(自动装配),整个过程中涉及的分支太多太多,各种类的名字又特别相似(被各种类名接口名绕晕的看这个Spring 4.x-Context的UML类图),一两本五百页的书都不一定能讲得清楚、讲的完整(例如《Spring Boot 编程思想》到最关键的refresh部分直接一带而过),下三张图花了很长很长时间才理清楚,是本文最最核心和valuable的内容,希望能给在源码里迷路的人做个导航。

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第10张图片

一切动作都是为了最终的Bean定义集合:beanDefinitionMap。中间主要的获取路径有两条,上图中红色路径箭头为分开点:

1、通过ComponentScanner扫描全部@Component及其派生注解标识的类,此路径主要用于自编程代码,取代原先springboot1.* xml标记时代bean.xml内手动组装的Bean内容,体现自动装配中的“自动”,其本质就是通过Scanner扫描@Component

2、通过ImportSelector从spring.factories文件中获取自动配置类,此路径用于解耦三方件之间的依赖,也就是我们代码从pom里引入其他模块是为什么也能够自动装配上里面的Bean。如果我们的程序写完也作外用,那么spring.factories这里面的key-value一定要仔细认真的核对。该文件里同时定义了各种上下文初始化器和事件监听器,非常重要。源码里位置放在srcmainresourcesMETA-INFspring.factories

填满beanDefinitionMap后Bean定义集合获取完毕。

Bean生命周期(自动装配)实例化Bean定义

实例化好之后放入singletonObjects,singletonFactories。

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第11张图片

@Autowired实例化过程,Bean实例化时候先放入三级缓存,进入下图的一系列确认和排查筛选出有@Autowired注解的已经实例化的Bean,如果有,将对应属性的Bean实例化,如果没有就将三级缓存的Bean 放入一级缓存中。

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第12张图片

@Autowired真的也是突出自动装配中“自动”二字的利器。

Runing

springboot2.3.5 获取bean_SpringBoot应用及Bean自动装配生命周期关键节点_第13张图片

最后

可能大家觉得还有很多重要的部分都没有讲,比如:消息事件体系、自动化参数配置、LifecycleProcessor、注解驱动等等。原因如开头所说,聚焦核心流程,避免干扰。后续另篇再述。

Spring体系太宏大,其中思想绝不是老瓶子装新酒或工程性优化这么简单,在国内各大互联网大厂的推动下,国内的参与度和贡献都很高,可以说是理论与实践均没输在起跑线上。是软件攻城狮们非常优选的一个职业深耕方向。

最后针对代码黑洞和代码走读迷路的情况加说一句:编程的世界里没有巧合,每个能出水的水龙头背后肯定不只是墙。仔细耐心一点慢慢看,最后会有那么一行code让你豁然开朗,那种感觉倍儿爽。

同时对各类框架和三方件要相信并遵守契约精神,敢用,大胆地用!

你可能感兴趣的:(springboot2.3.5,获取bean,springboot源码,红色J,解决,IDEA)