• 3.7 spring-property 子元素的使用与解析


    1.0 Property子元素的使用

      property 子元素是再常用不过的了, 在看Spring源码之前,我们先看看它的使用方法,

    1. 实例类如下:

     1 public class Animal {
     2 
     3     public String type;
     4 
     5     public Set<Integer> age;
     6 
     7     private Map<String, Integer> sell;
     8 
     9     public Animal() {
    10 
    11     }
    12 
    13     /**
    14      * @return the type
    15      */
    16     public String getType() {
    17         return type;
    18     }
    19 
    20     /**
    21      * @param type the type to set
    22      */
    23     public void setType(String type) {
    24         this.type = type;
    25     }
    26 
    27     /**
    28      * @return the age
    29      */
    30     public Set<Integer> getAge() {
    31         return age;
    32     }
    33 
    34     /**
    35      * @param age the age to set
    36      */
    37     public void setAge(Set<Integer> age) {
    38         this.age = age;
    39     }
    40 
    41     /**
    42      * @return the sell
    43      */
    44     public Map<String, Integer> getSell() {
    45         return sell;
    46     }
    47 
    48     /**
    49      * @param sell the sell to set
    50      */
    51     public void setSell(Map<String, Integer> sell) {
    52         this.sell = sell;
    53     }
    54 
    55     /*
    56      * (non-Javadoc)
    57      * 
    58      * @see java.lang.Object#toString()
    59      */
    60     @Override
    61     public String toString() {
    62         return "Animal [type=" + type + ", age=" + age + ", sell=" + sell + "]";
    63     }
    64 
    65 }

    xml如下,

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    
        <bean id="animal" class="test.property.Animal">
            <property name="type" value="cat"></property>
            <property name="age">
                <set>
                    <value>1</value>
                    <value>2</value>
                    <value>3</value>
                </set>
            </property>
            <property name="sell">
                <map>
                    <entry key="blue" value="111"></entry>
                    <entry key="red" value="22"></entry>
                </map>
            </property>
        </bean>
    </beans> 

    测试类如下:

     1 public class Main {
     2 
     3     public static String XML_PATH = "test\property\applicationContxt.xml";
     4 
     5     public static void main(String[] args) {
     6         try {
     7             Resource resource = new ClassPathResource(XML_PATH);
     8             XmlBeanFactory beanFactory = new XmlBeanFactory(resource);
     9             Animal bean = (Animal) beanFactory.getBean("animal");
    10             System.out.println(bean);
    11         }
    12         catch (Exception e) {
    13             e.printStackTrace();
    14         }
    15     }
    16 }

    控制台输出的结果为

    Animal [type=cat, age=[1, 2, 3], sell={blue=111, red=22}]

    2.0 Spring具体的解析过程为:

      2.1 

     1 /**
     2      * Parse property sub-elements of the given bean element.
     3      */
     4     public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
     5         NodeList nl = beanEle.getChildNodes();
     6         for (int i = 0; i < nl.getLength(); i++) {
     7             Node node = nl.item(i);
     8             if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
     9                 // 这里进去
    10                 parsePropertyElement((Element) node, bd);
    11             }
    12         }
    13     }

      2.2 

     1 /**
     2      * Parse a property element.
     3      */
     4     public void parsePropertyElement(Element ele, BeanDefinition bd) {
     5         // 获取配置文件中name 的值
     6         String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
     7         if (!StringUtils.hasLength(propertyName)) {
     8             error("Tag 'property' must have a 'name' attribute", ele);
     9             return;
    10         }
    11         this.parseState.push(new PropertyEntry(propertyName));
    12         try {
    13             // 不容许多次对同一属性配置
    14             if (bd.getPropertyValues().contains(propertyName)) {
    15                 error("Multiple 'property' definitions for property '" + propertyName
    16                         + "'", ele);
    17                 return;
    18             }
    19             Object val = parsePropertyValue(ele, bd, propertyName);
    20             PropertyValue pv = new PropertyValue(propertyName, val);
    21             parseMetaElements(ele, pv);
    22             pv.setSource(extractSource(ele));
    23             bd.getPropertyValues().addPropertyValue(pv);
    24         }
    25         finally {
    26             this.parseState.pop();
    27         }
    28     }

      2.3 然后又回到parsePropertyValue 方法了

     1 public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
     2         String elementName = (propertyName != null) ? "<property> element for property '"
     3                 + propertyName + "'" : "<constructor-arg> element";
     4 
     5         // Should only have one child element: ref, value, list, etc.
     6         // 应该只有一个子元素:REF,值,列表等。
     7         NodeList nl = ele.getChildNodes();
     8         Element subElement = null;
     9         for (int i = 0; i < nl.getLength(); i++) {
    10             Node node = nl.item(i);
    11             // 对应的description 或者meta不处理
    12             if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)
    13                     && !nodeNameEquals(node, META_ELEMENT)) {
    14                 // Child element is what we're looking for.
    15                 if (subElement != null) {
    16                     error(elementName + " must not contain more than one sub-element",
    17                             ele);
    18                 }
    19                 else {
    20                     subElement = (Element) node;
    21                 }
    22             }
    23         }
    24         // 解析 ref
    25         boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
    26         // 解析 value
    27         boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
    28         if ((hasRefAttribute && hasValueAttribute)
    29                 || ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
    30             /*
    31              * 1.不能同时有ref 又有 value 2.不能存在ref 或者 value 又有子元素
    32              */
    33             error(elementName
    34                     + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element",
    35                     ele);
    36         }
    37 
    38         if (hasRefAttribute) {
    39             String refName = ele.getAttribute(REF_ATTRIBUTE);
    40             if (!StringUtils.hasText(refName)) {
    41                 error(elementName + " contains empty 'ref' attribute", ele);
    42             }
    43             // ref 属性的处理 , 使用RuntimeBeanReference封装对应的ref名称
    44             RuntimeBeanReference ref = new RuntimeBeanReference(refName);
    45             ref.setSource(extractSource(ele));
    46             return ref;
    47         }
    48         else if (hasValueAttribute) {
    49             // Value 属性的处理 , 使用TypedStringValue封装对应的
    50             TypedStringValue valueHolder = new TypedStringValue(
    51                     ele.getAttribute(VALUE_ATTRIBUTE));
    52             valueHolder.setSource(extractSource(ele));
    53             return valueHolder;
    54         }
    55         else if (subElement != null) {
    56             // 解析子元素
    57             return parsePropertySubElement(subElement, bd);
    58         }
    59         else {
    60             // Neither child element nor "ref" or "value" attribute found.
    61             // 对于没有ref 也没有子元素的,Spring只好丢出异常
    62             error(elementName + " must specify a ref or value", ele);
    63             return null;
    64         }
    65     }

    这里之前构造函数的解析那里已经讲得很详细了,这里不多做解释,不同的是返回值使用PropertyValue 封装,并且记录在BeanDefinition 的 propertyValues属性当中.

  • 相关阅读:
    关于bool operator() 几种变种实现的整理
    C# 访问修饰符
    C# 运算符
    c# 集合、存储及排序、迭代
    【并查集】tree
    【最大流】【POJ1149】PIGS
    【拆边最小费用流】【Asia Harbin 2010/2011】【Transportation】
    【DP】【GG选题】
    【DP】【芝麻开门】
    【搜索】【2012 Dhaka Regional】E Poker End Games
  • 原文地址:https://www.cnblogs.com/mjorcen/p/3647847.html
Copyright © 2020-2023  润新知