源码深度解析Spring Bean的加载
在应用spring 的过程中,就会涉及到bean的加载,bean的加载经历一个相当复杂的过程,bean的加载入口如下:
使用getBean()方法进行加载Bean,最终调用的是AbstractBeanFactory.doGetBean() 进行Bean的加载。

doGetBean()源码如下:

从代码可看出Bean的加载过程可以分为一下几个步骤:
步骤一: 转换对应beanName
- 去除FactoryBean的修饰符,例如 name=“&aa”,则会先去除&成name=“aa”。调用BeanFactoryUtils.transformedBeanName(name) 方法进行去除"&",源代码如下:

- 取指定alias 所表示的最终beanName,canonicalName()方法实现使用alias做最终的beanName,源码如下:

步骤二: 尝试从缓存中加载单例
单例在Spring 的同一个容器内只会创建一次,后续在获取bean直接从单例缓存中获取,尝试从缓存中加载Bean,如果加载失败则再次尝试从SingletonFactories中加载.因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 创建bean 的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,当下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory.尝试从缓存中加载单例由重载的getSingleton()方法进行实现,源码如下

重载的getSingle()方法设计循环依赖的检测,以及多处变量的记录存取,此方法首先尝试从singletonObject 中获取实例,如果获取不到再从earlySingletoObjects里面获取,如果还获取不到,再尝试从singletonFactories 里面获取beanName对应的ObjectFactory,然后调用ObjectFactory.getObject() 来创建bean,并放到earlySingletonObjects里面去,并且从singletonFactories 中移除ObjectFactory.源代码如下:

尝试获取单例bean的流程如下:

步骤三:bean的实例化
如果从缓存职工得到了bean的原始状态,则需要对bean进行实例化,调用getObjectForBeanInstance()方法检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值,具体代码实现实现如下,

从代码中可以得知,getObjectForBeanInstance()做得更多的是功能性的判断,核心代码委托给getObjectFromFactoryBean()来实现了,而 getObjectForBeanInstance( )主要是完成一下几项工作:
第一: 对FactoryBean正确性的验证;
第二:对非FactoryBean不做任何处理;
第三:对bean进行转换;
第四:将从Factory中解析bean的工作委托给getObjectFromFactoryBean();
getObjectFromFactoryBean() 的作用是若 返回的bean是单例的就必须保证全局唯一, 正因使用了单例,使用功能缓存来提高性能.源代码如下:

在此方法中并没有看到核心代码 object = factory.getObject();, 而是再次调用了doGetObjectFromFactoryBean() 判断bean是否是FactoryBean类型,若是FactoryBean类型则当提取bean 时提取的并不是FactoryBean ,而是Factorybean中对应的getObject方法返回bean,doGetObjectFromFactoryBean()源代码如下:

步骤四:原型模式的依赖检查
只有在单例情况下才会尝试解决循环依赖,如果存在A中有B 的属性, B 中有A 的属性,
那么当依赖注入的时候,就会产生当A 还未创建完的时候因为对于B 的创建再次返回创建A,
造成循环依赖.

步骤五: 检测parentBeanFactory
检测如果当前加载的XML 配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory 去尝试下了,然后再去递归的调用getBean方法。判断语句为:

步骤六:将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition。
转换的原因是从XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,而bean后续的处理是针对RootBeanDefinition的, 在转换的过程中,如果父类bean不为空的话,也会一并合并父类属性、

方法源码简单,可自行查看,
步骤七: 寻找依赖
在Sring 的加载过程中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

步骤八:针对不同的scope进行bean的创建
在spring中存在着不同的scope,其中默认值是singleton,Spring 会根据不同的配置进行不同的初始化策略。

相关文章:
源码深度解析Spring Bean的加载
在应用spring 的过程中,就会涉及到bean的加载,bean的加载经历一个相当复杂的过程,bean的加载入口如下: 使用getBean()方法进行加载Bean,最终调用的是AbstractBeanFactory.doGetBean() 进行Bean的…...
STL——priority_queue
一、priority_queue介绍及使用 1.priority_queue文档介绍 (1)优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。 (2)此上下文类似与堆,在堆中可以…...
Springboot集成工作流Activity
介绍 官网:https://www.activiti.org/ 一 、工作流介绍 1.工作流(workflow) 就是通过计算机对业务流程自动化执行管理,它主要解决的是“使在多个参与这之间按照某种预定义规则自动化进行传递文档、信息或任务的过程,…...
2023软件测试工程师涨薪攻略,3年如何达到月薪30K?
1.软件测试如何实现涨薪 首先涨薪并不是从8000涨到9000这种涨薪,而是从8000涨到15K加到25K的涨薪。基本上三年之内就可以实现。 如果我们只是普通的有应届毕业生或者是普通本科那我们就只能从小公司开始慢慢往上走。 有些同学想去做测试,是希望能够日…...
Java面试——Spring Bean相关知识
目录 1.Bean的定义 2.Bean的生命周期 3.BeanFactory及Factory Bean 4.Bean的作用域 5.Bean的线程安全问题 1.Bean的定义 JavaBean是描述Java的软件组件模型。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生…...
上班在群里摸鱼,逮到一个字节8年测试开发,聊过之后羞愧难当...
老话说的好,这人呐,一旦在某个领域鲜有敌手了,就会闲得某疼。前几天我在上班摸鱼刷群的时候认识了一位字节测试开发大佬,在字节工作了8年,因为本人天赋比较高,平时工作也兢兢业业,现在企业内有一…...
HTTP、WebSocket和Socket.IO
一、HTTP协议 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)。HTTP 协议和 TCP/IP 协议族内的其他众多的协议相同, 用于客户端和服务器之间的通信。请求访问文本或图像等资源的一端称为客户端, 而提供资源响应的一端称…...
Fluent Python 笔记 第 11 章 接口:从协议到抽象基类
本章讨论的话题是接口:从鸭子类型的代表特征动态协议,到使接口更明确、能验证实现是否符合规定的抽象基类(Abstract Base Class,ABC)。 11.1 Python 文化中的接口和协议 对 Python 程序员来说,“X 类对象”“X 协 议”和“X 接口”都是一个…...
【Spark分布式内存计算框架——Spark Core】11. Spark 内核调度(下)
8.5 Spark 基本概念 Spark Application运行时,涵盖很多概念,主要如下表格: 官方文档:http://spark.apache.org/docs/2.4.5/cluster-overview.html#glossary Application:指的是用户编写的Spark应用程序/代码&#x…...
Java中的函数
1.String.trim() : 主要有2个用法: 1、就是去掉字符串中前后的空白;这个方法的主要可以使用在判断用户输入的密码之类的。 2、它不仅可以去除空白,还可以去除字符串中的制表符,如 ‘\t’,\n等。 2.Integer.parseInt() : 字符串…...
实验6-霍纳法则及变治技术
目录 1.霍纳法则(Horners rule) 2.堆排序 3.求a的n次幂 1.霍纳法则(Horners rule) 【问题描述】用霍纳法则求一个多项式在一个给定点的值 【输入形式】输入三行,第一行是一个整数n,表示的是多项式的最高次数;第二行多项式的系数组P[0...n](从低到高存储);第三行是…...
IP地址:揭晓安欣警官自证清白的黑科技
《狂飙》这部电视剧,此从播出以来可谓是火爆了,想必大家都是看过的。剧中,主人公“安欣”是一名警察。一直在与犯罪分子做斗争。 莽村的李顺案中,有匿名者这个案件在网上发帖恶意造谣,说安欣是黑恶势力的保护伞&#…...
考研复试机试 | C++
目录1.盛水最多的容器<11>题目代码:2.整数转罗马数字题目:代码:3. 清华大学机试题 abc题目题解4.清华大学机试题 反序数题目描述代码对称平方数题目代码:5. 杭电上机题 叠筐题目:代码pass:关于清华大…...
第四章.误差反向传播法—误差反向传播法实现手写数字识别神经网络
第四章.误差反向传播法 4.3 误差反向传播法实现手写数字识别神经网络 通过像组装乐高积木一样组装第四章中实现的层,来构建神经网络。 1.神经网络学习全貌图 1).前提: 神经网络存在合适的权重和偏置,调整权重和偏置以便拟合训练数据的过程称…...
IB学习者的培养目标有哪些?
IB课程强调要培养年轻人的探究精神,在富有渊博知识的同时,更要勤于思考,敢于思考,尊重和理解跨文化的差异,坚持原则维护公平,让这个世界充满爱与和平,让这个世界变得更加美好。上一次我们为大家…...
C++类基础(十三)
类的继承 ● 通过类的继承(派生)来引入“是一个”的关系( 17.2 — Basic inheritance in C) – 通常采用 public 继承( struct V.S. class ) – 注意:继承部分不是类的声明 – 使用基类的指针…...
03 OpenCV图像运算
文章目录1 普通加法1 加号相加2 add函数2 加权相加3 按位运算1 按位与运算2 按位或运算、非运算4 掩膜1 普通加法 1 加号相加 在 OpenCV 中,图像加法可以使用加号运算符()来实现。例如,如果要将两幅图像相加,可以使用…...
【C语言学习笔记】:动态库
一、动态库 通过之前静态库那篇文章的介绍。发现静态库更容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢? 1、为什么还需要动态库? 为什么需要动态库,其实也是静态库的特点导致。 ▶ 空间浪费是静…...
Zookeeper
zookeeper是一个分布式协调服务。所谓分布式协调主要是来解决分布式系统中多个进程之间的同步限制,防止出现脏读,例如我们常说的分布式锁。 zookeeper中的数据是存储在内存当中的,因此它的效率十分高效。它内部的存储方式十分类似于文件存储…...
wav转mp3,wav转换成mp3教程
很多使用音频文件的小伙伴,总会接触到不同类型的音频格式,根据需求不同需要做相关的处理。比如有人接触到了wav格式的音频,这是windows系统研发的一种标准数字音频文件,是一种占用磁盘体积超级大的音频格式,通常用于录…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
