您的位置:首页 > 编程语言 > Java开发

spring源码附录(5)解析子元素constructor-arg

2017-04-23 14:21 267 查看

一、基本使用

public class Animal {

public String type;

public int age;

/**
* @param type
* @param age
*/
public Animal(String type, int age) {
super();
this.type = type;
this.age = age;
}

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


<?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.constructor.Animal">
<constructor-arg index="0" value="cat" type="String"></constructor-arg>
<constructor-arg value="100" ></constructor-arg>
</bean>
</beans>


public class Main {

public static String XML_PATH = "test\\constructor\\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解析

对于construction-arg 子元素的解析,Spring 是通过 BeanDefinitionParserDelegate. parseConstructorArgElements(Element beanEle, BeanDefinition bd); 方法来实现的

/**
* Parse constructor-arg sub-elements of the given bean element.
*/
public void parseConstructorArgElements(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, CONSTRUCTOR_ARG_ELEMENT)) {
// parseConstructorArgElement
parseConstructorArgElement((Element) node, bd);
}
}
}


追踪下去如下:

从上面的代码上看,对构造函数中属性的解析,经历了以下几个过程:

  1. 略过description 和 meta

  2. 提取 ref ,value 属性,并验证其合法性,

  3. ref 属性的处理,使用 RuntimeBeanReference 封装

  4. Value 属性的处理 , 使用TypedStringValue封装

  5. 子属性的处理 如

<constructor-arg>
  <map>
   <entry key = "key" value = "value"></entry>
 </map>
</constructor-arg>


而对于子元素,则交给 parsePropertySubElement 方法来实现对各种子元素进行分类处理

public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
}


/**
* Parse a value, ref or collection sub-element of a property or constructor-arg
* element.
*
* @param ele subelement of property element; we don't know which yet
* @param defaultValueType the default type (class name) for any {@code <value>}
*        tag that might be created
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd,
String defaultValueType) {
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
}
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
}
else if (nodeNameEquals(ele, REF_ELEMENT)) {
// A generic reference to any name of any bean.
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
// A reference to the id of another bean in the same XML file.
// 解析本地资源
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
if (!StringUtils.hasLength(refName)) {
// A reference to the id of another bean in a parent context.
// 解析父类资源
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean', 'local' or 'parent' is required for <ref> element",
ele);
return null;
}
}
}
if (!StringUtils.hasText(refName)) {
error("<ref> element contains empty target attribute", ele);
return null;
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(extractSource(ele));
return ref;
}
// 对idref 的处理
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
// 对value 的处理
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
// 对 null 的处理
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue
// object in order to preserve the source location.
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
// 对array 的处理
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
// 对list 的处理
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
// 对set 的处理
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
// 对map 的处理
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
// 对props 的处理
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息