本篇文章是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解析
解析
最终,你回本溯源,你还是拿起了当初的那本《设计模式》,你终于深深地体会到了里面闪烁的智慧