Spring IOC基于XML容器的初始化(中)

6、分配路径处理策略
在 XmlBeanDefinitionReader 的抽象父类 AbstractBeanDefinitionReader 中定义了载入过程。AbstractBeanDefinitionReader 的 loadBeanDefinitions()方法源码如下:

AbstractRefreshableConfigApplicationContext 的 loadBeanDefinitions(Resource...resources) 方法实际上是调用 AbstractBeanDefinitionReader 的 loadBeanDefinitions()方法。从对 AbstractBeanDefinitionReader 的 loadBeanDefinitions()方法源码分析可以看出该方法就做了两件事:
首先,调用资源加载器的获取资源方法 resourceLoader.getResource(location),获取到要加载的资源。
其次,真正执行加载功能是其子类 XmlBeanDefinitionReader 的 loadBeanDefinitions()方法。在loadBeanDefinitions()方法中调用了 AbstractApplicationContext 的 getResources()方法,跟进去之后发现 getResources()方法其实定义在 ResourcePatternResolver 中,此时,我们有必要来看一下ResourcePatternResolver 的全类图:

 

 

 

从上面可以看到 ResourceLoader 与 ApplicationContext 的继承关系,可以看出其实际调用的是DefaultResourceLoader中的getSource() 方法定位Resource,因为ClassPathXmlApplicationContext 本身就是 DefaultResourceLoader 的实现类,所以此时又回到了ClassPath-XmlApplicationContext 中来。 
7、解析配置文件路径
XmlBeanDefinitionReader通过调用ClassPathXmlApplicationContext的父类DefaultResourceLoader 的 getResource()方法获取要加载的资源,其源码如下:

DefaultResourceLoader 提供了 getResourceByPath()方法的实现,就是为了处理既不是 classpath标识,又不是 URL 标识的 Resource 定位这种情况。

在 ClassPathResource 中完成了对整个路径的解析。这样,就可以从类路径上对 IOC 配置文件进行加载,当然我们可以按照这个逻辑从任何地方加载,在 Spring 中我们看到它提供的各种资源抽象,比如ClassPathResource、URLResource、FileSystemResource 等来供我们使用。上面我们看到的是定位Resource 的一个过程,而这只是加载过程的一部分。例如 FileSystemXmlApplication 容器就重写了getResourceByPath()方法。

通过子类的覆盖,巧妙地完成了将类路径变为文件路径的转换。 

8、开始读取配置内容

继续回到 XmlBeanDefinitionReader 的 loadBeanDefinitions(Resource …)方法看到代表 bean 文件的资源定义以后的载入过程。

 

通过源码分析,载入 Bean 配置信息的最后一步是将 Bean 配置信息转换为 Document 对象,该过程由documentLoader()方法实现。
9、准备文档对象 
DocumentLoader 将 Bean 配置资源转换成 Document 对象的源码如下: 

 

上面的解析过程是调用 JavaEE 标准的 JAXP 标准进行处理。至此 Spring IOC 容器根据定位的 Bean 配、置信息,将其加载读入并转换成为 Document 对象过程完成。接下来我们要继续分析 Spring IOC 容器将载入的 Bean 配置信息转换为 Document 对象之后,是如何将其解析为 Spring IOC 管理的 Bean 对象并将其注册到容器中的。

10、分配解析策略
XmlBeanDefinitionReader 类中的 doLoadBeanDefinition()方法是从特定 XML 文件中实际载入Bean 配置资源的方法,该方法在载入 Bean 配置资源之后将其转换为 Document 对象,接下来调用registerBeanDefinitions() 启 动 Spring IOC 容 器 对 Bean 定 义 的 解 析 过 程 ,registerBeanDefinitions()方法源码如下:

Bean 配置资源的载入解析分为以下两个过程:首先,通过调用 XML 解析器将 Bean 配置信息转换得到 Document 对象,但是这些 Document 对象并没有按照 Spring 的 Bean 规则进行解析。这一步是载入的过程其次,在完成通用的 XML 解析之后,按照 Spring Bean 的定义规则对 Document 对象进行解析,其解析过程是在接口BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader 中实现。 
11、将配置载入内存
BeanDefinitionDocumentReader 接 口 通 过 registerBeanDefinitions() 方 法 调 用 其 实 现 类DefaultBeanDefinitionDocumentReader 对 Document 对象进行解析,解析的代码如下:

通过上述 Spring IOC 容器对载入的 Bean 定义 Document 解析可以看出,我们使用 Spring 时,在Spring 配置文件中可以使用<import>元素来导入 IOC 容器所需要的其他资源,Spring IOC 容器在解析时会首先将指定导入的资源加载进容器中。使用<ailas>别名时,Spring IOC 容器首先将别名元素所定义的别名注册到容器中。对于既不是<import>元素,又不是<alias>元素的元素,即 Spring 配置文件中普通的<bean>元素的解析由 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement()方法来实现。这个解析的过程非常复杂,我们在 mini 版本的时候,就用 properties 文件代替了。

猜你喜欢

转载自www.cnblogs.com/47Gamer/p/13200422.html