Spring IOC 源码解析(七) BeanDefinition 的注册

Spring IoC 源码系列(一)BeanDefinition 初始化与注册 一、BeanDefinition 1.1 什么是 BeanDefinition 在一般的 Spring 项目中,主要通过 XML 的方式配置 bean,而 BeanDefinition 就是 XML 配置属性的载体,XML 文件首先会被转化成 Document 对象,通过解析 Document,把 XML 中 <bean /> 标签转化成 BeanDefinition 供 IoC 容器... 阅读详情

一.项目准备

1.1 创建项目

首先创建一个简单的 maven 项目,并导入 spring 最基础的依赖包.
这里用到的 spring 版本是 5.1.3.RELEASE
在这里插入图片描述

因为我们只用到最简单 BeanFactory ,并没有用 ApplicationContext (高级封装的 BeanFactory),所以只要一个 spring-beans 的依赖即可

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
    </dependencies>

1.2 创建基础类

我这里创建了2个基础类,一个启动 spring 的 main 类.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 创建 spring.xml 配置文件

<?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 id="student" class="com.zcsh.xmlbeanfactory.demo.bean.Student">
        <property name="name" value="zcsh"/>
        <property name="age" value="1"/>
    </bean>

    <bean class="com.zcsh.xmlbeanfactory.demo.bean.Teacher" >
        <property name="student" ref="student"/>
    </bean>

</beans>

可以看到我们在 xml 中创建了 student 的定义和 teacher 的定义,并将 teacher 中的 student 属性映射到前面定义的 student.

二.项目启动

我们直接运行 XmlBeanFactoryMain 的 main 方法,启动 XmlBeanFactory 启动容器初始化.

2.1 ClassPathResource

首先可以看到我们定义了一个 ClassPathResource .传的参数就是 xml 文件在类路径下的相对位置,因为我们的 spring.xml 放在的是 resources 根目录,所以可以直接传入文件名即可.

下面们来看看 ClassPathResource 是如何初始化的.
启动 Debug 模式开始解刨:

2.1.1 ClassPathResource 初始化

在这里插入图片描述

进入到下方主要构造器中,可以看到 ClassPathResource 在初始化的时候一共执行了3操作,

  1. 将转入的路径转化为类路径,在这里我们传入值 spring.xml 处理完还是原样,他会把一些特殊的转化,例如 /spring.xml -> spring.xml, Windows 下路径 \\spring.xml -> spring.xml
  2. 初始化属性值 path (也就是 spring.xml)
  3. 初始化 classLoader (也就是 AppClassLoader)

2.2 初始化 XmlBeanFactory

完成了 ClassPathResource 的创建后,就要用 XmlBeanFactory 解析这个资源路径的封装类来提取配置文件,然后进行解析,注册.

2.2.1 XmlBeanFactory 构造器

-w1144

第一步,我们的构造器会执行设置父工程(只有在使用 web IOC 容器的时候才会涉及父子容器).
XmlBeanFactory 的父类是 DefaultListableBeanFactory ,而 DefaultListableBeanFactory 在构造器中也是简单的调用父类的构造器,所以直接看有具体操作的构造器:
在这里插入图片描述

AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) 首先会调用自己的无参构造器. 无参构造器还是会调用父类 AbstractBeanFactory 的构造器,里面什么操作也没有,所以我们也不用进去看了.主要看调用的 ignoreDependencyInterface() 方法.

ignoreDependencyInterface() 功能是:设置忽略依赖指定接口的自动装配,也就是不会通过 @Autowired 注解注入这些接口的实现

下面的设置父工程方法,是指简单做了一个属性赋值:
在这里插入图片描述

第二步,创建 XmlBeanDefinitionReader 并执行 XmlBeanDefinitionReader 加载 BeanDefinition 方法.

XmlBeanDefinitionReader 的构造器需要传入一个 BeanDefinitionRegistry 的实现类,而 XmlBeanFactory 的父类 DefaultListableBeanFactory 是 BeanDefinitionRegistry 实现,所以 XmlBeanFactory 也具备 BeanDefinitionRegistry 的功能,即这里的构造器才会传入 this.

2.3 XmlBeanDefinitionReader 构造器

XmlBeanDefinitionReader 的构造器中直接调用的父类的构造器
在这里插入图片描述

父类 AbstractBeanDefinitionReader 的构造器
在这里插入图片描述

设置了 AbstractBeanDefinitionReader 的属性:

  1. registry (也就是 XmlBeanFactory 本身)
  2. resourceLoader (因为我们的 XmlBeanFactory 没有实现 ResourceLoader 所以是 PathMatchingResourcePatternResolver )
  3. environment ((因为我们的 XmlBeanFactory 没有实现 EnvironmentCapable 所以是 StandardEnvironment )

可以提前知道的是,我们在实际应用中都是使用的 ApplicationContext 的实现(BeanFactory 的高级封装), 而 ApplicationContext 都实现了 ResourceLoader 和 EnvironmentCapable 两个接口.所以如果传入的是 ApplicationContext 实现类,这里都会用 ApplicationContext 实现类的本身.

2.4 loadBeanDefinitions

结束了 XmlBeanDefinitionReader 创建,我们就要回到 2.1 中的第二步方法,执行 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法 this.reader.loadBeanDefinitions(resource);
在这里插入图片描述

可以看到实际执行的是下面的 loadBeanDefinitions 方法.将传入的 Resource (ClassPathResource) 封装成具有编码属性的 Resource;

根据图中的注解我们可以看到具体的流程,主要流程是 获取 Resource 的输入流 :看一看 ClassPathResource 如何重写getInputStream() 方法的:
在这里插入图片描述

最终我们的输入流是通过 this.classLoader.getResourceAsStream(this.path); 方式获取的.这里的 path 就是我们传入的 spring.xml.

获取完输入流,然后调用 doLoadBeanDefinitions 方法.所以我们进入 doLoadBeanDefinitions() 方法看一看

2.5 doLoadBeanDefinitions

看源码:
在这里插入图片描述

这里主要功能是将 io 流解析为 Docment 对象,然后将 Docment 传入到下一个处理环节.
Document 就是 xml 文件的封装类,我们来看一下 Document 对象中,我们熟悉的解析后的属性:
在这里插入图片描述

fNodeName 里面就是一系列的标签属性名等;而 fNodeValue 就是一系列的标签属性值;

2.6 registerBeanDefinitions

这里主要创建了解析 Document 对象的 DefaultBeanDefinitionDocumentReader 类.
在这里插入图片描述

2.7 DefaultBeanDefinitionDocumentReader.registerBeanDefinitions

获取 document 的元素
在这里插入图片描述
Element 的属性
在这里插入图片描述

将获取的 Element 传递给 doRegisterBeanDefinitions();

2.8 doRegisterBeanDefinitions

这里创建了通过 Element 作为基础的 BeanDefinition 解析委托类 delegate,
主要功能方法是 parseBeanDefinitions() ,这个方法是通过 BeanDefinition 解析委托类解析 Element 对象;
在这里插入图片描述

2.9 parseBeanDefinitions

这里主要作用是分离标签,分离 spring 自带标签和自定义的标签;
在这里插入图片描述

我们主要看解析 spring 自带标签的方法;

2.10 parseDefaultElement

这里是分离 spring 自带标签不同类别的地方,如 import,alias,bean,beans;
在这里插入图片描述

可以看到最下面的是解析 beans 标签的方法块,调用的是 2.8 的方法,也就是递归解析 beans 标签. 这里我们主要看解析 bean 标签的地方 processBeanDefinition()

2.11 processBeanDefinition

这个方法主要三个功能:

  1. 将 Element 真正的解析成 BeanDefinition 对象
  2. 将 BeanDefinition 注册到 BeanFactory 的容器中(Map 里面)
  3. 向 IOC 发送注册事件
    在这里插入图片描述
2.11.1 parseBeanDefinitionElement 解析 Element

这里直接上源码,源码上有注释;
在这里插入图片描述
这里面的主要方法是 parseBeanDefinitionElement() 看一下源码;
在这里插入图片描述
返回的就是解析完毕的 BeanDefinition 对象;

2.11.2 BeanDefinitionReaderUtils.registerBeanDefinition 注册 BeanDefinition

这里用传过来的 BeanDefinitionRegistry (也就是 DefaultListableBeanFactory)来注册 BeanDefinition
在这里插入图片描述
进入 registerBeanDefinition() 方法内
在这里插入图片描述

可以看到这里就是具体注册 BeanDefinition 的地方,在正常情况下都是会进入 860 行的方法块内;在这里会往 DefaultListableBeanFactory 的 beanDefinitionMap 和 beanDefinitionNames 集合中保存下来;

三.总结

经过一系列的摸索, 我们从创建 xml , 到通过类路径创建 resouce 封装类(ClassPathResource), 然后创建 XMLBeanFactory , 再获取 xml 输入流, 再将输入流解析为 document 对象, 然后解析 document 对象, 获取 element, 最后解析 element 获取 BeanDefinition , 注册 BeanDefinition.

BeanDefinition 的注册终于完毕了.当 BeanDefinition 注册完毕以后,在应用通过第一次调用 getBean() 方法获取 bean 实例的时候, 通过注册的 BeanDefinition 来创建具体的 bean 然后返回;这是我们后面要研究的方向.

Spring IOC 源码解析(八) Bean 的创建

spring ioc源码剖析 spring ioc源码剖析 ioc的定义IOC核心类与类关系BeanDifinition:如何定义一个beanBeanDefinitionRegistry:注册bean定义的接口AnnotationConfigApplicationContextGenericApplicationContext与BeanFactoryAbstractApplicationContextioc容器的源码实现后置处理器分类Spring ioc的扫描与注册BeanDefinitionBeanDefinitionRegistry 阅读详情

相关推荐

WRF后处理总结:wrf-python与NCL在WRF后处理中的基本应用——变量提取、计算与可视化

判断需要提取的变量与诊断量确定后,使用getvar函数进行提取。可使用ncdump-h命令查看wrfout中的变量,wrf中的诊断量分类也可从官方文档处查阅。判断绘图类型所需的可视化绘图类型,决定了你在WRF后处理中的计算步骤。1D点线图:ll_to_xy interpline2D填色图:interplevel3D剖面图:vinterp vertcross绘图、美化色标、XY轴、标签的设置等等。

weixin_43750300的博客 1万+

spring源码阅读--IOC容器初始化之Beandefinition注册

经过这阵子对于spring源码的学习,对于spring框架的一些常见概念的实现原理有一定的了解,例如spring核心容器模块、spring aop的实现原理、spring mvc的实现原理、spring声明式事务实现原理等有一定的了解,在此记录下来自己的一些阅读源码经验。 spring是一个非常庞大的框架,其中包含许多模块。但是任务模块的基础,都是spring的核心容器模块,所以最先了解的源码部分...

嘎嘎的博客 560

FreeRTOS系统CPU使用率统计

操作系统中CPU使用率是在软件架构设计中必须要考虑的一个重要性能指标。它直接影响到程序的执行时间以及优先级更高的任务能否实时响应的问题。而CPU使用率也不能过低,避免资源浪费。

灵哎惹,凌沃敏的博客 1378

Spring源码阅读4-IOC容器-BeanDefinition的载入和解析

在上一节中,我们读源码到Resource的定位部分。 当DefaultResourceLoader返回Resource后,在AbstractBeanDefinitionReader中会对得到的Resource进行读取和解析。 下面是AbstractBeanDefinitionReader中对应的方法: public int loadBeanDefinitions(String location, ...

Jiakunboy的专栏 452

网口电路/Bob Smith电路思考及测试

上表中的数据为实际数据,此时可以看出在结果比对中,分别为以上三种时,结果基本上变化很小,且网口一致性指标都是测试通过的,而且如果真的Bob Smith电路是有阻抗变换的作用的,我的以上操作(保留阻容、去掉电阻、去掉电阻电容)完全破环了阻抗平衡,但是实际上对网口一致性指标没有多大的影响,这是我认为该电路不具有阻抗变换的第一个原因。网口变压器的共模电感,就是电流型中的T10、T14、T17、T18,我们知道辐射超标一般都是共模电流导致的,而共模电感就是来消耗差分线路中的共模电流的,而对差模电流基本无影响。

domen_pan的博客 6057

【网络】PFC背景和原理 、文档(DCB=PFC + ETS,DCBX=DCB扩展)

目录 零、背景 一、PFC 1.概述 2.报文格式 3.工作机制 二、ETS 产生原因 基本原理 优先级组的调度 优先级的调度 三、DCBX 产生原因 基本原理 DCBX TLV介绍 五、PFC 拥塞研究(文档收集) 六、DC-QCN算法 (网络工程师必会) 7.1 α更新 7.2 降速 7.3 提速 8.总结 ...

小鱼菜鸟的博客 2165

Spring源码阅读5-IOC容器-BeanDefinition的注册

在上一节,我们得到了BeanDefinitionHolder对象,即将Bean的解析和载入完成了,下面将会对这个对象进行注册到容器中。 在前面我们提到过,IOC容器实际上是一个Map, 在这里将得到验证。 我们从前面的分析得到,在DefaultBeanDefinitionDocumentReader类中的processBeanDefinition方法中: protected void proces...

Jiakunboy的专栏 358

制作INCA和CANape通用的A2L

CANape和INCA通用的A2L配置与修改

赞的博客 5962

Spring IOC 源码解析(四) BeanDefinition

一.前言 BeanDefinition是配置文件&amp;lt;bean&amp;gt;元素标签在容器中地内部表示。&amp;lt;bean&amp;gt;元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition 则提供了相应地beanClass、scope、lazyInit类属性,BeanDefinition 就像&amp;lt;bean&amp;gt;中镜中人,二者是一一对应地 来看一下整体的类结构...

Carey丶zsh 的博客 495

手把手教你完成YOLOv10 PySide6目标检测界面搭建,使用Qt6设计YOLOv10检测系统,前台系统+后台管理系统开发实战,可用于大论文凑工作量或毕设必备,全网最详细教程

手把手教你完成YOLOv10 PySide6目标检测界面搭建,使用Qt6设计YOLOv10检测系统,前台系统+后台管理系统开发实战,可用于大论文凑工作量或毕设必备,全网最详细教程

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1733

Android P车机添加屏幕多指全局自定义手势操作

参照原生状态栏全局下拉手势拦截,实现屏幕全局多指手势响应操作,并对手势进行转换为KeyEvent,以便项目自定义手势行为或应用拦截手势行为。

shusuanly的博客 1251

不看后悔系列-Spring源码(七):标签解析——BeanDefinition装载、注册,IOC第一阶段完结

/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */ protected void parseBeanDefinitions(Element root, Bean...

qq_33366098的博客 312

Spring AI Alibaba实战训练营-20 基于注解驱动的MCP快速开发入门指南

本文详细讲解如何使用SpringAiAlibaba快速开发基于注解驱动的MCP应用。文章详细介绍了MCP协议并且重点介绍了Spring AI通过注解驱动的开发方式简化MCP服务开发。具体包括服务端和客户端的注解使用、城市最新时间查询MCP项目结构概览(服务端和客户端模块)以及环境配置要求。

program哲学 295

深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质

本文深入解析Spring框架的核心组件之一,即BeanDefinition,探索Bean的本质。首先介绍了BeanDefinition的概念和作用,它是Spring中管理Bean配置元数据的接口,定义了Bean的各种属性和行为。接着,分析了BeanDefinition的实现类以及其重要属性,如Bean的类名、作用域、构造函数、依赖关系等。通过深入研究BeanDefinition的源码,揭示了Spring是如何管理和创建Bean实例的过程。

忆~遂愿的博客 5075

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring IOC 之加载 BeanDefinition

文章从解析源码的角度分析IOC的初始化过程,从 Bean 资源的定位,转换为 Document 对象,接着对其进行解析,最后注册到 IOC 容器中,清晰的进行了讲解。通俗易懂,希望对你有所帮助,

小徐的博客 1345

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring源码笔记,将BeanDefinition注册进IoC容器

这篇文章分享一下spring IoC容器初始化第三部分的代码,也就是将前面解析得到的BeanDefinition注册进IoC容器,其实就是存入一个ConcurrentHashMap<String, BeanDefinition>中。 1、回过头看一下前面在DefaultBeanDefinitionDocumentReader中实现的processBeanDefinition(Eleme...

Nicholas.S的博客 1267

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Spring IOC 源码解析

Spring5源码分析(二):        既然本文我们来分析 Spring IOC 源码,那么我们就先来讨论以下几个问题:①什么是 IOC?  ② IOC 能帮我们做哪些事情? 1.什么是 IOC         控制反转(Inversion o...

扛麻袋的少年的博客 3099

【老王读Spring IoC-2】Spring IoC之BeanDefinition扫描注册的原理

IoC之BeanDefinition扫描注册前言版本约定正文BeanDefinition 是怎么样被扫描出来的?BeanDefinition 是如何注册的?思考:Bean 的依赖关系是不是在 BeanDefinition 中存储的?总结 前言 Spring 要实现"控制反转"的功能,就需要解决 BeanDefinition 的扫描和注册问题。只有将 BeanDefinition 扫描出来了,才知道要创建哪些 bean 的实例。 所以,我们这次要研究的重点是: BeanDefinition 是怎么样被扫描

老王的专栏 1307

Spring源码笔记,IoC容器将bean解析封装成BeanDefinition,源码解析

接着上一篇的BeanDefinition资源定位开始讲。Spring IoC容器BeanDefinition解析过程就是把用户在配置文件中定义好的bean,解析成容器可以装载的BeanDefinition,BeanDefinition是对pojo类的封装,这样封装可以更好的对pojo类进行管理和操作。 1、先看一下AbstractRefreshableApplicationContext中refr...

Nicholas.S的博客 1242

【Spring】IOC:初始化流程源码分析(下)注册 BeanDefinition

向IOC容器注册在第二步解析好的 BeanDefinition,这个过程是通过 BeanDefinitionRegistery 接口来实现的。在 IOC 容器内部其实是将第二个过程解析得到的 BeanDefinition 注入到一个 HashMap 容器中,IOC 容器就是通过这个 HashMap 来维护这些 BeanDefinition 的。 在这里需要注意的一点是这个过程并没有完成依赖注入,依赖注册是发生在应用第一次调用 getBean() 向容器索要 Bean 时。当然我们可以通过设置预处理,即对某

A minor 1464

Spring原理与源码分析 BeanDefinition解析与注册

Spring 原理与源码分析(2025 年最新最硬核源码分析)这才是真正决定你能不能进大厂、能不能写框架、能不能年薪 60w+ 的灵魂问题。下面直接给你 Spring 6.1.x + Spring Boot 3.3(2025 年最新版),每一行代码都配图+注释,真正看懂了直接吊打 99.9% 的面试官。

likuoelie的博客 1008

Spring IOC容器核心揭秘:BeanFactory创建、配置加载&解析并注册为BeanDefinition

本文深入解析Spring框架IOC容器启动的关键步骤——BeanFactory创建与配置元数据加载。作为容器启动的基础阶段,该流程完成BeanFactory实例化、配置元数据解析转换(生成BeanDefinition)及注册到容器等核心操作。通过源码分析,文章详细剖析了XML配置加载的委托模式解析架构、BeanDefinition属性解析以及注册机制,揭示了Spring分层设计思想与资源配置抽象体系。该阶段为后续依赖注入提供基础,是理解Spring核心机制的关键切入点。

张小洛的BOLG 915

Spring IoC 源码解析:以 FileSystemXmlApplicationContext 为例,拆解 BeanDefinition 的资源定位过程

本篇技术指南聚焦于 Spring IoC 容器初始化的第一个阶段——**BeanDefinition 的资源定位(Resource 定位)**。文章以经典 XML 容器 `FileSystemXmlApplicationContext` 为切入点,沿着构造方法 → `refresh()` → `refreshBeanFactory()` → `loadBeanDefinitions()` → `D

gitblog_00252的博客 1029

Spring原理学习系列之六:IOC原理之BeanDefinition注册

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。//设置这个bean依赖被初始化的bean的名字。

2401_83329402的博客 838

Spring Framework源码解析——BeanDefinition

本文深入剖析了Spring框架中的核心组件BeanDefinition,它是描述Bean元数据的统一模型,作为连接配置与运行时对象的桥梁。文章从设计目标、接口层级、核心方法及字段展开,详细解析了BeanDefinition如何解耦配置与实例化,支持动态注册修改,并提供完整的元数据支持。通过分析AbstractBeanDefinition等实现类,阐述了Spring容器实现依赖注入、AOP代理等功能的底层机制,揭示了BeanDefinition在IoC容器中的核心地位。

谷哥的小弟 1195

如何扩展 Glojure 的 Go 互操作?gen-import-interop 生成自定义包映射教程

Glojure 是运行在 Go 上的 Clojure 解释器,通过内置的包映射(package map)机制让你直接在 Clojure 代码里调用 Go 包。当默认的互操作范围不够用时,你可以用 `gen-import-interop` 工具生成一份**自定义包映射**,把任意 Go 包暴露给 Clojure——本文从原理到实操,带你快速完成扩展。 [![Glojure 蓝色猫头鹰吉祥物,展示

gitblog_00374的博客 753
上一篇: Spring IOC 源码解析(六) XmlBeanFactory
下一篇: JDK8 之 Lambda 总结
Carey丶zsh
博客等级 码龄10年 15粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值