3.7 spring

Wesley13
• 阅读 426

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属性当中.

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这