Spring : XML配置 JavaBean源码解析

news2024/11/24 13:00:21

文章目录

  • 前言
  • 一、xml 加载 Bean 对象
    • 总结XML加载Bean对象


前言

跟着大佬走!!!! https://github.com/DerekYRC/mini-spring

在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、xml 加载 Bean 对象

大家先了解一下这个图,是作者给的定义

在这里插入图片描述

正片开始

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory-bean.xml"); 获取一个应用程序上下文对象,里面加载了xml 文件,最后将 xml 文件的对象取出,这里对应我们刚开始学 Spring 使用 xml 配置bean 对象。

在这里插入图片描述
在这里插入图片描述

接下来我们一步步 deBug 深入大佬源码。我会先上图再给注释,上图下描述,DeBug 走起。

在这里插入图片描述

在这里插入图片描述

先来到集成图的最下面 ClassPathXmlApplicationContext ,这里调用有参构造 ClassPathXmlApplicationContext 传入了xml文件名,然后把 classpath:factory-bean.xml 转换成了一个 String 数组,扔给了另一个重载的 有参构造。

在这里插入图片描述

到了个有参构造,把 configLocations 文件名数组,赋值给了全局变量 this.configLocations (也是一个字符串数组)。然后会调用 refresh( ) 方法,

在这里插入图片描述
在这里插入图片描述

refresh( ) 会来到 AbstractApplicationContext , 会先调用 refreshBeanFactory() 方法刷新 bean 工厂,所有会去到子类。

在这里插入图片描述
在这里插入图片描述

来到子类 AbstractRefreshableApplicationContext 的 refreshBeanFactory() 方法, 会先调用 createBeanFactory(); 创建默认的 bean 工厂,然后将 工厂扔给了 loadBeanDefinitions(beanFactory); 方法,加载 bean定义。

DefaultListableBeanFactory beanFactory = createBeanFactory(); 调用本类方法,创建默认的 bean 工厂

在这里插入图片描述

return new DefaultListableBeanFactory(); 会来到 DefaultSingletonBeanRegistry

在这里插入图片描述
在这里插入图片描述

由于 DefaultListableBeanFactory 集成了三个类,这里要对继承的类进行初始化操作,子类初始化,要先将父类进行加载。

在这里插入图片描述

拥有了默认的 bean 工厂后,将工厂扔给 本类的 loadBeanDefinitions(beanFactory); ,但是这是一个抽象方法,还是要到子类进行查看。

在这里插入图片描述

值得我们注意的是,这个方法还是抽象方法,由子类进行实现。我们还要跟着去子类,但是这一跟就会回到一开始 debug 的地方。

在这里插入图片描述在这里插入图片描述

XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory, this); 会去创建 一个 XmlBeanDefinitionReade 对象

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结XML加载Bean对象

首先我们先记住三个继承图在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

XML文件配置JavaBean要从一个 new ClassPathXmlApplicationContext("classpath:factory-bean.xml");开始读取XML文件。这个最终继承到 AbstractApplicationContext ,当我们传入xml文件时,会先将 文件名转换成一个数组,调用ClassPathXmlApplicationContext的重载方法,传入这个数组,然后依次加载父类,AbstractXmlApplicationContext, AbstractRefreshableApplicationContext, AbstractApplicationContext , DefaultResourceLoader, 初始化子类需要先加载父类,然后将文件数组赋值给成员变量 private String[] configLocations; 以便于后续获取这个文件名。

然后会调用 refresh(); 方法,这个方法会调用到 AbstractApplicationContext 的 refresh(); 方法 然后执行 refreshBeanFactory(); //创建BeanFactory,并加载BeanDefinition 但是这是个抽象方法 abstract ,需要到子类AbstractRefreshableApplicationContext去查看,就会到 AbstractRefreshableApplicationContext 对象的 refreshBeanFactory() 方法,会获取到一个 DefaultListableBeanFactory 对象, 默认的Bean工厂。

然后就是创建默认 Bean工厂(第二张继承图),这时由于 DefaultListableBeanFactory 还是最底层的类,初始化之前,还要去初始化父类,父类依次是 AbstractAutowireCapableBeanFactory, AbstractBeanFactory , DefaultSingletonBeanRegistry ,到 DefaultSingletonBeanRegistry 会依次加载 Spring 的三级缓存对于Spring的三级缓存,可自行搜索了解,和一个任意处理的 Bean容器 Map<String, DisposableBean> disposableBeans。然后一路返回到 DefaultListableBeanFactory 默认Bean工厂,返回的路上还会初始化父类的成员属性。
然后会调用 loadBeanDefinitions(beanFactory); 把这个默认的 bean工厂扔进去,很不巧的是,这个还是个抽象方法,就会到 AbstractRefreshableApplicationContext 的子类 AbstractXmlApplicationContext

来到 AbstractXmlApplicationContext 的 loadBeanDefinitions()方法,会得到一个 XmlBeanDefinitionReader 对象(第三张继承图),这个对象用来整个前两个继承图的两个体系,在 new XmlBeanDefinitionReader(beanFactory, this); 会传入两个参数,一个是默认的 bean工厂 DefaultListableBeanFactory , this 是谁调用就是谁,我们是从 ClassPathXmlApplicationContext 进来的,所以这个 this是ClassPAC ,这样就把两个继承体系整合在了一起。然后调用 getConfigLocations() 方法获取文件名,很不巧这个方法仍然是抽象方法,会去到子类 ClassPathXmlApplicationContext 正是我们一开始 DeBUG 的地方,设计的非常巧妙。

然后调用 XmlBeanDefinitionReader . loadBeanDefinitions(xml文件名 ) 方法, Xmlbean定义读取器加载 xml 文件,然后调用到父类 AbstractBeanDefinitionReader 的loadBeanDefinitions() 方法遍历出文件名。很不巧的是 loadBeanDefinitions 是重载方法,会再次重载到 XmlBeanDefinitionReader . loadBeanDefinitions( ) 这个地方重载的也非常妙。然后就是 getResourceLoader(); 之前 new XmlBeanDefinitionReader ,时传入了一个 ClassPathXmlApplicationContext 这个对象间接实现了 ResourceLoader,所以这里 getResourceLoader()会获取到 ClassPathXmlApplicationContext ;只不过这里使用 ResourceLoader 进行接收,然后调用 getResource (location文件名),后面会将这个文件名封装到一个 InputStream 读取xml 文件,然后调用 resource.getInputStream(); 获取到这个 InputStream 流。

最后到 doLoadBeanDefinitions(InputStream inputStream) 真正执行程序加载 xml 文件, //解析context:component-scan标签并扫描指定包中的类,提取类信息,组装成BeanDefinition , 标签属性 //id优先于name, //如果id和name都为空,将类名的第一个字母转为小写后作为bean的名称 , //beanName不能重名

//注册BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);

最后将解析xml 得到的 bean 放到 DefaultListableBeanFactory 默认bean工厂的 beanDefinitionMap 。

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
		beanDefinitionMap.put(beanName, beanDefinition);
	}

至此 XML 文件配置 Java Bean 结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/555441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业型OV,增强型EV证书开通审核流程

选购 OV、EV型证书需要是企业用户&#xff0c;申请过程中需要提交企业资料。 选择证书品牌及型号 管理中心补全审核资料 下载“确认函”签字盖章并扫描&#xff0c;再上传。 审核部门联系确认企业信息&#xff0c;&#xff08;过需要7-10个工作日&#xff09; 审核通过&…

单商户高级版商城系统v2.3.0更新啦~

​likeshop单商户高级版商城系统更新至v2.3.0版本~主要更新内容如下&#xff1a; 新增 商品增加限购功能 小程序新版本更新提示 商品分类创建后可以显示该分类下有多少商品 积分商品列表新增封面图 商品支持批量移动分类 后台产品正版检测 优化 分销功能关闭时&#xff…

网络安全 2023 年为什么如此吃香?事实原来是这样....

前言 “没有网络安全就没有国家安全”。当前&#xff0c;网络安全已被提升到国家战略的高度&#xff0c;成为影响国家安全、社会稳定至关重要的因素之一。 网络安全行业特点 1、就业薪资非常高&#xff0c;涨薪快 2021年猎聘网发布网络安全行业就业薪资行业最高人均33.77万…

机器学习基础知识之预测性能评价指标

文章目录 预测性能评价思路1、均方误差&#xff08;Mean Square Error&#xff0c;MSE&#xff09;2、均方根误差&#xff08;Root Mean Square Error&#xff0c;RMSE&#xff09;3、平均绝对误差&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;4、平均绝对百分比…

多线程-线程创建方式1:继承Thread类

线程创建方式1&#xff1a;继承Thread类 概述 Java语言的JVM允许程序运行多个线程&#xff0c;使用java.lang.Thread类代表线程&#xff0c;所有的线程对象都必须是Thread类或其子类的实例。Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的&#…

LeetCode:1049.最后一块石头的重量II 494.目标和 474.一和零

1049.最后一块石头的重量II 题目 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能…

pygam第5课——自制音乐播放器

前言&#xff1a;前几节课我们已经学会了很多知识点&#xff0c;欢迎大家可以去考古一下 今天我们将学习加载音乐&#xff0c;并且自制一个音乐播放器&#xff0c;界面功能包括&#xff1a; 加载背景封面上一首开始\暂停下一首重播随机播放快进 效果展示(GIF所以你们听不到声…

day6 广播及实现

什么是广播 数据包发送方式只有一个接受方&#xff0c;称为单播 如果同时发给局域网中的所有主机&#xff0c;称为广播 只有用户数据报(使用UDP协议)套接字才能广播 广播地址&#xff1a; 一个网络内主机号全为1的IP地址为广播地址 发到该地址的数据包被所有的主机接收 255…

MT6833(天玑 700)处理器参数_芯片规格_性能介绍

MT6833&#xff08;天玑700&#xff09;是一款出色的基带处理器&#xff0c;具有许多优秀的功能&#xff0c;并且采用了强大的八核CPU&#xff0c;其中包括两个主频高达2.2GHz的Arm Cortex-A76核心。此外&#xff0c;他还配备了LPDDR4X内存和UFS 2.2存储&#xff0c;大大提高了…

MyBatis中的#{}和${}有什么区别?

首先#{} 和 ${} 都是参数占位符&#xff0c;其中#{}是预编译处理&#xff0c;${}是字符直接进行替换。预编译处理是指&#xff1a;MyBatis 在处理#{}时&#xff0c;会将 SQL 中的 #{} 替换为?号&#xff0c;使⽤ PreparedStatement 的 set ⽅法来赋值。直接替换是指MyBatis 在…

【谷粒商城笔记】2. 创建项目与运行

1. 创建微服务项目 共分为下面五个 商品服务product 存储服务ware 订单服务order 优惠券服务coupon 用户服务member 1.1 新建github/gitee项目 首先去github新建项目 在IDEA中导入项目 从版本控制(Version Control)新建Project 选择路径和git链接 1.2 创建微服务 新建…

modscan模拟数据,nodred通过modbus协议向emqx创建规则引擎写入TDengine库

nodred通过modbus协议向emqx创建规则引擎写入TDengine库过程 一、emqx存储数据到TDEngine数据库1.1 进入emqx界面1.2 新建资源1.3 新建规则引擎1.4 测试 二、modscan模拟设备数据三、在Node-RED上模拟Modbus通讯3.1 nodeRed环境搭建3.2 nodeRed使用3.3 nodered读取modbus发送的…

Firewalld

目录 firewalld概述 firewalld 与 iptables 的区别 firewalld 区域的概念 firewalld防火墙预定义了9个区域 firewalld数据处理流程 firewalld检查数据包的源地址的规则 firewalld防火墙的配置方法 常用的firewall-cmd 命令选项 区域管理 服务管理 ​编辑端口管理 设…

创建项目执行计划的5个简单步骤

项目执行计划是定义项目将如何执行的文件。执行计划解释项目中涉及的战略目标和步骤&#xff0c;定义项目完成时间表&#xff0c;并列出成功项目所需的资源&#xff08;包括团队成员&#xff09;。 使用项目计划是多种项目管理最佳实践之一。这个过程并不像看起来那么复杂。按…

读财报丨产品收入增长近70%,百济神州已成功切换成长驱动模式?

5月12日&#xff0c;百济神州&#xff08;北京&#xff09;生物科技有限公司&#xff08;下称“百济神州”&#xff09;公布2023年第一季度业绩报告。从数据来看&#xff0c;延续了2022年的良好增长态势&#xff0c;实现营业收入30.66亿元&#xff0c;同比增长57%&#xff0c;而…

unity实现小球poke不穿膜

引言 在oculus quest2官方实现了手部指尖poke按键不穿膜&#xff0c;具体采用代码的方式进行限制&#xff0c;具体看oculus quest包中的HandPokeLimiterVisual.cs&#xff0c;下面则实现其他物体&#xff08;小球&#xff09;作为pokeInteractor来poke按键&#xff0c;当按下的…

Linux网络——shell编程之SNAT与DNAT的应用

Linux网络——shell编程之SNAT与DNAT的应用 一、SNAT的介绍1.SNAT概述2.SNAT源地址转换过程 二、SNAT转换三、DNAT的介绍1.DNAT概述2.DNAT转换前提条件 四、DNAT的转换五、防火墙规则的备份和还原六、tcpdump抓包工具的运用 一、SNAT的介绍 SNAT&#xff08;SNAT&#xff09;一…

蓝桥杯数论总结:最大公约数和最小公倍数(原理+性质证明+python板子)

目录 最大公约数 手写GCD 最小公倍数 推导LCM函数表达式 GCD基本性质 性质的证明 取模运算基本性质 证明 最大公约数 gcd是最大公约数的意思。Python的math库里有gcd函数。 在Python命令行运行gcd&#xff0c;可发现其可传入0、不会返回负数、可对多个数进行判断的性质…

利用 DynamoDB 和 S3 结合 gzip 压缩,最大化存储玩家数据

前言 一些传统游戏架构中&#xff0c;采用 MySQL 存储玩家存档数据&#xff0c;利用分库分表分散单库单表的存储和性能压力&#xff0c;从而达到支持更多玩家的目的。随着数据量增长&#xff0c;数据表中 varchar 类型已经无法满足游戏中单字段的存储需求&#xff0c;而 blob …

数据结构 -最短路径dijkstra(迪杰斯特拉)算法讲解及代码实现

迪杰斯特拉算法是一种广义的贪心算法&#xff0c;求出局部最优解&#xff0c;再去求全局最优解 图文讲解&#xff1a; 举例图&#xff1a;&#xff08;起始点为1&#xff09; 辅助数组&#xff1a; s&#xff1a;记录了目标顶点到其他顶点的最短路径是否求得&#xff08;求得…