Spring源码分析:创建 BeanDefinition 流程
一、前期准备
1.1 环境依赖
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.7.RELEASE</version></dependency>
</dependencies>1.2 实体类
简单的User类,在测试过程中创建这个User类的对象。
public class User {private Integer id;private String name;public User() {System.out.println("创建了");}
}1.3 applicationContext.xml
在applicationContext.xml配置bean对象。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.zqc.domain.User" id="user"></bean>
</beans>1.4 测试代码
通过applicationContext.xml配置应用程序的上下文,在容器中创建User对象
public class SpringDemo {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) context.getBean("user");}
}二、探究过程
2.1 目标
目标:BeanDefinition是什么?是什么时候创建的?
2.2 BeanDefinition的创建过程
2.2.1 回顾bean对象的创建
前面在分析Bean创建的过程中,发现在执行完refresh()方法后就完成了bean对象的创建。
在测试代码中创建context对象:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");ClassPathXmlApplicationContext构造器中调用了另一个构造器:

该构造器中执行了refresh()方法

在refresh()方法中创建了非懒加载的单例对象:

所以BeanDefinition可定在这行代码之前创建的。下面看看在refresh()方法的什么地方创建了BeanDefinition。
2.2.2 AbstractApplicationContext
🔶 refresh()方法
首先我们要知道,Bean对象和BeanDefinition对象都是是通过BeanFactory创建。
所以,只有在获取BeanFactory之后才能获取到BeanDefinition。
在这一行创建了beanFactory对象

查看一下beanFactory,找寻与BeanDefinition相关的属性: beanDefinitionMap、beanDefinitionNames

Spring源码分析:创建 BeanDefinition 流程
本文来和大家一起聊聊:Spring创建BeanDefinition流程
参考视频:https://www.bilibili.com/video/BV1Bq4y1Q7GZ?p=4
通过视频的学习和自身的理解整理出的笔记。
一、前期准备
1.1 环境依赖
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.1.7.RELEASE</version></dependency>
</dependencies>1.2 实体类
简单的User类,在测试过程中创建这个User类的对象。
public class User {private Integer id;private String name;public User() {System.out.println("创建了");}
}1.3 applicationContext.xml
在applicationContext.xml配置bean对象。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.zqc.domain.User" id="user"></bean>
</beans>1.4 测试代码
通过applicationContext.xml配置应用程序的上下文,在容器中创建User对象。
public class SpringDemo {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");User user = (User) context.getBean("user");}
}二、探究过程
2.1 目标
目标:BeanDefinition是什么?是什么时候创建的?
2.2 BeanDefinition的创建过程
2.2.1 回顾bean对象的创建
前面在分析Bean创建的过程中,发现在执行完refresh()方法后就完成了bean对象的创建。
在测试代码中创建context对象:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");ClassPathXmlApplicationContext构造器中调用了另一个构造器:

该构造器中执行了refresh()方法

在refresh()方法中创建了非懒加载的单例对象:

所以BeanDefinition可定在这行代码之前创建的。下面看看在refresh()方法的什么地方创建了BeanDefinition。
2.2.2 AbstractApplicationContext
🔶 refresh()方法
首先我们要知道,Bean对象和BeanDefinition对象都是是通过BeanFactory创建。
所以,只有在获取BeanFactory之后才能获取到BeanDefinition。
在这一行创建了beanFactory对象。

查看一下beanFactory,找寻与BeanDefinition相关的属性: beanDefinitionMap、beanDefinitionNames
🔹 beanDefinitionMap:

key:bean的名称
value:beanDefinition,描述bean的相关信息
🔹 beanDefinitionNames:beanDefination的名称

说明当ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()执行完毕后,BeanDefination就已经创建完毕了。
obtainFreshBeanFactory()方法

refreshBeanFactory()方法

通过这行代码loadBeanDefinitions(beanFactory)创建了BeanDefinition对象。
2.2.3 AbstractXmlApplicationContext
loadBeanDefinitions()方法,输入beanFactory
通过读取xml文件来创建BeanDefinitions
beanFactory就是XmlBeanDefinitionReader里面的registry,所以后面我们看到的registry就是beanFactory对象。

loadBeanDefinitions()方法,输入beanDefinitionReader
方法重载,上面的形参类型为DefaultListableBeanFactory,这里的形参beanDefinitionReader,就是上面的beanFactory。

loadBeanDefinitions()方法,输入locations

在loadBeanDefinitions(location)方法里创建了BeanDefinition。
2.2.4 AbstractBeanDefinitionReader
loadBeanDefinitions()方法,输入locations

loadBeanDefinitions()方法,输入locations和Set<Resource>

loadBeanDefinitions()方法,输入可变参数resources

2.2.5 XmlBeanDefinitionReader loadBeanDefinitions()方法,输入resources

loadBeanDefinitions()方法

doLoadBeanDefinitions()方法

registerBeanDefinitions()方法

2.2.6 DefaultBeanDefinitionDocumentReader
registerBeanDefinitions()方法

doRegisterBeanDefinitions()方法

parseBeanDefinitions()方法
这里通过解析xml文件遍历里面的bean标签创建beanDefinition

parseDefaultElement()方法
根据当前的元素标签,选择不同的解析方式。比如:import、alias、beans

processBeanDefinition()方法

在这里创建beanDefinition对象并存储在bdHolder中:

2.2.7 BeanDefinitionParserDelegate
parseBeanDefinitionElement()方法

parseBeanDefinitionElement()方法

parseBeanDefinitionElement()方法

创建BeanDefinition对象后,继续对xml文件进行解析并设置beanDefinition。
下面继续简单看看createBeanDefinition的过程。
createBeanDefinition()方法

2.2.8 BeanDefinitionReaderUtils
createBeanDefinition()方法

2.2.9 结论
在容器创建时会先去创建一个beanFactory,然后使用XmlBeanDefinitionReader去读取xml配置文件,把里面的标签进行解析,然后创建BeanDefinition对象来存放bean标签中各个属性的值。所以BeanDefinition相当于就是保存了bean的定义信息的对象。
通过BeanDefinition里面的信息,就可以使用反射来创建bean对象。
2.3 BeanDefinition的存储
2.3.1 DefaultBeanDefinitionDocumentReader
我们回到【2.2.6】节的DefaultBeanDefinitionDocumentReader的processBeanDefinition()方法中。
在这里创建beanDefinition对象并存储在bdHolder中。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);那么接下来应该将bdHolder保存下来。

可以看出来getReaderContext().getRegistry()这就是一个beanFactory对象

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这段代码的作用就是将beanDefintion对象注册到beanFactory中。

下面我们看看registerBeanDefinition()方法。
2.3.2 BeanDefinitionReaderUtils

下面看看registerBeanDefinition()方法。
2.3.3 DefaultListableBeanFactory

最终会运行到这里:

2.3.4 结论
BeanDefinition被创建后会被存入beanDefinitionMap集合和beanDefinitionNames集合中。
beanDefinitionMap:key为beanName,value为beanDefinition
beanDefinitionNames:存储beanName
相关文章:
Spring源码分析:创建 BeanDefinition 流程
一、前期准备1.1 环境依赖<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dependency><dependency><groupId&…...
Linux 练习一(思维导图 + 练习过程)
文章目录一、Linux 用户管理及文件操作第一段练习记录:主要对用户进行删除添加设置密码等操作第二段练习记录:主要包括权限设置和查找命令第三段练习记录:关于文件的命令练习第四段练习记录:查找命令及查看内存命令的使用二、Linu…...
高德地图基础教程超详细版
在当前社会,对于地图的使用是很必须的,所以对于程序员来说也是需要掌握的技能,目前主流的又百度地图和高德地图,但是我建议使用高德地图,因为百度地图的API着实不好用吖,不好理解,对于开发人员来…...
基于A7核开发板的串口实现控制LED亮灭
1.通过操作Cortex-A7核,串口输入相应的命令,控制LED灯进行工作 1>例如在串口输入led1on,开饭led1灯点亮 2>例如在串口输入led1off,开饭led1灯熄灭 3>例如在串口输入led2on,开饭led2灯点亮 4>例如在串口输入led2off,开饭led2灯熄灭 5>例如…...
HyperGBM用Adversarial Validation解决数据漂移问题
本文作者:杨健,九章云极 DataCanvas 主任架构师 数据漂移问题近年在机器学习领域来越来越得到关注,成为机器学习模型在实际投产中面对的一个主要挑战。当数据的分布随着时间推移逐渐发生变化,需要预测的数据和用于训练的数据分布…...
关基系统三月重保安全监测怎么做?ScanV提供纯干货!
三月重保当前,以政府、大型国企央企、能源、金融等重要行业和领域为代表的关键信息基础设施运营单位都将迎来“网络安全大考”。 对重要关基系统进行安全风险监测并收敛暴露面,响应监管要求进行安全加固,重保期间实时安全监测与数据汇报等具体…...
RK3588关键电路 PCB Layout设计指南
1、音频接口电路 PCB 设计(1)所有 CLK 信号建议串接 22ohm 电阻,并靠近 RK3588 放置,提高信号质量;(2)所有 CLK 信号走线不得挨在一起,避免串扰;需要独立包地,…...
二分边界详细总结
一、查找精确值 从一个有序数组中找到一个符合要求的精确值(如猜数游戏)。如查找值为Key的元素下标,不存在返回-1。 //这里是left<right。 //考虑这种情况:如果最后剩下A[i]和A[i1](这也是最容易导致导致死循环的…...
STM32---备份寄存器BKP和 FLASH学习使用
BKP库函数 学习BKP,首先就是知道BKP每一个函数的作用然后如何使用即可 使用备份域的作用只需要操作上面的两个函数即可,其余的都是它的其他功能 BKP简介 备份寄存器是42个16位的寄存器,可用来存储84个字节的用户应用程序数据。他们处在备份…...
Python-生成元组和字典
1.生成元组元组是元素按顺序组合后的产物,元组对象的类型是tuple型含有两个元素的元组成为数据对元组可以包含任意数量和任意类型的元素,其元素总数可以为0、1、2等,并且元素的先后顺序是由意义的。另外,元组中的元素类型没有必要…...
I.MX6ULL内核开发10:设备树
目录 一、设备树简介 二、设备树源码 三、获取设备树信息 1、增加设备节点 2、内核编译设备树 3、替换设备树文件 4、查看设备树节点 5、在驱动中获取节点的属性 6、编译驱动模块 7、加载模块 一、设备树简介 设备树的作用是描述一个硬件平台的硬件资源。这个“设备树…...
【大数据】记一次hadoop集群missing block问题排查和数据恢复
问题描述 集群环境总共有2个NN节点,3个JN节点,40个DN节点,基于hadoop-3.3.1的版本。集群采用的双副本,未使用ec纠删码。 问题如下: bin/hdfs fsck -list-corruptfileblocks / The list of corrupt files under path…...
国产音质好的蓝牙耳机有哪些?国产音质最好的耳机排行
随着时间的推移,真无线蓝牙耳机逐渐占据耳机市场的份额,成为人们日常生活中必备的数码产品之一。蓝牙耳机品牌也多得数不胜数,哪些国产蓝牙耳机音质好?下面,我们从音质出来,来给大家介绍几款国产蓝牙耳机&a…...
CTFer成长之路之XSS的魔力
XSS的魔力CTF XSS闯关 题目描述: 你能否过关斩将解决所有XSS问题最终获得flag呢? docker-compose.yml version: "3.2"services:xss:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-xss:latestports:- 3000:3000启动方式 docker-compose up -…...
行锁、表锁、主键外键、表之间的关联关系
Java知识点总结:想看的可以从这里进入 目录2.4、行锁、表锁2.5、主键、外键2.5.1、主键2.5.2、外键2.6、表的关联关系2.4、行锁、表锁 MyISAM默认采用表级锁,InnoDB默认采用行级锁。 表锁:开销小,加锁快,不会出现死锁…...
JavaScript 进阶(面试必备)--charater4
文章目录前言一、深浅拷贝:one: 浅拷贝:two:深拷贝二、异常处理:one: throw 抛异常:two: try /catch 捕获异常:three:debugger三、处理thisthis指向 :one:普通函数this指向this指向 :two: 箭头函数this指向3.2 改变this:one: call():two: apply():three: bind()四、性能优化:on…...
ARM+FPGA架构开发板PCIE2SCREEN示例分析与测试-米尔MYD-JX8MMA7
本篇测评由电子发烧友的优秀测评者“zealsoft”提供。 本次测试内容为米尔MYD-JX8MMA7开发板其ARM端的测试例程pcie2screen并介绍一下FPGA端程序的修改。 01. 测试例程pcie2screen 例程pcie2screen是配合MYD-JX8MMA7开发板所带的MYIR_PCIE_5T_CMOS 工程的测试例&#…...
51单片机入门 - SDCC / Keil_C51 会让没有调用的函数参与编译吗?
Small Device C Compiler(SDCC)是一款免费 C 编译器,适用于 8 位微控制器。 不想看测试过程的话可以直接划到最下面看结论:) 关于软硬件环境的信息: Windows 10STC89C52RCSDCC (构建HEX文件&…...
OpenCV只含基本图像模块编译
编译OpenCV4.5.5只含基本图像模块,环境为Windows10 x64CMake3.23.3VS2019。默认编译选项编译得到的OpenCV库往往大几百MB甚至上GB,本文配置下编译得到的库压缩后得到的zip包大小仅6.25MB,适合使用OpenCV基本图像功能模块的项目移植而不牵涉其…...
Java实现阴历日历表(附带星座)
准备工作 1.无敌外挂(GitHub直达源码) Nobb 直击灵魂 https://github.com/xuyishanBD/Java_create_calendar.git2.maven配置(如果没有走上面的捷径) <dependencies><dependency><groupId>net.sourceforge.javacsv</groupId><artifactId>javac…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
