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

2014-11-24 03:05:58 · 作者: · 浏览: 8
,通过对上述源码的分析,就会明白我们在Spring配置文件中 元素的中配置的属性就是通过该方法解析和设置到Bean中去的。

注意:在解析 元素过程中没有创建和实例化Bean对象,只是创建了Bean对象的定义类BeanDefinition,将 元素中的配置信息设置到BeanDefinition中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的Bean对象。

上面方法中一些对一些配置如元信息(meta)、qualifier等的解析,我们在Spring中配置时使用的也不多,我们在使用Spring的 元素时,配置最多的是 属性,因此我们下面继续分析源码,了解Bean的属性在解析时是如何设置的。

5.BeanDefinitionParserDelegate解析 元素:

BeanDefinitionParserDelegate在解析 调用parsePropertyElements方法解析 元素中的 属性子元素,解析源码如下:

[java]
  1. //解析 元素中的 子元素 public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
  2. //获取 元素中所有的子元素 NodeList nl = beanEle.getChildNodes();
  3. for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i);
  4. //如果子元素是 子元素,则调用解析 子元素方法解析 if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
  5. parsePropertyElement((Element) node, bd); }
  6. } }
  7. //解析 元素 public void parsePropertyElement(Element ele, BeanDefinition bd) {
  8. //获取 元素的名字 String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
  9. if (!StringUtils.hasLength(propertyName)) { error(Tag 'property' must have a 'name' attribute, ele);
  10. return; }
  11. this.parseState.push(new PropertyEntry(propertyName)); try {
  12. //如果一个Bean中已经有同名的property存在,则不进行解析,直接返回。 //即如果在同一个Bean中配置同名的property,则只有第一个起作用
  13. if (bd.getPropertyValues().contains(propertyName)) { error(Multiple 'property' definitions for property ' + propertyName + ', ele);
  14. return; }
  15. //解析获取property的值 Object val = parsePropertyValue(ele, bd, propertyName);
  16. //根据property的名字和值创建property实例 PropertyValue pv = new PropertyValue(propertyName, val);
  17. //解析 元素中的属性 parseMetaElements(ele, pv);
  18. pv.setSource(extractSource(ele)); bd.getPropertyValues().addPropertyValue(pv);
  19. } finally {
  20. this.parseState.pop(); }
  21. } //解析获取property值
  22. public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { String elementName = (propertyName != null)
  23. element for property ' + propertyName + ' : element;
  24. //获取 的所有子元素,只能是其中一种类型:ref,value,list等 NodeList nl = ele.getChildNodes();
  25. Element subElement = null; for (int i = 0; i < nl.getLength(); i++) {
  26. Node node = nl.item(i); //子元素不是description和meta属性
  27. if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) {
  28. if (subElement != null) { error(elementName + must not contain more than one sub-element, ele);
  29. } else {//当前 元素包含有子元素
  30. subElement = (Element) node; }
  31. } }
  32. //判断property的属性值是ref还是value,不允许既是ref又是value boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
  33. boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); if ((hasRefAttribute && hasValueAttribute) ||
  34. ((hasRefAttribute || hasValueAttribute) && subElement != null)) { error(elementName +
  35. is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element, ele); }
  36. //如果属性是ref,创建一个ref的数据对象RuntimeBeanReference,这个对象 //封装了ref信息
  37. if (hasRefAttribute) { String refName = ele.getAttribute(REF_ATTRIBUTE);
  38. if (!StringUtils.hasText(refName)) { error(elementName + contains empty 'ref' attribute, ele);
  39. } //一个指向运行时所依赖对象的引用
  40. RuntimeBeanReference ref = new RuntimeBeanReference(refName); //设置这个ref的数据对象是被当前的property对象所引用
  41. ref.setSource(extractSource(ele)); return ref;
  42. } //如果属性是value,创建一个value的数据对象TypedStringValue,这个对象
  43. //封装了value信息 else if (hasValueAttribute) {
  44. //一个持有String类型值的对象 TypedStringValue valueHolder = new TypedStringValue(ele.getAttrib