从根儿上学习spring 十一 之run方法启动第四段(5)
图15-AbstractAutowireCapableBeanFactory#doCreateBean方法

我们接着讲doCreateBean方法,之前对循环依赖做了些解释,我们接着往下看populateBean(beanName, mbd, instanceWrapper)方法
图15-572行
这行就是调用populateBean(beanName, mbd, instanceWrapper)方法对实例化好的bean对象进行属性注入,也就是处理我们经常使用的@autowired或者@resource这些注解。我们看下该方法的代码
图16-AbstractAutowireCapableBeanFactory#populateBean方法
图16-1277到1286行
这几行没什么好说的,做了个简单的空值校验,如果bean实例为空但beanDefinition却定义了bean属性的value值则报错,否则直接返回。
图16-1291到1303行
这几行的目的只有一个,就是调用后置处理器InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法对bean属性进行设值。如果该方法返回了false说明bean属性已设置完毕不需要populateBean方法后续继续对bean进行属性设置。continueWithPropertyPopulation属性就是来判断是否需要后续继续对bean的属性进行设置。对于具体有哪些后置处理器做了什么不是我们当前的重点,大家只需要知道这里spring为我们提供了一个扩展点即可。这个后置处理器我们前面也说过,这里就不赘述了。
图17-AbstractAutowireCapableBeanFactory#populateBean方法

图17-1309到1322行
这几行的功能主要是获取bean实例中的属性,然后根据beanDefinition定义的注入类型判断是否根据name注入或者根据类型注入去获取每个属性对应的bean实例。根据name注入也就是通过beanName去spring容器获取该属性的bean实例,根据类型注入是根据属性class类型到spring容器中获取该属性的bean实例。最后将获取到的属性bean实例根据属性名作为key放到newPvs变量中,为后面对属性设值做准备。
图18-AbstractAutowireCapableBeanFactory#populateBean方法
图18这段逻辑主要做了两件事,
1331-1342:判断当前spring容器是否有InstantiationAwareBeanPostProcessor后置处理器的存在,如果有则执行其postProcessPropertyValues方法,该方法允许我们在对bean设置属性前对属性的值进行修改,也就是修改pvs或者直接替换pvs;
1343-1345:对bean的属性进行检查,检查必填属性是否为空。一共有4中检查模式都定义在AbstractBeanDefinition类里,分别是DEPENDENCY_CHECK_NONE-不检查,DEPENDENCY_CHECK_OBJECTS-检查引用类型的属性,DEPENDENCY_CHECK_SIMPLE-检查基本类型的属性,DEPENDENCY_CHECK_ALL-所有类型的属性都检查。
1348-1350:通过反射对属性进行设值,完成属性注入。
讲到这AbstractAutowireCapableBeanFactory#populateBean方法也就讲完了,接下来我们开始讲图15-AbstractAutowireCapableBeanFactory#doCreateBean方法的initializeBean(beanName, exposedObject, mbd)方法。
图16-AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)方法
AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)方法的逻辑相对而言简单了很多,我们从上往下看来捋一下。
图16-1674到1682行
这几行的逻辑就是调用了invokeAwareMethods(beanName, bean)方法,这个方法的逻辑很简单就是判断当前初始化的bean是不是实现了Aware接口,如果实现了该接口那么就判断具体的Aware接口类型,比如是否是BeanNameAware接口,是的话则调用其setBeanName方法等等,这个方法很简单大家自己点进去看下就明白了,我就不赘述了。
图16-1684到1687行
这几行就是调用之前我们说过的一个bean后置处理BeanPostProcessor的postProcessBeforeInitialization方法,该方法的含义是在执行bean的初始化前执行,具体指的是在执行spring的InitializingBean#afterPropertiesSet方法前执行,这个方法我们马上就会说到。
图16-1690行
这行就是判断当前bean是否实现了InitializingBean接口,如果实现了这个接口则调用其afterPropertiesSet方法,这也是spring提供的给我们的扩展,给我们提供自定义初始化bean的能力。
图16-1697到1699行
这几行是调用BeanPostProcessor的postProcessAfterInitialization方法,在bean初始化完成之后提供的一个扩展方法。到这我们的bean就彻底初始化完毕了。
让我们再回到AbstractAutowireCapableBeanFactory#doCreateBean方法的剩余部分。
图17-AbstractAutowireCapableBeanFactory#doCreateBean方法

earlySingletonExposure变量我们之前说过,如果spring容器允许单例循环依赖且当前bean是单例且当前bean正在创建改变量就为true。然后调用getSingleton(beanName, false)方法第二个参数为false表示不允许从单例工厂中获取实例,只能从单例容器singletonObjects或者提前暴露的单例容器earlySingletonObjects中获取实例。
目前虽然bean已经初始化好但目前spring还未将bean实例放入单例容器singletonObjects中,所以在没有出现循环依赖的情况下这里获取到的Object earlySingletonReference变量为空没啥好说的。如果earlySingletonReference不为空说明出现了循环依赖,当前beanName对应的bean提前暴露了一个实例就是earlySingletonReference。
接下来判断exposedObject == bean,这个判断一般都是相对的,因为如果是循环依赖的情况且bean是需要动态代理的,那么在前面getEarlyBeanReference(beanName, mbd, bean)方法执行的时候就会执行动态代理,后面就不会再执行动态代理,这也是为什么这个判断成立的情况下要使用earlySingletonReference给exposedObject赋值的原因。
如果exposedObject不等于bean,说明在initializeBean方法里执行后置处理器时更改了bean的引用,那么提前暴露出去的bean也将失效。这时候如果提前暴露的bean已经被其它bean引用了,那就需要报错。
最后判断当前bean是否需要注册为DisposableBean,注册为DisposableBean的话在容器销毁时会执行其destroy()方法。
感谢大家的观看,希望这些文章可以帮助大家更好理解spring。
相关文章:
从根儿上学习spring 十一 之run方法启动第四段(5)
图15-AbstractAutowireCapableBeanFactory#doCreateBean方法 我们接着讲doCreateBean方法,之前对循环依赖做了些解释,我们接着往下看populateBean(beanName, mbd, instanceWrapper)方法 图15-572行 这行就是调用populateBean(beanName, mbd, instanceW…...
常见8种数据结构
常见的数据结构包括数组、链表、队列、栈、树、堆、哈希表和图,每种数据结构都有其特点,如下: 常见数据结构 1.数组2.链表3.队列4.栈5.树6.图7.哈希表8.堆 1.数组 特点: 固定大小的线性数据结构支持快速随机访问插入和删除效率…...
黑马Java零基础视频教程精华部分_11_面向对象进阶(3)_抽象类、接口、适配器
《黑马Java零基础视频教程精华部分》系列文章目录 黑马Java零基础视频教程精华部分_1_JDK、JRE、字面量、JAVA运算符 黑马Java零基础视频教程精华部分_2_顺序结构、分支结构、循环结构 黑马Java零基础视频教程精华部分_3_无限循环、跳转控制语句、数组、方法 黑马Java零基础视…...
Promethues Metrics
Metrics Metrics可分为三部分: HELP 描述metric作用TYPE metric类别 TYEP Counter 某个事件发生的次数数字只能增长 Total reuqests Total ExceptionsGauge 描述当前值可以上升或下降 CurrentCPU Utilization Available System Memory Number of concurren…...
公网IP与私网IP具体有哪些区别?
1.接入方式不同 公网IP以公网连接Internet上的非保留地址,私网IP则是局域网上的IP,通过NAT才能够与公网进行通信。 2.特点不同 公网IP由国际互联网络信息中心InterNIC负责,将IP地址分配给注册并向InterNIC提出申请的机构或组织。私网IP则是为节省可分配…...
LeetCode——3143. 正方形中的最多点数
通过万岁!!! 题目:给你一个n*2的数组,然后第i行表示第i个点的坐标,然后还给你了一个字符串s,s[i]则表示第i个点的名称。然后让你找一个中心是(0,0)的正方形,…...
const重新赋值的问题
问: const haveNextPage false; // 默认没有下一页fetch(historyFullUrl).then(data > {haveNextPage data.data.has_more;这段代码有什么问题吗? 回答: 在你的代码中,有一个潜在的问题涉及到 haveNextPage 的赋值。你定义了 haveNextPage 作为一个常量&am…...
python开发上位机 - PyCharm环境搭建、安装PyQt5及工具
目录 简介: 一、安装PyCharm 1、下载 PyCharm 2、PyCharm安装 1)配置安装目录 2)安装选项 3、问题及解决方法 二、安装PyQt5 1、打开 Pycharm,新建 Project 2、安装 pyqt5 3、安装很慢怎么办? 4、安装 pyq…...
day02-安装虚拟机
1. 安装配置 前面一直下一步就OK 2. 虚拟机操作系统配置 语言 中文 软件安装: 最小安装,标准,调试工具,开发工具,系统工具,man手册 网络和主机名配置 主机名,自己起名字 网络配置 常规 &g…...
Qt:线程
一个Qt窗口生成后,为什么拖动窗口,窗口可以随着鼠标移动或放大缩小 因为对窗口操作后,都有对应的事件产生,Qt在其框架中对这些事件进行了默认处理 一个Qt程序默认只有一个线程,称为主线程(也叫ui线程&#…...
VisionPro二次开发学习笔记11-使用 Caliper和Fixture定位Blob工具检测方块
该示例演示了如何使用卡尺工具和夹具工具来固定 Blob 工具。示例代码将检测图像上部区域中小方块的存在。当点击“运行”按钮时,将读取一张新图像。卡尺工具将被运行,卡尺工具的输出 Y 信息将传递给夹具工具。夹具工具使用来自卡尺工具的 Y 信息和新图像…...
高翔【自动驾驶与机器人中的SLAM技术】学习笔记(五)卡尔曼滤波器一:认知卡尔曼滤波器;协方差矩阵与方差;
卡尔曼滤波器 为了研究卡尔曼,我阅读了大量博文。不敢说完全吃透,但是在做一件什么事,可以通过下面这文章来理解,我读了不下五遍。并整理标准重点,添加自己的一些见解。 自动驾驶传感器融合算法 - 自动驾驶汽车中的激…...
【Go】通过反射解析对象tag信息,实现简易ORM
反射是运行时,需要在运行时解析类型信息,编译期无法优化这些操作,因此比编译时已知类型信息的直接调用效率要低。 package mainimport ("fmt""reflect""strings" )type Person struct {Name string json:&quo…...
gemini2相机和宇树雷达L1的使用注意点
gemini2相机: 官方资料:Gemini2深度相机 (yahboom.com) 目前深度这一块智能提供某一点的深度数据,没有提供某一点的世界坐标,虽然网上有文章说是可以计算 已知深度图,获得某个像素点的三维坐标_深度图如何知道特征点的3d坐标-CS…...
FPGA开发——verilog随机涵数$random的使用方法
一、概述 我们进行FPGA开发的过程中在做仿真的时候,难免会需要一些数据作为输入。有的时候需要输入大量的数据对于设计结果进行一个验证,如果逐个去进行输入,就需要花费大量的时间。这种情况下我们通常会想到使用随机数。随机数在我们的日常…...
Android14 WPA2和WPA3 类型的WiFi网络连接
Android14 WPA2和WPA3 类型的WiFi网络连接 文章目录 Android14 WPA2和WPA3 类型的WiFi网络连接一、前言二、源码分析1、Android原生Settings 连接WPA 和WPA3 网络的配置代码 三、其他1、WPA/WPA2和WPA3连接小结2、WPA配置无法连接WPA3的网络的情况Android11 Wifi 加密类型详解 …...
24/8/5算法笔记 逻辑回归sigmoid
今日是代码对sigmoid函数的实现和运用 #linear_model线性回归 #名字虽然叫逻辑回归,作用于分类 #分类:类别 #回归:预测 from sklearn.linear_model import LogisticRegression 实现函数 import numpy as np import matplotlib.pyplot as pl…...
适用于验证码的OCR,识别快速,使用简单!
环境 windows 11python 3.9 前言 Muggle OCR 是一个高效本地 OCR 模块,旨在通过简单的几步设置提供强大的文本识别功能,无论是在处理印刷文本还是解析验证码,都能让用户在工作中畅通无阻。Muggle OCR 易于安装和使用,支持双模型&a…...
超简单适合练手的双指针题:判断子序列
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列&#…...
打破老美垄断,潘展乐商业价值起飞
文|琥珀食酒社 作者 | 积溪 奥运会上的潘展乐 真是牛逼坏了 拿下男子100米自由游金牌 打破欧美长达近百年垄断 搞定男子4x100米混合泳金牌 终结了美国在这项目上 10年不败的神话 比赛前 美国选手对他爱答不理 招呼都不打 比赛后美国选手想套热乎 潘展乐…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...
GB/T 43887-2024 核级柔性石墨板材检测
核级柔性石墨板材是指以可膨胀石墨为原料、未经改性和增强、用于核工业的核级柔性石墨板材。 GB/T 43887-2024核级柔性石墨板材检测检测指标: 测试项目 测试标准 外观 GB/T 43887 尺寸偏差 GB/T 43887 化学成分 GB/T 43887 密度偏差 GB/T 43887 拉伸强度…...
