Spring框架学习[IoC容器解析Bean](八)

2014-11-24 03:05:58 · 作者: · 浏览: 2
回null
  • else { error(Unknown property sub-element: [ + ele.getNodeName() + ], ele);
  • return null; }
  • }

    通过上述源码分析,我们明白了在Spring配置文件中,对 元素中配置的Array、List、Set、Map、Prop等各种集合子元素的都通过上述方法解析,生成对应的数据对象,比如ManagedList、ManagedArray、ManagedSet等,这些Managed类是Spring对象BeanDefiniton的数据封装,对集合数据类型的具体解析有各自的解析方法实现,解析方法的命名非常规范,一目了然,我们对 集合元素的解析方法进行源码分析,了解其实现过程。

    7.解析 子元素:

    在BeanDefinitionParserDelegate类中的parseListElement方法就是具体实现解析 元素中的 集合子元素,源码如下:

    [java]
    1. //解析 集合子元素 public List parseListElement(Element collectionEle, BeanDefinition bd) {
    2. //获取 元素中的value-type属性,即获取集合元素的数据类型 String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
    3. //获取 集合元素中的所有子节点 NodeList nl = collectionEle.getChildNodes();
    4. //Spring中将List封装为ManagedList ManagedListtarget = new ManagedList(nl.getLength());
    5. target.setSource(extractSource(collectionEle)); //设置集合目标数据类型
    6. target.setElementTypeName(defaultElementType); target.setMergeEnabled(parseMergeAttribute(collectionEle));
    7. //具体的 元素解析 parseCollectionElements(nl, target, bd, defaultElementType);
    8. return target; }
    9. //具体解析 集合元素, 都使用该方法解析 protected void parseCollectionElements(
    10. NodeList elementNodes, Collectiontarget, BeanDefinition bd, String defaultElementType) { //遍历集合所有节点
    11. for (int i = 0; i < elementNodes.getLength(); i++) { Node node = elementNodes.item(i);
    12. //节点不是description节点 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
    13. //将解析的元素加入集合中,递归调用下一个子元素 target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
    14. } }
    15. }

      经过对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容器的初始化过程。

      8.解析过后的BeanDefinition在IoC容器中的注册:

      让我们继续跟踪程序的执行顺序,接下来会到我们第3步中分析DefaultBeanDefinitionDocumentReader对Bean定义转换的Document对象解析的流程中,在其parseDefaultElement方法中完成对Document对象的解析后得到封装BeanDefinition的BeanDefinitionHold对象,然后调用BeanDefinitionReaderUtils的registerBeanDefinition方法向IoC容器注册解析的Bean,BeanDefinitionReaderUtils的注册的源码如下:

      [java]
      1. //将解析的BeanDefinitionHold注册到容器中 public static void registerBeanDefinition(
      2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
      3. //获取解析的BeanDefinition的名称 String beanName = definitionHolder.getBeanName();
      4. //向IoC容器注册BeanDefinition registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
      5. //如果解析的BeanDefinition有别名,向容器为其注册别名 String[] aliases = definitionHolder.getAliases();
      6. if (aliases != null) { for (String aliase : aliases) {
      7. registry.registerAlias(beanName, aliase); }
      8. } }

        当调用BeanDefinitionReaderUtils向IoC容器注册解析的BeanDefinition时,真正完成注册功能的是DefaultListableBeanFactory。

        9.DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition:

        DefaultListableBeanFactory中使用一个HashMap的集合对象存放IoC容器中注册解析的BeanDefinition,向IoC容器注册的主要源码如下:

        [java]
        1. //存储注册的俄BeanDefinition private final Map beanDefinitionMap = new ConcurrentHashMap ();
        2. //向IoC容器注册解析的BeanDefiniton public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        3. throws BeanDefinitionSt