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; } }
相关文章推荐
- Spring解析子元素constructor-arg
- spring源码附录(8)import、beans标签的解析
- spring的xml的property和constructor-arg的解析
- spring源码解析之bean的子元素
- Spring源码解析(2)之默认标签的解析(二)
- 做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1
- spring ioc 源码解析(二)
- spring boot 源码解析10-SpringApplication#run第10-13步
- spring源码分析(2)——Bean 定义的解析与Bean的注册
- Spring源码解析之自定义标签的解析
- Spring源码解析(七)——实例创建(中)
- spring源码解析
- 关于Spring 的Classpath: 和 Classpath*: 源码解析
- Spring-web源码解析之HttpRequestHandler
- Spring 源码解析错误来源
- [置顶] Spring-Session实现Session共享实现原理以及源码解析
- spring 源码解析
- Spring源码分析--Ioc容器定位解析资源文件并注册BeanDefinition
- spring boot 源码解析53-AbstractNamedMvcEndpoint
- spring boot 源码解析15-spring mvc零配置