首页 > 编程语言 >Spring源码之XML文件中Bean标签的解析1

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

时间:2023-08-05 20:23:24浏览次数:51  
标签:XML xml 读取 Spring 源码 标签 解析 BeanDefinition

读取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;
        存储BeanDefinition
    
        private 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

标签:XML,xml,读取,Spring,源码,标签,解析,BeanDefinition
From: https://www.cnblogs.com/nicaicai/p/17608543.html

相关文章

  • SpringBoot+SpringCloud面试题整理附答案
    什么是SpringBoot?1、用来简化spring初始搭建和开发过程使用特定的方式进行配置(properties或者yml文件)2、创建独立的spring引用程序main方法运行3、嵌入Tomcat无需部署war包,直接打成jar包nohupjava-jar–&启动就好4、简化了maven的配置4、自动配置spring添加对应的starter自......
  • 智慧工地管理平台源码,视频监控、劳务实名制、环境监测、安全质量管理、GIS地理信息、
    智慧工地可视化系统利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术,通过工地中台、三维建模服务、视频AI分析服务等技术支撑,实现智慧工地高精度动态仿真,趋势分析、预测、模拟,建设智能化、标准化的智慧工地综合业务系统,解决传统工地管理存在的弊端,更好的提高工地......
  • 在SpringBoot框架中集成MyBatis
    使用MyBatis框架操作数据,在SpringBoot框架中集成MyBatis。使用步骤如下:1、准备好数据库?serverTimezone=GMT2、MyBatis起步依赖:完成MyBatis对象自动配置,对象放在容器中创建模块的时候,需要勾选springweb、MyBatisFramework、MySQLDriver这三个pom.xml文件<?xmlversion="1.0"e......
  • SpringBoot学习笔记--过滤器Filter
    一、普通过滤器Filter是Servlet规范中的过滤器,可以处理请求,对请求的参数、属性进行调整。常常在过滤器中处理字符编码。1、创建自定义过滤器类packagecom.cqjtu.vo;importjavax.servlet.*;importjava.io.IOException;//自定义过滤器类publicclassMyFilterimplements......
  • 创建一个基于SpringBoot的web项目
    1、使用国内地址创建SpringBoot项目国内地址:https://start.springboot.io/2、项目结构1:Java目录下放Java相关文件2:static目录下放.css.html.js等文件,包括图片之类的3:templates目录下放模板文件4:放SpringBoot主要配置文件3、创建基于SpringBoot的web案例在上面基础之上,进行下......
  • pom.xml
    打包插件<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.2.4</version>......
  • 4 Diac中E_CYCLE模块源码分析
    E_CYCLE的源码分析一E_CYCLE的功能输入事件接口:START、STOP,输出事件接口EO数据输入接口:DTSTART是开启定时事件,STOP结束定时事件,EO是时间到了触发的事件,DT是配置时间间隔参数,数据类型为字符串类型。举例:DT输入T#10MS,则10MS触发一次EO事件   二源码分析该源码主要......
  • Android开发 Jetpack Compose 与xml的混合开发AndroidView
    前言  JetpackCompose虽然已经逐渐完善,但是其实还是有很多地方未满足需求。比如播放视频、相机预览等等依然需要原来的View。所以目前阶段JetpackCompose与xml的混合开发非常重要。  官方文档地址:https://developer.android.google.cn/jetpack/compose/migrate/interopera......
  • 随笔(二十六)『SpringBoot + Vue 简单部署到Linux』
    1、安装docker1.1、卸载系统之前的dockersudoyumremovedocker\docker-client\docker-client-latest\docker-common\docker-latest\docker-latest-logrotate\......
  • Spring-Retry 重试机制小计
    在实际工作中,重处理是一个非常常见的场景,比如:发送消息失败。调用远程服务失败。争抢锁失败。这些错误可能是因为网络波动造成的,等待过后重处理就能成功。通常来说,会用try/catch,while循环之类的语法来进行重处理,但是这样的做法缺乏统一性,并且不是很方便,要多写很多代码。然而sprin......