当前位置: 首页 > news >正文

从根儿上学习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哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)

这是系统中断服务程序的默认处理汇编函数&#xff0c;如果我们没有定义实现某个中断函数&#xff0c;那么当stm32产生了该中断时&#xff0c;就会默认跑这里来了&#xff0c;所以我们打开了什么中断&#xff0c;一定要记得实现对应的系统中断函数&#xff0c;否则会进来一直循环…...

GB/T 43887-2024 核级柔性石墨板材检测

核级柔性石墨板材是指以可膨胀石墨为原料、未经改性和增强、用于核工业的核级柔性石墨板材。 GB/T 43887-2024核级柔性石墨板材检测检测指标&#xff1a; 测试项目 测试标准 外观 GB/T 43887 尺寸偏差 GB/T 43887 化学成分 GB/T 43887 密度偏差 GB/T 43887 拉伸强度…...