Spring源码之XML文件中Bean标签的解析1

读取XML文件,创建对象

xml文件里包含Bean的信息,为了避免多次IO,需要一次性读取xml文件中所有bean信息,加入到Spring工厂。

读取配置文件

new ClassPathResource("applicationContext.xml")

ClassPathResource是Spring封装的一个类型;

Resource

Resource接口 :可以读取相关资源文件的内容 获得输入流;可读取的类型,不仅包括本地的xml、 properties、txt 等文件,还包括 网络中的资源。它有父接口,InputStreamSource,其中定义了一个getInputStream方法,用来获取输入流。

ClassPathResource类中对getInputStream方法的实现。

截图

Resource将xml配置文件读取到jvm中,那jvm中是如何体现xml中的bean呢?

因为一切皆对象,所以肯定是以对象的方式存在的。标签就会以BeanDefinition对象的方式存在于jvm中。

Spring通过SAX的技术手段,对xml解析,封装BeanDefiniton。

IOC的核心

下方代码所代表的含义,实际上就是IOC的核心:

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

它包括以下几个问题:

  1. 怎么读取配置文件 获得IO资源
  2. 读取配置文件后,如何在Spring中以对象的形式进行封装
  3. 根据配置信息创建对象
  4. 所创建对象的生命周期
怎么读取配置文件 获得IO资源

通过Resource接口的实现类,比如ClassPathResource,得到InputStream。

读取配置文件后,如何在Spring中以对象的形式进行封装

以BeanDefinition的形式存在,用的最多的实现类是GenericBeanDefinition。

截图

Spring底层如何通过读取 XML 封装成BeanDefinition呢

使用XmlBeanFactory中的XmlBeanDefinitionReader对象的方法。

截图

Spring标识XmlBeanFactory过期了,可以用以下代码替换:

DefaultListableBeanFactory beanFactory1 = new DefaultListableBeanFactory();
Resource resource = new ClassPathResource("applicationContext.xml");
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory1);
xmlBeanDefinitionReader.loadBeanDefinitions(resource);Object product1 = beanFactory1.getBean("product"); 
System.out.println("product1 = " + product1);

但是比较繁琐,我们分析源码还是使用XmlBeanFactory来分析。

Spring底层如何做到通过XmlBeanDefinitionReader读取 XML封装成BeanDefinition呢?

类属性截图

Spring允许在一个工程中有多个Spring工厂同时出现 ,但是情况非常少见 。

比如SpringMVC中 父子容器
DispatcherServlet ---- childFactory
ContextLoaderListener ---- rootFactory

方法截图

InputStream inputStream = encodedResource.getResource().getInputStream();
这行代码是封装成SAX的InputStream类型,对xml进行解析。
最主要的就是return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
来加载BeanDefinition。

方法截图

Document doc = doLoadDocument(inputSource, resource);
这行代码得到的还是XML解析封装的对象。
int count = registerBeanDefinitions(doc, resource);
这行代码就是注册BeanDefinition的方法,并返回注册的数量。

方法截图

方法截图

方法截图

parseDefaultElement(ele, delegate);用来解析基本标签比如:<bean id="" class="" scope="" parent="" init-method=""<property name  value</bean><bean id="" class="" scope="" parent="" init-method=""<construt-arg></bean>
delegate.parseCustomElement(ele);解析自定义标签比如:<context:propertyplace-holder<context:component-scan..<tx:annotation-driven<mvc:annotation-drvent<aop:config

我们目前看基本标签的解析;

parseDefaultElement

  • import标签

    可以引入其他的配置文件
    <import resource="applicationContext1.xml"/>
    <import resource="applicationContext2.xml"/>
    <import resource="applicationContext3.xml"/>
    
  • alias标签

    别名
    <bean id="product" name= "p"  class="xxxx.xxx.Product"/>name代表别名
    也可以这样写
    <bean id="user"  class="xxxx.xxx.User"/>
    <alias name="user" alias="u"/>
    alias标签也可以写别名
    
  • beans标签上文已经讲过

  • bean标签——用的最多,着重分析

    processBeanDefinition

    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);解析标签里的元素,封装成BeanDefinitionHolder(对BeanDefinition做了一层包装)其中有三个属性private final BeanDefinition beanDefinition;存储BeanDefinitionprivate final String beanName;存储id值,如果没有id,就是name值如果也没有name,会自动生成一个private final String[] aliases;存储别名bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);如果有自定义标签,再解析自定义标签BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());将BeanDefinition,以id为key存储到map中getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));发送注册完成的事件;此方法是空实现,可以自己实现
    
    parseBeanDefinitionElement重载1
    此方法用来解析id、别名,判断id是否唯一、调用parseBeanDefinitionElement重载2;若id,name都没有,生成id等操作。
    

parseBeanDefinitionElement重载

parseBeanDefinitionElement重载2
此方法用来解析class标签,创建BeanDefinition、解析scope、abstract标签等。

parseBeanDefinitionElement重载2

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 仿京东头部滚动头像动态变化

UI出了一个新需求&#xff0c;仿京东头部滚动&#xff0c;头像需要动态变化&#xff0c;先来看下京东的是什么效果 我们知道什么效果以后&#xff0c;接下来就想想怎么实现吧&#xff0c;Android常规吸顶折叠布局是由CoordinatorLayoutAppBarLayoutCollapsingToolbarLayout组成…

express学习笔记5 - 自定义路由异常处理中间件

修改router/index.js&#xff0c;添加异常处理中间件 *** 自定义路由异常处理中间件* 注意两点&#xff1a;* 第一&#xff0c;方法的参数不能减少* 第二&#xff0c;方法的必须放在路由最后*/ router.use((err, req, res, next) > {console.log(err);const msg (err &…

SpringCloud入门Day01-服务注册与发现、服务通信、负载均衡与算法

SpringCloudNetflix入门 一、应用架构的演变 伴随互联网的发展&#xff0c;使用互联网的人群越来越多&#xff0c;软件应用的体量越来越大和复杂。而传统单体应用 可能不足以支撑大数据量以及发哦并发场景应用的框架也随之进行演变从最开始的单体应用架构到分布式&#xff08…

Python零基础入门(十一)——异常处理

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python入门专栏&#xff1a;《Python入门》欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; 码字不易&#xff0c;如果觉得文章不…

远程访问本地mysql

文章目录 一、设置本地mysql允许外部访问找到mysql配置文件my.ini &#xff0c;linux环境是my.cnf配置mysql配置文件 二、创建外部访问的mysql用户三、配置mysql用户的权限四、配置防火墙端口五、连接查看本地ip地址 参考 连接命令 mysql -h <host> -P <port> -u &…

深度学习之双线性插值

1、单线性插值 单线性插值是一种用于估计两个已知数据点之间未知点的方法。它基于线性关系&#xff0c;通过计算目标位置的值&#xff0c;使用已知点之间的线性函数进行插值。这在图像处理中常用于放缩、旋转等操作&#xff0c;计算简单&#xff0c;产生平滑结果&#xff0c;但…

将python源代码打包成.exe可执行文件

步骤 1、安装pyinstaller2、打开终端或命令提示符窗口并进入解释器的虚拟环境3、从解释器的虚拟环境进入包含要打包Python文件的目录4、通过以下命令打包5、打包后文件存放位置 1、安装pyinstaller pip install pyinstaller2、打开终端或命令提示符窗口并进入解释器的虚拟环境…

Win11大小写切换图标关闭方法

大家使用Win11操作系统的时候经常会切换大小写键盘&#xff0c;有些游戏本在游戏过程中需要切换大小写&#xff0c;这个时候电脑的屏幕就会出现大小写切换的图标而影响游戏体验&#xff1b; 那么想要关闭Win11电脑上大小写切换图标&#xff0c;又不知道具体怎么操作&#xff0c…

vscode如何退出/切换 github 账号

退出/切换 github 账号 左下角点击头像按钮&#xff0c;选择注销&#xff0c;然后再重新登录

阿里为啥禁止三表Join关联?

阿里出过一个《Java开发手册》&#xff0c;上面有一条规约是禁止超过三张表的join。 为什么要禁止&#xff0c;其实最主要的原因就是join的效率比较低。 mysql只有一种表连接类型:嵌套循环连接(nested-loop)&#xff0c;不支持排序-合并连接(sort-merge join)与散列连接(hash …

纯JS+Vue实现一个仪表盘

在使用canvas的时候发现数值变化&#xff0c;每次都要重新渲染&#xff0c;值都从0开始&#xff0c;这和我的需求冲突。 1. 先绘制基本的圆环背景&#xff0c;利用border-color和border-radius将正方形变成基本的圆环。 <div class"circle"><div class&qu…

Docker实战-操作Docker容器实战(二)

导语   上篇分享中,我们介绍了关于如何创建容器、如何启动容器、如何停止容器。这篇我们来分享一下如何操作容器。 如何进入容器 可以通过使用-d参数启动容器后会进入后台运行,用户无法查看容器中的信息,无法对容器中的信息进行操作。 这个时候如果我们需要进入容器对容器…

利用XSS在线平台获取用户cookie

//XSS弹窗&#xff1a; <script>alert("xss")</script> XSS漏洞&#xff1a; //XSS弹窗&#xff1a; <script>alert("xss")</script> //XSS在线平台&#xff1a; <ScRipT sRc//7ix7kigpovxdbtd32fuspgffmtmufo3wwzgnzaltddewtb…

iMX6ULL应用移植 | 移植 infoNES 模拟器(重玩经典NES游戏)

没玩过NES游戏的童年&#xff0c;可能不是80后的童年。我们小时候是从玩FC开始接触游戏机的&#xff0c;那时真的是红极一时啊&#xff0c;我上初中时还省吃俭用买了一台小霸王&#xff0c;暑假里把电视机都给打爆了&#xff01;那时任天堂单是FC机的主机的发售收入就超过全美的…

程序环境和预处理(含C语言程序的编译+链接)--1

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f43b;‍❄个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN…

在CentOS 7上挂载硬盘到系统的步骤及操作

目录 1&#xff1a;查询未挂载硬盘2&#xff1a;创建挂载目录3&#xff1a;检查磁盘是否被分区4&#xff1a;格式化硬盘5&#xff1a;挂载目录6&#xff1a;检查挂载状态7&#xff1a;设置开机自动挂载总结&#xff1a; 本文介绍了在CentOS 7上挂载硬盘到系统的详细步骤。通过确…

完全背包问题

题目链接 题意&#xff1a;在01背包的基础上多了每个物品都可以无限取的条件 思路&#xff1a;首先考虑在01背包的基础上的暴力枚举&#xff0c;我们可以在枚举前i件物品最多拿j的容量时再遍历当前物品拿的数量 贴一个暴力tle代码&#xff1a; #include<bits/stdc.h> #d…

【云原生K8s】初识Kubernetes的理论基础

K8S由google的Borg系统(博格系统&#xff0c;google内部使用的大规模容器编排工具)作为原型&#xff0c;后经GO语言延用Borg的思路重写并捐献给CNCF基金会开源。 云原生基金会&#xff08;CNCF&#xff09;于2015年12月成立&#xff0c;隶属于Linux基金会。CNCF孵化的第一个项目…

短视频矩阵源码

一、短视频矩阵源码搭建解析&#xff1a; 目录 一、短视频矩阵源码搭建解析&#xff1a; 二、短视频矩阵源码的开发路径分享&#xff1a; 三、短视频矩阵系统开发应具备哪些能力&#xff1f; 短视频技术开发能力&#xff1a; 开发人员应具备短视频相关技术能力&#xff0c…

iOS 后台运行

iOS后台行&#xff0c;一般有两种方式&#xff1a; 1.UIBackgroundTaskIdentifier后台任务标记时, 2.设置后台运行模式&#xff0c;需要有voip&#xff0c;location功能的才行。不然app上线审核肯定是过不了的。 下面是我学习后台运行的尝试过程。 一.首先创建一个项目功程…