关于具体的Spring BeanDefinition的解析,是在BeanDefinitionParserDelegate中完成的。这个类里包含了各种Spring Bean定义规则的处理,感兴趣的同学可以仔细研究。我们举一个例子来分析这个处理过程,比如我们最熟悉的对Bean元素的处理是怎样完成的,也就是我们在XML定义文件中出现的<bean></bean>这个最常见的元素信息是怎样被处理的。在这里,我们会看到那些熟悉的BeanDefinition定义的处理,比如id、name、aliase等属性元素。把这些元素的值从XML文件相应的元素的属性中读取出来以后,会被设置到生成的BeanDefinitionHolder中去。这些属性的解析还是比较简单的。对于其他元素配置的解析,比如各种Bean的属性配置,通过一个较为复杂的解析过程,这个过程是由parseBeanDefinitionElement来完成的。解析完成以后,会把解析结果放到BeanDefinition对象中并设置到BeanDefinitionHolder中去,如以下清单所示: 

 

  1. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {   
  2.         //这里取得在<bean>元素中定义的id、name和aliase属性的值   
  3.          String id = ele.getAttribute(ID_ATTRIBUTE);   
  4.          String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);   
  5.   
  6.          List<String> aliases = new ArrayList<String>();   
  7.         if (StringUtils.hasLength(nameAttr)) {   
  8.              String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);   
  9.              aliases.addAll(Arrays.asList(nameArr));   
  10.          }   
  11.   
  12.          String beanName = id;   
  13.         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {   
  14.              beanName = aliases.remove(0);   
  15.             if (logger.isDebugEnabled()) {   
  16.                  logger.debug("No XML 'id' specified - using '" + beanName +   
  17.                         "' as bean name and " + aliases + " as aliases");   
  18.              }   
  19.          }   
  20.   
  21.         if (containingBean == null) {   
  22.              checkNameUniqueness(beanName, aliases, ele);   
  23.          }   
  24.   
  25.         //这个方法会引发对bean元素的详细解析   
  26. AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);   
  27.         if (beanDefinition != null) {   
  28.             if (!StringUtils.hasText(beanName)) {   
  29.                 try {   
  30.                     if (containingBean != null) {   
  31.                          beanName = BeanDefinitionReaderUtils.generateBeanName(   
  32.                                  beanDefinition, this.readerContext.getRegistry(), true);   
  33.                      }   
  34.                     else {   
  35.                          beanName = this.readerContext.generateBeanName(beanDefinition);   
  36.                         // Register an alias for the plain bean class name, if still possible,   
  37.                         // if the generator returned the class name plus a suffix.   
  38.                         // This is expected for Spring 1.2/2.0 backwards compatibility.   
  39.                          String beanClassName = beanDefinition.getBeanClassName();   
  40.                         if (beanClassName != null &&   
  41.                                  beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&   
  42.                                  !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {   
  43.                              aliases.add(beanClassName);   
  44.                          }   
  45.                      }   
  46.                     if (logger.isDebugEnabled()) {   
  47.                          logger.debug("Neither XML 'id' nor 'name' specified - " +   
  48.                                 "using generated bean name [" + beanName + "]");   
  49.                      }   
  50.                  }   
  51.                 catch (Exception ex) {   
  52.                      error(ex.getMessage(), ele);   
  53.                     return null;   
  54.                  }   
  55.              }   
  56.              String[] aliasesArray = StringUtils.toStringArray(aliases);   
  57.             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);   
  58.          }   
  59.   
  60.         return null;   
  61.      }  


在具体生成BeanDefinition以后。我们举一个对property进行解析的例子来完成对整个BeanDefinition载入过程的分析,还是在类BeanDefinitionParserDelegate的代码中,它对BeanDefinition中的定义一层一层地进行解析,比如从属性元素集合到具体的每一个属性元素,然后才是对具体的属性值的处理。根据解析结果,对这些属性值的处理会封装成PropertyValue对象并设置到BeanDefinition对象中去,如以下代码清单所示。

  1. /**
  2. * 这里对指定bean元素的property子元素集合进行解析。
  3. */  
  4. public void parsePropertyElements(Element beanEle, BeanDefinition bd) {   
  5.     //遍历所有bean元素下定义的property元素   
  6.      NodeList nl = beanEle.getChildNodes();   
  7.     for (int i = 0; i < nl.getLength(); i++) {   
  8.          Node node = nl.item(i);   
  9.         if (node instanceof Element && DomUtils.nodeNameEquals(node, PROPERTY_ELEMENT)) {   
  10.             //在判断是property元素后对该property元素进行解析的过程   
  11.              parsePropertyElement((Element) node, bd);   
  12.          }   
  13.      }   
  14. }   
  15. public void parsePropertyElement(Element ele, BeanDefinition bd) {   
  16.     //这里取得property的名字   
  17.      String propertyName = ele.getAttribute(NAME_ATTRIBUTE);   
  18.     if (!StringUtils.hasLength(propertyName)) {   
  19.          error("Tag 'property' must have a 'name' attribute", ele);   
  20.         return;   
  21.      }   
  22.     this.parseState.push(new PropertyEntry(propertyName));   
  23.     try {   
  24.         //如果同一个bean中已经有同名的存在,则不进行解析,直接返回。也就是说,如果在同一个bean中有同名的property设置,那么起作用的只是第一个。   
  25.         if (bd.getPropertyValues().contains(propertyName)) {   
  26.              error("Multiple 'property' definitions for property '" + propertyName + "'", ele);   
  27.             return;   
  28.          }   
  29.         //这里是解析property值的地方,返回的对象对应对Bean定义的property属性设置的解析结果,这个解析结果会封装到PropertyValue对象中,然后设置到BeanDefinitionHolder中去。   
  30.          Object val = parsePropertyValue(ele, bd, propertyName);   
  31.          PropertyValue pv = new PropertyValue(propertyName, val);   
  32.          parseMetaElements(ele, pv);   
  33.          pv.setSource(extractSource(ele));   
  34.          bd.getPropertyValues().addPropertyValue(pv);   
  35.      }   
  36.     finally {   
  37.         this.parseState.pop();   
  38.      }   
  39. }   
  40. /**
  41. * 这里取得property元素的值,也许是一个list或其他。
  42. */  
  43. public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {   
  44.      String elementName = (propertyName != null) ?   
  45.                     "<property> element for property '" + propertyName + "'" :   
  46.                     "<constructor-arg> element";   
  47.   
  48.     // Should only have one child element: ref, value, list, etc.   
  49.      NodeList nl = ele.getChildNodes();   
  50.      Element subElement = null;   
  51.     for (int i = 0; i < nl.getLength(); i++) {   
  52.          Node node = nl.item(i);   
  53.         if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT) &&   
  54.                  !DomUtils.nodeNameEquals(node, META_ELEMENT)) {   
  55.             // Child element is what we're looking for.   
  56.             if (subElement != null) {   
  57.                  error(elementName + " must not contain more than one sub-element", ele);   
  58.              }   
  59.             else {   
  60.                  subElement = (Element) node;   
  61.              }   
  62.          }   
  63.      }   
  64.     //这里判断property的属性,是ref还是value,不允许同时是ref和value。   
  65.     boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);   
  66.     boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);   
  67.     if ((hasRefAttribute && hasValueAttribute) ||   
  68.              ((hasRefAttribute || hasValueAttribute) && subElement != null)) {   
  69.          error(elementName +   
  70.                 " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);   
  71.      }   
  72.     //如果是ref,创建一个ref的数据对象RuntimeBeanReference,这个对象封装了ref的信息。   
  73.     if (hasRefAttribute) {   
  74.          String refName = ele.getAttribute(REF_ATTRIBUTE);   
  75.         if (!StringUtils.hasText(refName)) {   
  76.              error(elementName + " contains empty 'ref' attribute", ele);   
  77.          }   
  78.          RuntimeBeanReference ref = new RuntimeBeanReference(refName);   
  79.          ref.setSource(extractSource(ele));   
  80.         return ref;   
  81.      } //如果是value,创建一个value的数据对象TypedStringValue ,这个对象封装了value的信息。   
  82.     else if (hasValueAttribute) {   
  83.          TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));   
  84.          valueHolder.setSource(extractSource(ele));   
  85.         return valueHolder;   
  86.      } //如果还有子元素,触发对子元素的解析   
  87.     else if (subElement != null) {   
  88.         return parsePropertySubElement(subElement, bd);   
  89.      }   
  90.     else {   
  91.         // Neither child element nor "ref" or "value" attribute found.   
  92.          error(elementName + " must specify a ref or value", ele);   
  93.         return null;   
  94.      }   
  95. }