spring源码附录(6)解析子元素property

对于子元素constructor-arg的解析看这里:http://blog.csdn.net/disiwei1012/article/details/70500005

一、基本用法

public class Animal {

    public String type;

    public Set<Integer> age;

    private Map<String, Integer> sell;

    public Animal() {

    }

    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * @return the age
     */
    public Set<Integer> getAge() {
        return age;
    }

    /**
     * @param age the age to set
     */
    public void setAge(Set<Integer> age) {
        this.age = age;
    }

    /**
     * @return the sell
     */
    public Map<String, Integer> getSell() {
        return sell;
    }

    /**
     * @param sell the sell to set
     */
    public void setSell(Map<String, Integer> sell) {
        this.sell = sell;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Animal [type=" + type + ", age=" + age + ", sell=" + sell + "]";
    }

}
<?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>

测试:

public class Main {

    public static String XML_PATH = "test\\property\\applicationContxt.xml";

    public static void main(String[] args) {
        try {
            Resource resource = new ClassPathResource(XML_PATH);
            XmlBeanFactory beanFactory = new XmlBeanFactory(resource);
            Animal bean = (Animal) beanFactory.getBean("animal");
            System.out.println(bean);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二、spring解析

/**
     * Parse property sub-elements of the given bean element.
     */
    public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
                // 这里进去
                parsePropertyElement((Element) node, bd);
            }
        }
    }
/**
     * Parse a property element.
     */
    public void parsePropertyElement(Element ele, BeanDefinition bd) {
        // 获取配置文件中name 的值
        String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
        if (!StringUtils.hasLength(propertyName)) {
            error("Tag 'property' must have a 'name' attribute", ele);
            return;
        }
        this.parseState.push(new PropertyEntry(propertyName));
        try {
            // 不容许多次对同一属性配置
            if (bd.getPropertyValues().contains(propertyName)) {
                error("Multiple 'property' definitions for property '" + propertyName
                        + "'", ele);
                return;
            }
            Object val = parsePropertyValue(ele, bd, propertyName);
            PropertyValue pv = new PropertyValue(propertyName, val);
            parseMetaElements(ele, pv);
            pv.setSource(extractSource(ele));
            bd.getPropertyValues().addPropertyValue(pv);
        }
        finally {
            this.parseState.pop();
        }
    }
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
        String elementName = (propertyName != null) ? "<property> element for property '"
                + propertyName + "'" : "<constructor-arg> element";

        // Should only have one child element: ref, value, list, etc.
        // 应该只有一个子元素:REF,值,列表等。
        NodeList nl = ele.getChildNodes();
        Element subElement = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            // 对应的description 或者meta不处理
            if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)
                    && !nodeNameEquals(node, META_ELEMENT)) {
                // Child element is what we're looking for.
                if (subElement != null) {
                    error(elementName + " must not contain more than one sub-element",
                            ele);
                }
                else {
                    subElement = (Element) node;
                }
            }
        }
        // 解析 ref
        boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
        // 解析 value
        boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
        if ((hasRefAttribute && hasValueAttribute)
                || ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
            /*
             * 1.不能同时有ref 又有 value 2.不能存在ref 或者 value 又有子元素
             */
            error(elementName
                    + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element",
                    ele);
        }

        if (hasRefAttribute) {
            String refName = ele.getAttribute(REF_ATTRIBUTE);
            if (!StringUtils.hasText(refName)) {
                error(elementName + " contains empty 'ref' attribute", ele);
            }
            // ref 属性的处理 , 使用RuntimeBeanReference封装对应的ref名称
            RuntimeBeanReference ref = new RuntimeBeanReference(refName);
            ref.setSource(extractSource(ele));
            return ref;
        }
        else if (hasValueAttribute) {
            // Value 属性的处理 , 使用TypedStringValue封装对应的
            TypedStringValue valueHolder = new TypedStringValue(
                    ele.getAttribute(VALUE_ATTRIBUTE));
            valueHolder.setSource(extractSource(ele));
            return valueHolder;
        }
        else if (subElement != null) {
            // 解析子元素
            return parsePropertySubElement(subElement, bd);
        }
        else {
            // Neither child element nor "ref" or "value" attribute found.
            // 对于没有ref 也没有子元素的,Spring只好丢出异常
            error(elementName + " must specify a ref or value", ele);
            return null;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值