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

12、载入<bean>元素
Bean 配置信息中的<import>和<alias>元素解析在 DefaultBeanDefinitionDocumentReader 中已经完成,对 Bean 配置信息中使用最多的<bean>元素交由 BeanDefinitionParserDelegate 来解析,其解析实现的源码如下:
     

 只要使用过 Spring,对 Spring 配置文件比较熟悉的人,通过对上述源码的分析,就会明白我们在 Spring配置文件中<Bean>元素的中配置的属性就是通过该方法解析和设置到 Bean 中去的。注意:在解析<Bean>元素过程中没有创建和实例化 Bean 对象,只是创建了 Bean 对象的定义类BeanDefinition,将<Bean>元素中的配置信息设置到 BeanDefinition 中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的 Bean 对象。上面方法中一些对一些配置如元信息(meta)、qualifier 等的解析,我们在 Spring 中配置时使用的也不多,我们在使用 Spring 的<Bean>元素时,配置最多的是<property>属性,因此我们下面继续分析源码,了解 Bean 的属性在解析时是如何设置的。

13、载入<property>元素
BeanDefinitionParserDelegate 在解析<Bean>调用 parsePropertyElements()方法解析<Bean>元素中的<property>属性子元素,解析源码如下:
 

 

通过对上述源码的分析,我们可以了解在 Spring 配置文件中,<Bean>元素中<property>元素的相关配置是如何处理的:
1、ref 被封装为指向依赖对象一个引用。
2、value 配置都会封装成一个字符串类型的对象。
3、ref 和 value 都通过“解析的数据类型属性值.setSource(extractSource(ele));”方法将属性值/引用与所引用的属性关联起来。
在方法的最后对于<property>元素的子元素通过 parsePropertySubElement ()方法解析,我们继续分析该方法的源码,了解其解析过程。
14、载入<property>的子元素
在 BeanDefinitionParserDelegate 类中的 parsePropertySubElement()方法对<property>中的子元素解析,源码如下:
   
通过上述源码分析,我们明白了在 Spring 配置文件中,对<property>元素中配置的 array、list、set、map、prop 等各种集合子元素的都通过上述方法解析,生成对应的数据对象,比如 ManagedList、ManagedArray、ManagedSet 等,这些 Managed 类是 Spring 对象 BeanDefiniton 的数据封装,对集合数据类型的具体解析有各自的解析方法实现,解析方法的命名非常规范,一目了然,我们对<list>
集合元素的解析方法进行源码分析,了解其实现过程。
15、载入<list>的子元素
在 BeanDefinitionParserDelegate 类中的 parseListElement()方法就是具体实现解析<property>元素中的<list>集合子元素,源码如下:
 
经过对 Spring Bean 配置信息转换的 Document 对象中的元素层层解析,Spring IOC 现在已经将 XML形式定义的 Bean 配置信息转换为 Spring IOC 所识别的数据结构——BeanDefinition,它是 Bean 配置信息中配置的 POJO 对象在 Spring IOC 容器中的映射,我们可以通过 AbstractBeanDefinition 为入口,看到了 IOC 容器进行索引、查询和操作。通过 Spring IOC 容器对 Bean 配置资源的解析后,IOC 容器大致完成了管理 Bean 对象的准备工作,即初始化过程,但是最为重要的依赖注入还没有发生,现在在 IOC 容器中 BeanDefinition 存储的只是一些静态信息,接下来需要向容器注册 Bean 定义信息才能全部完成 IOC 容器的初始化过程。
16、分配注册策略
让我们继续跟踪程序的执行顺序,接下来我们来分析 DefaultBeanDefinitionDocumentReader 对Bean 定 义转 换的 Document 对 象解 析的 流程 中, 在其 parseDefaultElement() 方 法中 完成对
Document 对 象 的 解 析 后 得 到 封 装 BeanDefinition 的 BeanDefinitionHold 对象 , 然后调用BeanDefinitionReaderUtils 的 registerBeanDefinition() 方 法 向 IOC 容 器 注 册 解 析 的 Bean ,BeanDefinitionReaderUtils 的注册的源码如下:
当调用 BeanDefinitionReaderUtils 向 IOC 容器注册解析的 BeanDefinition 时,真正完成注册功能的是 DefaultListableBeanFactory。
17、向容器注册
DefaultListableBeanFactory 中 使 用 一 个 HashMap 的 集 合 对 象 存 放 IOC 容 器 中 注 册 解 析 的BeanDefinition,向 IOC 容器注册的主要源码如下:
 

 

 

 

至此,Bean 配置信息中配置的 Bean 被解析过后,已经注册到 IOC 容器中,被容器管理起来,真正完成了 IOC 容器初始化所做的全部工作。现在 IOC 容器中已经建立了整个 Bean 的配置信息,这些BeanDefinition 信息已经可以使用,并且可以被检索,IOC 容器的作用就是对这些注册的 Bean 定义信息进行处理和维护。这些的注册的 Bean 定义信息是 IOC 容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。 

猜你喜欢

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