前两篇文章中,我们已经了解了如何使用Spring 配置简单属性值(使用value 属性)和引用其他Bean 的属性(使用ref 属性)。但是value 和ref 仅在Bean 的属性值是单个值的情况下才有用。当Bean 的属性值是集合,Spring 该如何配置呢?

当配置集合类型的Bean属性时,Spring 提供了4 种类型的集合配置元素。

集合元素 用途
<list> 装配list类型的值,允许重复。
<set> 装配set类型的值,不允许重复。
<map> 装配map类型的值,名称和值可以使任意类型。
<props> 装配properties类型的值,名称和值必须都是String类型。

当装配类型为数组或者java.util.Collection 任意实现的属性时,<list>和<set> 元素非常有用。我们很快就会看到,其实属性实际定义的集合类型与选择<list> 或者<set> 元素没有任何关系。如果属性为任意的java.util.Collection类型时,这两个配置元素在使用时几乎可以完全互换。

<map> 和<props> 这两个元素分别对应java.util.Map 和java.util.Properties。当我们需要由键- 值对组成的集合时,这两种配置元素非常有用。关键区别在于,<props> 要求键和值都必须为String 类型,而<map> 允许键和值可以是任意类型。

1. 装配Set和List

为了展示在Spring 中装配集合,让我们使用如下书店的例子。

package com.sjf.bean;
/**
* book实体类
* @author Administrator
*
*/
public class Book {
private String name;
private String author;
private double price;
public void setName(String name) {
this.name = name;
}
 
public void setAuthor(String author) {
this.author = author;
}
 
public void setPrice(double price) {
this.price = price;
}
 
@Override
public String toString() {
return "name:" + name + " author:" + author + " price:" + price;
}
}
package com.sjf.bean;
 
import java.util.Collection;
/**
* Bookstore实体类
* @author Administrator
*
*/
public class Bookstore {
private String name;
private Collection<Book> books;
public void setName(String name) {
this.name = name;
}
public void setBooks(Collection<Book> books) {
this.books = books;
}
public void listAllBook(){
System.out.println("[" + name + "]共存储一下书籍:");
for(Book book : books){
System.out.println(book.toString());
}//for
}
}

在这里最重要的是通过setBooks() 方法注入书籍(book)的集合。

让我们使用<list> 配置元素,为Bookstore赋予所拥有的书籍集合:

<bean id = "china-pub" class = "com.sjf.bean.Bookstore">
<property name="name" value="china-pub"/>
<property name="books">
<list>
<ref bean="spring"/>
<ref bean="spark"/>
<ref bean="java"/>
</list>
</property>
</bean>
<bean id = "spring" class = "com.sjf.bean.Book">
<property name="name" value = "Spring实战"/>
<property name="author" value="Craig Walls"/>
<property name="price" value="59.00"/>
</bean>
<bean id = "spark" class = "com.sjf.bean.Book">
<property name="name" value = "Spark大数据处理技术"/>
<property name="author" value="夏俊鸾"/>
<property name="price" value="65.00"/>
</bean>
<bean id = "java" class = "com.sjf.bean.Book">
<property name="name" value = "写给大忙人看的Java SE 8"/>
<property name="author" value="Cay S. Horstmann"/>
<property name="price" value="59.00"/>
</bean>

<list> 元素包含一个或多个值。这里的<ref> 元素用来定义Spring 上下文中的其他Bean 引用。当然还可以使用其他的Spring 设值元素作为<list> 的成员,包括<value>、<bean> 和<null/>。实际上,<list> 可以包含另外一个<list> 作为其成员,形成多维列表。

运行结果:

[china-pub]共存储一下书籍:
name:Spring实战 author:Craig Walls price:59.0
name:Spark大数据处理技术 author:夏俊鸾 price:65.0
name:写给大忙人看的Java SE 8 author:Cay S. Horstmann price:59.0
如果Bean 的属性类型为数组类型或java.util.Collection 接口的任意实现(List等),都可以使用<list> 元素。换句话说,即使像下面那样配置books属性,<list> 元素也一样有效:
private List<Book> books;
或者
private Book[] books;
同样,也可以使用<set> 元素来装配集合类型或者数组类型的属性:
<bean id = "china-pub" class = "com.sjf.bean.Bookstore">
<property name="name" value="china-pub"/>
<property name="books">
<set>
<ref bean="spring"/>
<ref bean="spark"/>
<ref bean="java"/>
</set>
</property>
</bean>

无论<list> 还是<set> 都可以用来装配类型为java.util.Collection的任意实现或者数组的属性。不能因为属性为java.util.Set 类型,就表示用户必须使用<set> 元素来完成装配。使用<set> 元素配置java.util.List 类型的属性,虽然看起来有点怪怪的,但是这的确是可以的。如果真这样的做话,就需要确保List 中的每一个成员都必须是唯一的。

2. 装配Map

package com.sjf.bean;
 
import java.util.Map;
/**
* Bookstore实体类
* @author Administrator
*
*/
public class Bookstore {
private String name;
private Map<String,Book> books;
public void setName(String name) {
this.name = name;
}
public void setBooks(Map<String,Book> books) {
this.books = books;
}
public void listAllBook(){
System.out.println("[" + name + "]共存储一下书籍:");
for(String key : books.keySet()){
System.out.println(key + "->" + books.get(key).toString());
}//for
}
}
books属性为java.util.Map 类型,Map 元素的键为String 类型,值为Book类型。因为Map 的成员是由键-值对构成的,当装配该属性时,简单的<list> 或者<set> 配置元素都无法胜任。

下面我们使用map配置books属性:

<bean id = "china-pub" class = "com.sjf.bean.Bookstore">
<property name="name" value="china-pub"/>
<property name="books">
<map>
<entry key="spring" value-ref="spring in action"/>
<entry key="spark" value-ref="spark in action"/>
<entry key="java" value-ref="java for busy"/>
</map>
</property>
</bean>
<bean id = "spring in action" class = "com.sjf.bean.Book">
<property name="name" value = "Spring实战"/>
<property name="author" value="Craig Walls"/>
<property name="price" value="59.00"/>
</bean>
<bean id = "spark in action" class = "com.sjf.bean.Book">
<property name="name" value = "Spark大数据处理技术"/>
<property name="author" value="夏俊鸾"/>
<property name="price" value="65.00"/>
</bean>
<bean id = "java for busy" class = "com.sjf.bean.Book">
<property name="name" value = "写给大忙人看的Java SE 8"/>
<property name="author" value="Cay S. Horstmann"/>
<property name="price" value="59.00"/>
</bean>
<map> 元素声明了一个java.util.Map 类型的值。每个<entry> 元素定义Map 的一个成员。在前边的示例中,key 属性指定了entry 的键,而value-ref属性定义了entry 的值,并引用了Spring 上下文中的其他Bean。
运行结果:
[china-pub]共存储一下书籍:
spring->name:Spring实战 author:Craig Walls price:59.0
spark->name:Spark大数据处理技术 author:夏俊鸾 price:65.0
java->name:写给大忙人看的Java SE 8 author:Cay S. Horstmann price:59.0

尽管在我们的示例中,使用key 属性来指定String 类型的键,使用valueref属性来指定引用类型的值,但实际上,<entry> 元素共有四个属性,分别可以用来指定entry 的键和值:
属性 用途
Key 指定map中entry的键为String。
Key-ref 指定map中entry的键为Spring上下文中其他Bean的引用。
Value 指定map中entry的值为String。
Value-ref 指定map中entry的值为Spring上下文中其他Bean的引用。

程序地址:https://github.com/sjf0115/springdemo-map/tree/master/springdemo-injection

3. 装配properties集合

上面实例中books属性声明为Map 类型,我们用到了value-ref指定每一个entry 的值。这是因为每一个entry 最终都会成为Spring 上下文中的一个Bean。但是如果所配置Map 的每一个entry 的键和值都为String 类型时,我们可以考虑使用java.util.Properties 代替Map。Properties 类提供了和Map 大致相同的功能,但是它限定键和值必须为String 类型。

package com.sjf.bean;
 
import java.util.Properties;
 
/**
* Bookstore实体类
* @author Administrator
*
*/
public class Bookstore {
private String name;
private Properties books;
public void setName(String name) {
this.name = name;
}
public void setBooks(Properties books) {
this.books = books;
}
public void listAllBook(){
System.out.println("[" + name + "]共存储一下书籍:");
for(Object key : books.keySet()){
System.out.println(key + "->" + books.get(key).toString());
}//for
}
}
下面我们使用property配置books属性:
<bean id = "china-pub" class = "com.sjf.bean.Bookstore">
<property name="name" value="china-pub"/>
<property name="books">
<props>
<prop key="spring in action" >Spring实战</prop>
<prop key="spark in action" >Spark大数据处理技术</prop>
<prop key="java for busy" >写给大忙人看的Java SE 8</prop>
</props>
</property>
</bean>
<props> 元素构建了一个java.util.Properties 值, 这个Properties的每一个成员都由<prop> 元素定义。每一个<prop> 元素都有一个key 属性,其定义了Properties 每个成员的键,而每一个成员的值由<prop> 元素的内容所定义。<property> 元素用于把值或Bean 引用注入到Bean 的属性中;<props> 元素用于定义一个java.util.Properties 类型的集合值;<prop> 元素用于定义<props> 集合的一个成员。

参考:《Spring实战》

[Spring实战系列](9)装配集合相关推荐

  1. [Spring实战系列](11)SpEL使用表达式装配

    到目前为止,我们为Bean 的属性和构造器参数装配的所有东西都是在Spring 的XML 配置文件中静态定义的. <bean id = "yoona" class = &qu ...

  2. [Spring实战系列](12)Bean的自动装配

    Spring提供了4种各具特色的自动装配策略: 类型 说明 no 默认方式,Bean的引用必须通过XML文件中的</ref>元素或者ref属性手动设定. byName 把与Bean的属性具 ...

  3. [Spring实战系列](13)使用注解自动装配

    1. 简介 从Spring2.5开始,我们就可以使用注解的自动装配方式装配Spring Bean的属性.使用注解自动装配方式与在XML中使用autowire属性自动装配没有太大区别.那为啥还要研发出这 ...

  4. [Spring实战系列](8)Spring注入方式之setter注入

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50631178 通常,JavaBean 的属性 ...

  5. [Spring实战系列](18)注解切面

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50659876 使用注解来创建切面是Aspec ...

  6. [Spring实战系列](6)配置Spring IOC容器的Bean

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50619900 1. 简介 Spring提供了 ...

  7. [Spring实战系列](5)Spring应用上下文

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50618337 下面是Spring-Hello ...

  8. Spring实战01——自动化装配bean

    自动装配bean 的四种方式: 首先定义一个类,使用@Configuration 标注类成为配置类,然后有下面四种方式: 1.配置类使用@ComponentScan 注解扫描指定包下的类,默认是扫描同 ...

  9. [Spring实战系列](19)Servlet不同版本之间的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/51076823 1.   2.3版本 2.3版 ...

  10. Spring实战6-利用Spring和JDBC访问数据库

    主要内容 定义Spring的数据访问支持 配置数据库资源 使用Spring提供的JDBC模板 写在前面:经过上一篇文章的学习,我们掌握了如何写web应用的控制器层,不过由于只定义了SpitterRep ...

最新文章

  1. CxImage的编译及简单使用举例
  2. 我在兰亭这三年之自动化框架升级
  3. 创业者如何小步快跑,从0开始实现自己的产品?
  4. 动态规划/贪心总结(一)
  5. 【研发管理】结构化流程框架
  6. x390拆机 升级内存和硬盘_工作效率低下?双十二是时候升级硬盘与内存了
  7. Java多线程之CountDownLatch用法
  8. 如何获取 OSS AccessKeyId、AccessKeySecret
  9. 图解SQL的inner join、left join、right join、full outer join、union、union all的区别
  10. PropertyGrid控件 分类(Category)及属性(Property)排序
  11. Proteus8.版本以上中文教程
  12. php 监听端口数据客户端ip_PHP获取客户端和服务器端IP
  13. 小米mix2的Android9好久更新,官方确认 小米6/MIX2/Note 3升级Android 9
  14. 球面坐标系转换为笛卡尔坐标系
  15. Android仿微信语音聊天功能
  16. simulink仿真之比较产生阶梯波
  17. 使用Jsch执行Shell脚本
  18. 孟郎诗词网3.0版本问题总结
  19. 程序员的奋斗史(四十一)——大学断代史(五)——我的娱乐方式
  20. 2022-2028年全球与中国智能天线行业发展趋势及投资战略分析

热门文章

  1. 刘庆付统考计算机基础选择题答案
  2. 汇编程序:找出最小值
  3. 搭建RTSP流媒体服务器的三种方式
  4. 爬取国家统计局数据正式篇
  5. 从32位应用程序到64位应用程序
  6. ffmpeg系列之两种视频解码方式
  7. dt100g3什么意思_酷黑滑盖风 金士顿DT100G3优盘评测
  8. MySQL:数据库练习题-3
  9. Android相同包名不同签名的apk安装失败问题分析
  10. 游戏测试永乐大典——测试成就感