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

spring,源码,xml,文件,bean,标签,解析 · 浏览次数 : 17

小编点评

读取XML文件,创建对象xml文件里包含Bean的信息,为了避免多次IO,需要一次性读取xml文件中所有bean信息,加入到Spring工厂。读取配置文件new ClassPathResource(\"applicationContext.xml\")ClassPathResource是Spring封装的一个类型;Resource接口 :可以读取相关资源文件的内容 获得输入流;可读取的类型,不仅包括本地的xml、 properties、txt 等文件,还包括网络中的资源。它有父接口,InputStreamSource,其中定义了一个getInputStream方法,用来获取输入流。 **读取XML文件后,如何在Spring中以对象的形式进行封装以BeanDefinition的形式存在,用的最多的实现类是GenericBeanDefinition。** Spring底层如何通过读取 XML 封装成BeanDefinition呢使用XmlBeanFactory中的XmlBeanDefinitionReader对象的方法。XmlBeanDefinitionReader读取XML文件并构建BeanDefinition实例。 **解析基本标签** * import标签可以引入其他的配置文件 * * ... **解析自定义标签** *

正文

读取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

与Spring源码之XML文件中Bean标签的解析1相似的内容:

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

## 读取XML文件,创建对象 xml文件里包含Bean的信息,为了避免多次IO,需要一次性读取xml文件中所有bean信息,加入到Spring工厂。 #### 读取配置文件 ```java new ClassPathResource("applicationContext.xml") ``` Cl

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

### 读取XML文件,创建默认bean标签对象的核心代码 ```markdown 在DefaultBeanDefinitionDocumentReader类中的如下方法中: protected void processBeanDefinition(Element ele, BeanDefiniti

《系列一》-- 5、xml配置文件解析之[自定义]命名空间[标签]的解析

阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。 Spring源码阅读系列--全局目录.md 引子 1、容器最基本使用.md 系列1 - bean 标签解析: 2、XmlBeanFactory

《系列一》-- 4、xml配置文件解析之[默认]命名空间[标签]的解析

阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。 Spring源码阅读系列--全局目录.md 引子 1、容器最基本使用.md 系列1 - bean 标签解析: 2、XmlBeanFactory

《系列一》-- 3、XmlBeanFactory 对xml文件读取

阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。 Spring源码阅读系列--全局目录.md 引子 1、容器最基本使用.md 系列1 - bean 标签解析: 2、XmlBeanFactory

Spring源码——初识Spring容器

## Spring源码之工厂(容器) ### 为什么把Spring的工厂又叫做容器呢? 工厂的责任是创建对象,但是创建完对象后还要进行存储(针对于单例的对象来讲),以供其他地方使用,这就是容器。为了能存多个对象,并能方便查找,所以Spring创建的单实例对象是通过类似map的结构来存储的。 ```m

源码学习之Spring容器创建原理

1 前言 众所周知,Spring可以帮我们管理我们需要的bean。在我们需要用到这些bean的时候,可以很方便的获取到它,然后进行一系列的操作。比如,我们定义一个bean MyTestBean public class MyTestBean { private String testStr = "t

入门篇-其之四-字符串String的简单使用

什么是字符串? 在Java编程语言中,字符串用于表示文本数据。 字符串(String)属于引用数据类型,根据String的源码,其头部使用class进行修饰,属于类,即引用数据类型。 字符串的表示 字符串使用双引号""表示,在双引号中你可以写任意字符。 和前面定义并初始化基本数据类型的变量一样,定义

上周热点回顾(6.3-6.9)

热点随笔: · C#开源实用的工具类库,集成超过1000多种扩展方法 (追逐时光者)· RabbitMQ 进阶使用之延迟队列 → 订单在30分钟之内未支付则自动取消 (青石路)· .Net 中间件 - 新开源代码生成器 -ReZero (阿妮亚)· C#.Net筑基-String字符串超全总结 [深

Spring源码阅读系列--全局目录

> 阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证。全系列文章基于 spring 源码 5.x 版本。 写在开始前的话: 阅读spring 源码实在是一件庞大的工作,不说全部内容,单就最基本核心部分包含的东西就需要很长时间去消化了: - be