Spring源码刨析之配置文件的解析和bean的创建以及生命周期
public void test1(){XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));user u = xmlBeanFactory.getBean("user",org.xhpcd.user.class);// System.out.println(u.getStu());}
先介绍一个类XmlBeanFactory,这个类负责配置文件的解析和bean的创建和初始化。在Spring中对象信息会被封装为一个BeanDefinition对象,这个对象会保存配置文件中所描述的类的信心比如属性名属性值类名等,以便创建bean时根据BeanDefinition对象的信息反射创建并赋值。
配置文件解析
xmlbeanfactory内部会创建XmlBeanDefinitionReader用来解析配置文件资源。

把xml文件封装为Document,接着调用注册方法。此方法内部再经过调用会调用到parseBeanDefinitions方法。

这里的Node就是<bean>标签的信息的封装parseDefaultElement(ele, delegate)方法用来解析常规标签,delegate.parseCustomElement(ele)用来解析自定义标签比如<mvc:annotation-driven></mvc:annotation-driven>这种的或者自定义的标签。

信息封装完毕后,会被存放在XmlBeanFactory的Map文件中,keybeanname,value是beanDefinition。到这里基本xml文件都被解析了。
Bean的创建和赋值
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));user u = xmlBeanFactory.getBean("user",org.xhpcd.user.class);
代码在getBean内部有体现

首先transformedBeanName(name)的作用是可能用户提供的是别名转化为beannaem也就是配置文件中bean的id,beanFactory会把创建的bean存放起来以便复用,所以底层使用的就是Map数据结构,根据beanname和bean对象进行存储,主要关注getSingleton(beanName)方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}
这里就是所谓的三级缓存,它还有一个重要功能解决循环依赖等问题。
由于我们这里主要讲解bean的生命周期和创建,第一次获取肯定是获取不到。上上个图中if分支是判断bean的类型是不是BeanFactory,如果是的话就调用工厂的getObject方法,else分支内就是父子容器的概念,如果在创建XmlBeanFactory时值定了其它的容器那么会把它存放在parentBeanFactory中,那么我们子容器再查找时就会先找自己的内部看是否有,如果没有就找父类的。
接下来注意markBeanAsCreated(beanName)和final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);方法

先看getMergedLocalBeanDefinition(beanName)方法其内部本质是获取对应的bean信息,然后会去查看bean是否有指定继承的类
<bean id="abs" class="" abstract="true"><property name="id" value="1"></property></bean><bean id="stu" name="u" class="org.xhpcd.student" parent="abs"></bean>
就像这样存在继承的类,spring做的就是把当前类的bean定义信息和父类的bean定义信息组合在一起并返回,然后这里就是完整的bean定义信息

以此递归调用获取父类bean信息,然后会把这些信息存放在mergedBeanDefinitions中。
接下来看之前的markBeanAsCreated(beanName)方法

将指定的 Bean 标记为已创建(或即将创建)。这允许 Bean 工厂优化其缓存,以便重复创建指定的 Bean。现在我们实际上正在创建 bean,让我们重新合并 bean 定义......以防万一它的某些元数据在此期间发生了变化。(注解原话)
接下来 mbd.getDependsOn()方法就是获取bean标签中的depend-on信息解析,不过用的不多。

这段代码是真正创建bean的代码,首先判断bean是单例还是多例又或者是session,request等作用域。先看单例吧,首先getSingleton方法内部传递了一个lambda表达式,作用是为了后续回调此方法,接下来分析getSingleton方法

首先先看 beforeSingletonCreation(beanName) 方法,
protected void beforeSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}
}
这段代码就是判断当前类是否被排除并且把它加入到singletonsCurrentlyInCreation集合中,防止在bean的生命周期完成前被多次创建。
然后就是singletonObject = singletonFactory.getObject();此方法就是对传入的表达式的一个方法回调,回调createBean方法,接下来分析此方法

首先解析bean定义信息获取Class信息,
mbdToUse.prepareMethodOverrides()方法是和方法替换有关但平时用的少我会在其他文章进行讲述。
再接下来就是
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
这段代码涉及Aop,通过@EnableAspect注解注册的bean后处理器,提前返回一个代理对象,代理对象不经过后面其它的后处理器等。以后文章会讲解aop这部分
接下来就是重点 doCreateBean(beanName, mbdToUse, args) 方法

首先创建一个包装对象,里面有一个属性就是我们的bean对象,只是此时还没没进行属性赋值初始化。包装类的作用主要就是用于类型转换,配置文件中把字符串转化为int等。

紧接着创建对应工厂放入三级缓存中,主要用来解决代理循环依赖问题。这里用不到
然后就是popilateBean方法了,这个方法内部进行属性的注入;

先看这个方法此方法内部是获取所有InstantiationAwareBeanPostProcessors
类型的后处理器,然后在最开始进行一些修改。
类型转换

首先尝试获取自定义类型转换器,紧接着对bean定义信息中set方法获取到转换的类型的属性的封装信息PropertyValue进行逐个遍历,内部通过set方法获取类型,然后或取真实的类型转换信息进行转换并赋值给PropertyValue,最终把类型转换后的结果存放在beanwrapper的属性中并进行属性赋值

首先根据 GenericTypeAwarePropertyDescriptor 拿到可写的方法就是set方法,然后利用反射进行属性赋值。

紧接着调用initializeBean方法

执行aware注入方法,紧接着执行Bean后置处理器的before方法然后调用init方法再调用后处理器的after方法,就基本完成创建的生命周期
到这里上面所说的回调方法基本分析完毕。

然后调用 afterSingletonCreation(beanName)
protected void afterSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");}}
移除之前上面正在创建bean的信息,然后调用add方法放入一级缓存。到这里bean就创建完毕了
相关文章:
Spring源码刨析之配置文件的解析和bean的创建以及生命周期
public void test1(){XmlBeanFactory xmlBeanFactory new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));user u xmlBeanFactory.getBean("user",org.xhpcd.user.class);// System.out.println(u.getStu());}先介绍一个类XmlBeanFac…...
如何使用 Grafana 监控文件系统状态
当 JuiceFS 文件系统部署完成并投入生产环境,接下来就需要着手解决一个非常重要的问题 —— 如何实时监控它的运行状态?毕竟,它可能正在为关键的业务应用或容器工作负载提供持久化存储支持,任何小小的故障或性能下降都可能造成不利…...
智能革命:未来人工智能创业的天地
智能革命:未来人工智能创业的天地 一、引言 在这个数字化迅速变革的时代,人工智能(AI)已经从一个边缘科学发展成为推动未来经济和社会发展的关键动力。这一技术领域的飞速进步,不仅影响着科技行业的每一个角落,更是为创业者提供了…...
4月14日总结
java学习 一.多线程 简介:多线程是计算机科学中的一个重要概念,它允许程序同时执行多个任务或操作。在单个程序内部,多线程使得代码可以并行执行,从而提高程序的性能和响应速度。 这里先来介绍一下创建多线程的几种方法。 1.扩展…...
kafka---broker相关配置
一、Broker 相关配置 1、一般配置 broker.id 当前kafka服务的sid(server id),在kafka集群中,该值是唯一的(unique),如果未设置此值,kafka会自动生成一个int值;为了防止自动生成的值与用户设置…...
【Golang学习笔记】从零开始搭建一个Web框架(二)
文章目录 模块化路由前缀树路由 前情提示: 【Golang学习笔记】从零开始搭建一个Web框架(一)-CSDN博客 模块化路由 路由在kilon.go文件中导致路由和引擎交织在一起,如果要实现路由功能的拓展增强,那将会非常麻烦&…...
高精度地图导航论文汇总
文章目录 2021基于车载激光点云的高精地图矢量化成图[J] 2022基于高精度地图的智能车辆路径规划与跟踪控制研究[M] 2023一种无人驾驶融合决策方案的设计与实现[M] 2021 基于车载激光点云的高精地图矢量化成图[J] 摘要: 针对车载激光点云中对各特征物提取结果后矢量…...
【域适应】基于域分离网络的MNIST数据10分类典型方法实现
关于 大规模数据收集和注释的成本通常使得将机器学习算法应用于新任务或数据集变得异常昂贵。规避这一成本的一种方法是在合成数据上训练模型,其中自动提供注释。尽管它们很有吸引力,但此类模型通常无法从合成图像推广到真实图像,因此需要域…...
从零实现诗词GPT大模型:pytorch框架介绍
专栏规划: https://qibin.blog.csdn.net/article/details/137728228 因为咱们本系列文章主要基于深度学习框架pytorch进行,所以在正式开始之前,现对pytorch框架进行一个简单的介绍,主要面对深度学习或者pytorch还不熟悉的朋友。 一、安装pytorch 这一步很简单,主要通过p…...
[目标检测] OCR: 文字检测、文字识别、text spotter
概述 OCR技术存在两个步骤:文字检测和文字识别,而end-to-end完成这两个步骤的方法就是text spotter。 文字检测数据集摘要 daaset语言体量特色MTWI中英文20k源于网络图像,主要由合成图像,产品描述,网络广告(淘宝)MS…...
Windows环境下删除MySQL
文章目录 一、关闭MySQL服务1、winR打开运行,输入services.msc回车2、服务里找到MySQL并停止 二、卸载MySQL软件1、打开控制模板--卸载程序--卸载MySQL相关的所有组件 三、删除MySQL在物理硬盘上的所有文件1、删除MySQL的安装目录(默认在C盘下的Program …...
uniapp:uview-plus的一些记录
customStyle 并不是所有的组件都有customStyle属性来设置自定义属性,有的还是需要通过::v-deep来修改内置样式 form表单 labelStyle 需要的是一个对象 :labelStyle"{color: #333333,fontSize: 32rpx,fontWeight: 500}"dateTimePicker选择器设置默认值…...
OLTP 与 OLAP 系统说明对比和大数据经典架构 Lambda 和 Kappa 说明对比——解读大数据架构(五)
文章目录 前言OLTP 和 OLAPSMP 和 MPPlambda 架构Kappa 架构 前言 本文我们将研究不同类型的大数据架构设计,将讨论 OLTP 和 OLAP 的系统设计,以及有效处理数据的策略包括 SMP 和 MPP 等概念。然后我们将了解经典的 Lambda 架构和 Kappa 架构。 OLTP …...
步骤大全:网站建设3个基本流程详解
一.领取一个免费域名和SSL证书,和CDN 1.打开网站链接:https://www.rainyun.com/z22_ 2.在网站主页上,您会看到一个"登陆/注册"的选项。 3.点击"登陆/注册",然后选择"微信登录"选项。 4.使用您的…...
利用Sentinel解决雪崩问题(二)隔离和降级
前言: 虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。而要将这些故障控制在一定范围避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了,不管是线程隔离还是熔断降级,都是对客户端(调…...
基于springboot的房产销售系统源码数据库
基于springboot的房产销售系统源码数据库 摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于房产销售系统当然也不能排除在外,随着网络技术的不断成熟,带动了房产…...
【MATLAB】基于Wi-Fi指纹匹配的室内定位-仿真获取WiFi RSSI数据(附代码)
基于Wi-Fi指纹匹配的室内定位-仿真获取WiFi RSSI数据 WiFi指纹匹配是室内定位最为基础和常见的研究,但是WiFi指纹的采集可以称得上是labor-intensive和time-consuming。现在,给大家分享一下我们课题组之前在做WiFi指纹定位时的基于射线跟踪技术仿真WiFi…...
深圳晶彩智能ESP32-3248S035R使用LovyanGFX实现手写板
深圳晶彩智能ESP32-3248S035R介绍 深圳晶彩智能出品ESP32-3248S035R为3.5寸彩色屏采用分辨率480x320彩色液晶屏,驱动芯片是ST7796。板载乐鑫公司出品ESP-WROOM-32,Flash 4M。型号尾部“R”标识电阻膜的感压式触摸屏,驱动芯片是XPT2046。 Lo…...
【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析
💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 Spring Boot 日志一. 日志的概念?…...
ISTQB选择国内版,还是国际版呢
1, ISTQB简介 ISTQB(International Software Testing Qualifications Board)是一个国际软件测试资格认证机构,旨在提供一个统一的软件测试认证标准。ISTQB成立于2002年,是非盈利性的组织,由世界各地的国家或地区软件测…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
