Spring源码里开天辟地的五个Bean,再介绍一个学习方法

news2025/7/12 7:35:39

                                    准备工作

首先咱们还是来写一个最简单的例子:

用的还是 https://github.com/xiexiaojing/yuna 里的代码,只是标签和引用都换成了Spring原生的。

配置类就是配置了扫描路径:

在可以被扫描的包路径下定义了一个Bean对象。用了Component注解这里就可以理解为Bean对象了。

运行成功,通过Spring的IoC容器成功的获取了UserService的Bean对象,并调用了其test方法。

在《把对象交给spring管理的3种方法及经典应用》中我提到Spring有5个开天辟地的Bean。还列出了怎么通过SpringBoot的debug去找。这里其实在debug日志里就能看到把它们打印出来了:

​大家不要忽略启动日志,读懂启动日志能获得很多信息,今天咱们就把这段启动日志Spring相关的部分分析透。

                       Spring启动日志第一行

org.springframework.context.annotation.AnnotationConfigApplicationContext

-

Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5bfbf16f

上面是Spring日志的第一行,翻译成中文就是刷新注解配置应用上下文。咱们来看源码:

进入这个实例化方法中看Spring的源码:

共三行,咱们来解读一下:

this初始化方法,里面初始化的后面都要用到,用到的时候再看,这一行可以忽略。剩余两行,一行作用是注册Bean的定义,另外一行是完成Bean的定义。

先时候注册Bean的定义。什么叫Bean的定义呢。如果Bean是一个产品,那Bean定义就是它的规格说明书。就是一个文档说明,这时候Bean还没有开始创建。注册Bean定义还有一种通过扫描来实现的方式:

这时候进入Spring注解配置应用上下文的实例化方法变成这个:

​第二行register方法变成scan方法,其他没有变化,这说明scan方法和register方法完成了两种的功能。就是BeanDefinition。scan的原理我在《手撕spring核心源码,彻底搞懂spring流程》里详细讲过,这就和之前的内容对上了。

创建的事情要交给Bean工厂,也就是refresh方法要做的事情。

其实Bean工厂能不能完成Bean的创建等生命周期管理呢?可以。咱们的测试例子也可以这么写:

​我直接用Bean工厂创建一个Bean也能实现。那ApplicationContext应用上下文与BeanFactory的区别在哪里呢?

BeanFactory可以理解为一个汽车工厂,它就是生产汽车的。 别人需要告诉他汽车怎么生产,看我例子里BeanDeclaration实际有很多参数需要我来添上,我展开给大家看看:

ApplicationContext 可以理解为汽车4s店。他提供一条龙服务。我只需要告诉他,我需要哪个汽车,其他都不需要管了。4s店自己帮我处理好。

咱们来看refresh方法,synchronized是多线程同步的,不需要管。第一个运行的方式是prepareRefresh。

​进入这个方法就找到了第一行日志打印的地方:

咱们来看prepareRefresh主要做的4件事情:

1、初始化占位符属性的资源

2、检验所有必需的属性都是可解析的

3、存储应用监听器或者应用监听器半成品

4、初始化应用事件半成品

​这四件事情不是本文的核心内容仅做了解。其实这四件事情对下文没有任何推动作用,这就是源码存在太多细枝末节,容易干扰视线的原因。所以要带着明确的目的去看。

                          Spring启动日志第二行

org.springframework.beans.factory.support.DefaultListableBeanFactory

-

Creating

shared

instance

of

singleton

bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'

这是Spring开天辟地的五个Bean中的第一个。类型是

ConfigurationClassPostProcessor

它是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。

找一行日志打印的位置有点困难,咱们用debug的方式找到哪一行打印的。最终定位在这里:

下面咱们站在上帝视角重新回到refresh方法:

refresh的前面都是在组建Bean工厂,从533行也就是内部会打印咱们这条日志的这一行开始调用Bean工厂后置处理器。Bean工厂后置处理器与Bean后置处理器不是一回事。Bean工厂后置处理器的作用就是前面Bean工厂组建完成,现在可以把组建好的Bean工厂传给这个后置处理器。后置处理器自己可以决定要对Bean工厂做些什么。

因为最重要的方法都在这里面,咱们直接来看

PostProcessorRegistrationDelegate

里面做了什么

​日志是从标红的那行代码打印的,这是触发实现了高优先级的

BeanDefinitionRegistryPostProcessor

进行实例化并注册成后置处理的类。从这里咱们可以得出结论:Spring给它排了很高的优先级,对于Spring默认来说配置类解析器是最先被加载的后置处理器。

                      Spring启动日志第三行

org.springframework.context.annotation.ClassPathBeanDefinitionScanner

-

Identified

candidate

component

class:

file [D:\yuna\target\classes\com\brmayi\yuna\newspring\UserService.class]

这是验证用户bean是否符合要求的,可debug查看不详细解释。

Spring其他4个开天辟地的Bean

其他的由于方法相同,这里只介绍其他4个Bean的作用:

EventListenerMethodProcessor和 DefaultEventListenerFactory

DefaultEventListenerFactory是一个Bean工厂,

EventListenerMethodProcessor 是 Bean工厂的一个后置处理器, 用来对 @EventListener 提供支持。

AutowiredAnnotationBeanPostProcessor

使用Spring 编程时,使用Ioc,我们只需要声明对象,而由Spring 替我门自动注入,

而其中起重要作用则为

AutowiredAnnotationBeanPostProcessor,

它在bean实例化后,进行这重要的初始化操作。

CommonAnnotationBeanPostProcessor

这个Bean后置处理器通过继承

InitDestroyAnnotationBeanPostProcessor

对@ javax.annotation.PostConstruct

和@ javax.annotation.PreDestroy

注解的支持。以及依据bean name依赖注入的

@javax.annotation.Resource支持。

总结

本文介绍了使用查日志所在位置的方式学习源码。这种方式在文中我也特意举例说明了容易被带偏,偏离重心,要做好时间和学习规划,才能达到好的效果。

学习Spring不是一件容易的事,我之前学习的时候放弃过很多次。这期间不断变换学习方法重新学。最终突然达到了“蓦然回首”的顿悟。从此再看Spring都不是事儿。

从那之后再也不会因为手欠升级了某个版本或者删除了某些理论上不相关的依赖,程序运行不起来各种尝试才搞定。而变成了遇到问题,呆呆的想上一小会,定位一段源码验证一下猜想,做个简单的调整就搞定了。

假期哪里也去不了,在家看了一些过去的高分电影。很多电影反映了一些底层贫苦人民暗无天日的生活,一直到最后,他们的生活仍然没有一丝希望。咱们现在可能会经历一些小的痛苦,比如学Spring就很苦,但是这是带着希望的苦。喝下之后就像咖啡一样回味悠远~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/17933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java#16(包装类和集合练习)

目录 基本数据类型对应的包装类: 一.添加学生对象并遍历 二.添加用户对象并判断是否存在 三.添加手机对象并返回要求的数据 基本数据类型对应的包装类: byte------>Byte short------->Short char------->Character int------->Integer long------->Long flo…

MRT(MODIS Reprojection Tool) 下载及安装教程

大家下载MODIS数据的时候,大多是hdf的格式数据。HDF数据包括11个波段的数据(如下图),假如想要其中一个波段数据,我们需要批量提取,这时就要用到NASA提供的MODIS Reprojection Tool,此工具虽不能…

c++ 指针,new运算符

1、指针相关基础知识: 1.1、指针一般指向变量的地址,等同于变量名前加&,如下: int a 3; int* p; p &a; 1.2、 * 符号被称为间接值运算符或解除引用运算符,将其运用于指针,可以获取指针指向的值…

【Java八股文总结】之IO流

文章目录Java IO流一、IO基础知识1、字节流2、字符流3、字节缓冲流4、打印流5、随机访问流6、字节流和字符流的区别?二、IO设计模式1、装饰器模式2、适配器模式Q:适配器模式和装饰器模式的区别?3、工厂模式4、观察者模式三、IO模型详解&#…

柯桥留学日语培训机构有吗日本人平时都喝什么酒?

日本葡萄酒侍酒大师高野丰先生,带来一瓶在北海道发现的陈年白兰地。 那是2014年的事,高野先生去北海道十胜地区的一家葡萄酒厂考察,在一个多年未开启的葡萄酒储存库的角落里,发现了一只陈旧的酒桶,他很好奇地问酒厂的…

Javaweb filter过滤器 跟 listener监听器

Filter 权限控制:登录才能进数据库等 统一编码:统一各种编码 Filter快速入门 放行前,我们对request里的数据进行处理 处理完,然后放行,携带到对应的资源里去 放行后,对response的数据进行处理 //将re…

C/C++问题:一个指针的大小是多少?怎么理解指针变量的存在

目录 举例 一、 int a; int (*(*v)[])(); 二、 int func(); int (*func)(); 三、 const; int const a; const int a; int const*r; int *const r; 四、一个指针的大小是多少?(补充) 举例 一、 int a; 可以看到上面声明了一个变…

【MySQL基础】SQL语言的概述、组成及特点

目录 一、SQL的概述 二、SQL语言的组成 三、SQL语言的特点 语法特点: 💟 创作不易,不妨点赞💚评论❤️收藏💙一下 一、SQL的概述 SQL全称: Structured Query Language,是结构化查询语言&am…

数据结构先序序列创建二叉树

2022.11.19连发两回。 先序序列创建二叉树任务描述相关知识编程要求测试说明C/C代码任务描述 本关任务:利用先序遍历创建二叉树,并给出相应二叉树的中序遍历结果。 相关知识 为了完成本关任务,你需要掌握:1.二叉树的前序遍历&a…

win11系统下,迅雷启动后闪退的问题

win11系统,迅雷最新版本。 之前用迅雷一直好好的,某天要下东西突然发现点击就闪退,进程管理器里一点痕迹都没有。 启动就闪退,没有一点点痕迹。 因为之前是win10系统,一直用的好好的,考虑是不是win11系统…

创建自己数据集全套流程

目录 1、准备自己具有的数据集 2、标注数据----json格式 3、标注数据转为分割图----voc格式 4、增广数据集 5、分训练集以及验证集 1、准备自己具有的数据集 注意:数据集必须是统一的后缀格式,jpg或者png 2、标注数据----json格式 采用labelme标注…

前后端分离项目(vue+springboot)集成pageoffice实现在线编辑office文件

前后端分离项目下使用PageOffice原理图 集成步骤 前端 vue 项目 在您Vue项目的根目录下index.html中引用后端项目根目录下pageoffice.js文件。例如&#xff1a; <script type"text/javascript" src"http://localhost:8081/samples-springboot-back/pageof…

gom传奇引擎无限蜂功能插件安装图文教程

无限蜂功能插件安装教程 1. 百度搜索无限蜂官网,下载功能插件程序&#xff0c;请下载最新版&#xff01;2. 下载无限蜂功能插件&#xff0c;到桌面&#xff0c;并进行解压&#xff0c;如下图所示。 3. 打开无限蜂功能插件控制台(?.?.?)&#xff0c;进行账号注册。 4. 注册成…

InnoDB之Undo log格式

1. 前言 InnoDB有两大日志模块&#xff0c;分别是redo log和undo log。为了避免磁盘随机写&#xff0c;InnoDB设计了redo log&#xff0c;数据写入时只写缓冲页和redo log&#xff0c;脏页由后台线程异步刷盘&#xff0c;哪怕系统崩溃也能根据redo log恢复数据。但是我们漏了一…

STC51单片机32——液晶1602显示

//用LCD循环右移显示字符 //开发板上的跳帽连接Vcc #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 sbit EP2^7; //使能信号位&#xff0c;将E位定义为P2.7引脚 sbit RSP2^6; //寄存器选择位&#…

Js逆向教程-09常见的加密方式

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; Js逆向教程-09常见的加密方式 常见的加密方式 一、js逆向流程 抓包调试扣去js改写本地运行 二、常见的加密方式 2.1取盐校验 不可…

【考研复试】计算机相关专业面试英语自我介绍范文(一)

文章目录前言&#xff1a;1.第一段&#xff1a;打招呼寒暄2.第二段&#xff1a;自我介绍3.第三段&#xff1a;为什么要读研4.第四段&#xff1a;个人优势5.第五段&#xff1a;立flag前言&#xff1a; 英语面试第一件事情就是让考生做自我介绍&#xff0c;考官可以借此机会了解…

图片编辑软件怎样加文字内容?图片添加文字方法大分享

大家平时在分享自己拍摄的照片时&#xff0c;有些时候会不会觉得照片有点单调&#xff0c;想在上面添加一些文字来装饰图片呢&#xff1f;又或者是在日常生活中&#xff0c;不小心拍到朋友的搞怪表情&#xff0c;这时候要是加上一些有趣的文字&#xff0c;就可以免费获得一个表…

Design A Twitter

title: Notes of System Design No.04 —Design a Twitter description: ’ Design a Twitter ’ date: 2022-05-14 09:50:32 tags: 系统设计 categories: 系统设计 00.What is Twitter 注&#xff1a;TimeLine 就是按照时间顺序显示的信息流 01. Functional Requirements 1…

特征工程(六)—(1)利用PCA进行特征转换

(1)鸢尾花数据集的手动处理 PCA利用了协方差矩阵的特征值分解 过程如下&#xff1a; (1)创建数据集的协方差矩阵 (2)计算协方差矩阵的特征值 (3)保留前K个特征值(按照特征值降序排列) (4)要保留的特征向量转换新的数据点 1、加载鸢尾花数据集 import matplotlib as mpl # 解…