先说层次架构
// 水桶和上下文类层次概要(还有如何打水)
// 当你在使用FileSystemXmlApplicationContext之类的类时,你会感觉里面的方法调用错综复杂,层次很多。
// 那么,我们先从主要类的作用和层次说起,让我们有个大体的概念和印象,便于后面的分析。
// =====================================================解析相关============================================
// 解析第一步:读取资源
// 解析第二步:Document读取
// DefaultDocumentLoader,dom解析就不说了,和我们平时做dom解析应该没太大区别,我们平时可以借助很多不错的第三方框架。
// 解析第二步半:BeanDefinitionDocumentReader(资源整合,或者说功能抽取)
// 解析第三步:通过Document解析成BeanDefinition
再说执行过程
==============================FileSystemXmlApplicationContext==============================
*org.springframework.context.support.FileSystemXmlApplicationContext
比较常用的ApplicationContext有多种,我们选择一种FileSystemXmlApplicationContext进行入口分析。(几种ApplicationContext实现的区分基本在于资源获取方式和解析方式不同)
创建:
*1:refresh():(由最基础实现类AbstractApplicationContext提供)
**1.1:容器获取、数据解析入口:obtainFreshBeanFactory()具体实现refreshBeanFactory()留给子类实现
(因为AbstractApplicationContext就是具体的通用的资源准备,具体的计息读取规则应该由各分支子类实现):
AbstractRefreshableApplicationContext---refreshBeanFactory
***1.1.1:需要注意的是我们以后要用的BeanFactory--DefaultListableBeanFactory:
****1.1.1.1:创建之后会赋值给AbstractRefreshableApplicationContext的变量:
****1.1.1.2:并实现了AbstractApplicationContext声明的获取方法:
****1.1.1.3:同步的锁:
***1.1.2加载解析Bean的原始封装数据:BeanDefinitions -- loadBeanDefinitions(beanFactory)
这里主要指定了读取工具类(XmlBeanDefinitionReader),和执行解析入口。因为,我们的配置可以是多种形式的,这里需要具体资源形式的子类(AbstractXmlApplicationContext)去实现。
AbstractXmlApplicationContext:
****1.1.2.1这里的application environment的值是由最开始FileSystemXmlApplicationContext构造器中super(parent),一路调用父类构造器,最终在
AbstractApplicationContext中实现:
****1.1.2.2ResourceLoader是通过继承获得(AbstractApplicationContext extends DefaultResourceLoader)
****1.1.2.3EntityResolver:Allow the application to resolve external entities.
通过下面两个常量,我们可以猜是对格式规范的读取
****1.1.2.4为XmlBeanDefinitionReader准备好各种所需的资源后,就开始真正解析了:
这里是对我们前面赋值的资源便利读取:
*********1.1.2.4.1目前主要是下面那个String[]数组。
赋值的地方在AbstractRefreshableConfigApplicationContext(这也是我们为什么在AbstractRefreshableApplicationContext的基础上有多了个AbstractRefreshableConfigApplicationContext原因,单独为资源赋值形式抽取封装):
此方法调用是在我们上面的FileSystemXmlApplicationContext构造器中。
(所以到这里,可以看到,我们上面出现了很多很多不同地方,不同形式的赋值,这些赋值在以后的解析等过程中进行了各自的作用)
到这里我们ApplicationContext关于解析的工作告一段落,然后就是XmlBeanDefinitionReader如何具体解析:
上面准备了和计算出了很多环境条件,然后接下来就是具体的如何通过Xml解析成最初的Bean类型BeanDefinition
===================================解析===================================
1、开始是一连串的AbstractBeanDefinitionReader处理,做了他可以做的事情之后,具体的又交给了父类,也就是上面指定的XmlBeanDefinitionReader
2、XmlBeanDefinitionReader也有做了一大串的判断,在doLoadBeanDefinitions方法中调用了DefaultDocumentLoader的loadDocument获取了Document
3、然后又把一些资源和Document传给了DefaultBeanDefinitionDocumentReader,DefaultBeanDefinitionDocumentReader又做了一些介于Reader和纯Document解析之间的一些工作,包括各种解析判断走向什么的。
4、然后又通过BeanDefinitionParserDelegate,BeanDefinitionParserDelegate只接收了Element,根绝我们的规则解析出了BeanDefinitionHolder
5、最后我们又通过BeanDefinitionReaderUtils,把我们解析出的BeanDefinition注解进我们的容器DefaultListableBeanFactory。