1.0 Property子元素的使用

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

1. 实例类如下:

 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如下,

<?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();
}
}
}

控制台输出的结果为

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

2.0 Spring具体的解析过程为:

  2.1

 /**
* 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);
}
}
}

  2.2

 /**
* 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();
}
}

  2.3 然后又回到parsePropertyValue 方法了

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

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

3.7 spring-property 子元素的使用与解析的更多相关文章

  1. 3.6 spring-construction-arg 子元素的使用与解析

    对于构造函数子元素是非常常用的. 相信大家也一定不陌生, 举个小例子: public class Animal { public String type; public int age; /** * ...

  2. 3.5 spring-replaced-method 子元素的使用与解析

    1.replaced-method 子元素 方法替换: 可以在运行时用新的方法替换现有的方法,与之前的 look-up不同的是replace-method 不但可以动态地替换返回的实体bean,而且可 ...

  3. 3.4 spring- lookup-method 子元素的使用与解析

    1. lookup-method的应用: 1.1 子元素lookup-method 似乎不是很常用,但是在某些时候他的确是非常有用的属性,通常我们称它为 "获取器注入" . 引用 ...

  4. 3.8 spring-qualifier 子元素的使用与解析

      对于 qualifier 子元素,我们接触的更多的是注解形式,在使用Spring 自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个.当找不到一个匹配的 Bean 时, S ...

  5. 3.3 spring-meta子元素的使用与解析

    1. meta元素的使用 在解析元数据的分析之前,我们先回顾一下 meta属性的使用: <bean id="car" class="test.CarFactoryB ...

  6. Spring 系列教程之默认标签的解析

    Spring 系列教程之默认标签的解析 之前提到过 Spring 中的标签包括默认标签和自定义标签两种,而两种标签的用法以及解析方式存在着很大的不同,本章节重点带领读者详细分析默认标签的解析过程. 默 ...

  7. Spring框架之beans源码完全解析

    导读:Spring可以说是Java企业开发里最重要的技术.而Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Oriented Programmin ...

  8. spring bean属性及子元素使用总结

    spring bean属性及子元素使用总结 2016-08-03 00:00 97人阅读 评论(0) 收藏 举报  分类: Spring&SpringMVC(17)  版权声明:本文为博主原创 ...

  9. Spring 配置文件中 元素 属性 说明

    <beans /> 元素 该元素是根元素.<bean /> 元素的属性 default-init // 是否开启懒加载.默认为 false default-dependency ...

随机推荐

  1. Servlet & JSP - HttpSession

    关于 Session 的内容,参考 HTTP - Session 机制 创建和检索 HttpSession 通过 HttpServletRequest.getSession 方法可以获取 HttpSe ...

  2. 和阿文一起学H5--设计稿尺寸全攻略

  3. 和阿文一起学H5-文字云制作

    ---恢复内容开始--- 实用工具!优秀的标签云免费生成工具 来源:http://www.uisdc.com/online-word-cloud-generators 标签云或文字云是关键词的视觉化描 ...

  4. C# WCF学习笔记(二)终结点地址与WCF寻址(Endpoint Address and WCF Addressing) WCF中的传输协议

    URI的全称是 Uniform Rosource Identifire(统一资源标识),它唯一标识一个确定的网绐资源,同时也表示资源所处的位置及访问的方式(资源访问所用的网络协议). 对于Endpoi ...

  5. sql查询统计,根据新闻类别ID统计,没有数据显示0

    有两张表,新闻信息表MessageInfo和新闻类别表MessageType.表结构如下: 然后需要实现下面这种查询结果: 这个是我面试时遇到的,上面的新闻类型是乱写的.当时没有做出来,然后回来又研究 ...

  6. [译]使用Babel和Browserify创建你的ES6项目

    原文地址:Setting up an ES6 Project Using Babel and Browserify JavaScript的发展日新月异,ES6很快就要接管JS了.很多著名的框架像Ang ...

  7. PHP中的变量

    PHP中的变量 程序是由代码与数据两部分组成,数据存储在变量,变量的本质是内存中的一个存储空间.变量对应的空间有一个名子,叫变量名,变量名用于对数据进行读写. 变量的定义 在php变量名之前必须使用' ...

  8. C/C++编译过程理解【转】

    转载自:http://www.cppblog.com/woaidongmao/archive/2008/11/07/66254.aspx 今天,通过自己的努力终于对C/C++的编译过程有了个粗略的了解 ...

  9. Windows Phone 8.1 列表控件(2):分组数据

    说到 List 控件,Windows Phone 8.1 上推荐使用的是 ListView 和 GridView. 而这两个控件实在太多东西可讲了,于是分成三篇来讲: (1)基本 (2)分组数据 (3 ...

  10. L006-oldboy-mysql-dba-lesson06

    L006-oldboy-mysql-dba-lesson06 数据清理状态,先标记update table state=1,再删除. myisam没外键,硬件,并发,锁表力度,不支持事务,OLAP. ...