本篇文章是Springframework源码阅读系列第一章第一节,其主要讲解Spring是如何把xml配置文件一步一步加载成Document对象最终被装换成Bean对象的。主要通过代码领读的方式去深入探索(图中的注解同样重要,注意查看)。


Spring加载bean的流程:

①读取xml文件->②生成Document对象->③根据命名空间策略处理Document生成BeanDefinition->④注册到BeanFactory

然后你就可以通过getBean(args..)获取你的Bean对象了。

其中①②本篇文章讲解,③④下一篇讲解。

项目入口


跟进ClassPathXmlApplicationContext类:

我们发现,这个类并没有做什么太多的处理,只有两个作用

调用父类构造将父上下文上传
将bean配置xml,转换成Resource资源
1. 调用父类构造将父上下文上传,我们只要明白他是干什么的就行,我们举一个例子: 当Spring上下文已经被加载了,此时已经有一个ApplicationContext(A1)了,

此时我们在去读取配置文件,那么A1就是一个父上下文。super(A1),就是将A1已经加载的Bean合并到新的上下文中。


Code例子:


2.将bean配置xml,转换成Resource资源


这里为什么要转换成Resource主要是Resource接口有一些对文件处理的接口。方便Spring对文件的读取,进行一些

加工。


怎么样,简单吧,我们经常用的ClassPathXmlApplicationContext就是这么简单,主要就只有这两个功能。当你读到这里的时候

开始前的准备我们已经做好了,此时我们有①父上下文和②xml文件的资源信息Resource了。接下来我们就要对xml进行处理了。

此时我们就进去了refresh()方法。这个方法是一个抽象方法。其实现是AbstractApplicationContext去实现的.refresh就是整个ioc容器启动的全过程。我们IOC模块的讲解,可以说就是讲refresh()的所有过程。为了方便我们解释,小编把refresh截图下来,之后第一章其他三小节课程都会用到该图。


为了让大家先有一个思路,小编做一个小小的总结:

IOC核心的调用流程,其实都是在AbstractApplicationContext调用的,但是其真正的实现都是在子类中去实现的. 在我们真正开始分析前,我们先自己思考下Spring可能会做哪些事情?以下是小编的思考,小编也是按照这个逻辑一点一点去refresh()方法中去查找的。

读取XML转换成Resource,从中获取InputStream资源输入流【这一步ClassPathXmlApplicationContext中已经完成】
将资源输入流转换成SAX解析(xml解析的一种方式)为Document对象,并进行DTD和XSD校验

refresh()

本部分内容请结合图中注释查看。

当调用refresh()方法首先会运行(1)方法.主要做准备工作


然后运行方法(2): 通过名字我们可以知道这点是创建BeanFactory的,而前面我们又说了BeanFactory之所以能创建生成Bean是因为

其保存了Bean的相关信息。这个类叫BeanDefinition。那么我们思考无论是@Component和xml的形式配置的Bean对象,其实都是要转换成BeanDefinition交给BeanFactory来保管的,那么我们猜测xml的配置处理一定是在这个方法(2)中处理的。我们看下图

AbstractApplicationContext:


其中refreshBeanFactory()和getBeanFactory()都属于抽象方法其实现都是有其子类

AbstractRefreshableApplicationContext实现的。

我们来看refreshBeanFactory方法:

主要做了3件事:

①: 先判断是否已经存在BeanFactory,存在就销毁,重新创建

②: 创建一个BeanFactory,对BeanFactory做一些限定,并合并父容器code->new DefaultListableBeanFactory(getInternalParentBeanFactory());

③: 加载BeanDeanDefinitions,那么我们判断XMl的读取一定在这个里面。


因为本篇的主要内容就是解析xml所以我们深入跟进loadBeanDefinitions()


发现其还是一个抽象接口,其由子类AbstractXmlApplicationContext提供实现


我们主要看loadBeanDefinitions()方法,从这里开始就可以和上面ClassPathXmlApplicationContext的作用接住了。

我们还记得ClassPathXmlApplicationContext有一个作用就是将bean的配置文件xml,转换成Resource资源。

而loadBeanDefinitions就要从这个资源里面去读取配置了。

AbstractBeanDefinitionReader

XmlBeanDefinitionReader:


doLoadDocument()

从名字就可以看出来肯定是把xml转换成document的


到这里xml文件就已经被解析成Document对象了。

总结

以上就是Spring解析xml的全过程,通过上面的学习我们就知道xml是如何被加载转换成Document的。

本篇文章的主要内容就是这些。详细描述了xml是如何一步一步被Java加载的。内容比较简单,但是比较重要,这一步清楚了,下一篇就简单的很了。

在下一篇<

扩展知识

这部分属于基础,是关于xml转换document的基础,如果你还不清楚的话,可以看看这部分

① xml约束(主要是对xml文件做一些约束,比如限定标签属性值的类型)

schema约束和dtd约束的区别:

  ⑴XML Schema符合XML语法结构。

  ⑵DOM、SAX等XML API很容易解析出XML Schema文档中的内容。

  ⑶XML Schema对名称空间支持得非常好。

  ⑷XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。

  ⑸XML Schema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。

  ⑹XML Schema不能像DTD一样定义实体,比DTD更复杂,但Xml Schema现在已是w3c组织的标准,它正逐步取代DTD。

②Document解析


解析

最终,你回本溯源,你还是拿起了当初的那本《设计模式》,你终于深深地体会到了里面闪烁的智慧