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

【Spring学习笔记】之【3.1 DI的使用 二】

2013-08-28 21:33 585 查看

3.1.6 注入集合、数组和字典

Spring不仅能注入简单类型数据,还能注入集合(Collection、无序集合Set、有序集合List)类型、数组(Array)类型、字典(Map)类型数据、Properties类型数据,接下来就让我们一个个看看如何注入这些数据类型的数据。一、注入集合类型:包括Collection类型、Set类型、List类型数据:(1)List类型:需要使用<list>标签来配置注入,其具体配置如下:

让我们来写个测试来练习一下吧: 准备测试类:
java代码:查看复制到剪贴板打印package cn.javass.spring.chapter3.bean;
import java.util.List;
publicclass ListTestBean {
private List<String> values;
public List<String> getValues() {
return values;
}
publicvoid setValues(List<String> values) {
this.values = values;
}
}

进行Bean定义,在配置文件(resources/chapter3/listInject.xml)中配置list注入:
java代码:查看复制到剪贴板打印<bean id="listBean"class="cn.javass.spring.chapter3.bean.ListTestBean">
<property name="values">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
</bean>

测试代码:
java代码:查看复制到剪贴板打印@Test
publicvoid testListInject() {
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("chapter3/listInject.xml");
ListTestBean listBean = beanFactory.getBean("listBean", ListTestBean.class);
System.out.println(listBean.getValues().size());
Assert.assertEquals(3, listBean.getValues().size());
}

(2)Set类型:需要使用<set>标签来配置注入,其配置参数及含义和<lsit>标签完全一样,在此就不阐述了: 准备测试类:
java代码:查看复制到剪贴板打印package cn.javass.spring.chapter3.bean;
import java.util.Collection;
publicclass CollectionTestBean {
private Collection<String> values;
publicvoid setValues(Collection<String> values) {
this.values = values;
}
public Collection<String> getValues() {
return values;
}
}

进行Bean定义,在配置文件(resources/chapter3/listInject.xml)中配置list注入:
java代码:查看复制到剪贴板打印<bean id="setBean"class="cn.javass.spring.chapter3.bean.SetTestBean">
<property name="values">
<set>
<value>1</value>
<value>2</value>
<value>3</value>
</set>
</property>
</bean>
具体测试代码就不写了,和listBean测试代码完全一样。
(2)Collection类型:因为Collection类型是Set和List类型的基类型,所以使用<set>或<list>标签都可以进行注入,配置方式完全和以上配置方式一样,只是将测试类属性改成“Collection”类型,如果配置有问题,可参考cn.javass.spring.chapter3.DependencyInjectTest测试类中的testCollectionInject测试方法中的代码。二、注入数组类型:需要使用<array>标签来配置注入,其中标签属性“value-type”和“merge”和<list>标签含义完全一样,具体配置如下:

如果练习时遇到配置问题,可以参考“cn.javass.spring.chapter3.DependencyInjectTest”测试类中的testArrayInject测试方法中的代码。
三、注入字典(Map)类型:字典类型是包含键值对数据的数据结构,需要使用<map>标签来配置注入,其属性“key-type”和“value-type”分别指定“键”和“值”的数据类型,其含义和<list>标签的“value-type”含义一样,在此就不罗嗦了,并使用<key>子标签来指定键数据,<value>子标签来指定键对应的值数据,具体配置如下:

如果练习时遇到配置问题,可以参考“cn.javass.spring.chapter3.DependencyInjectTest”测试类中的testMapInject测试方法中的代码。四、Properties注入:Spring能注入java.util.Properties类型数据,需要使用<props>标签来配置注入,键和值类型必须是String,不能变,子标签<prop key=”键”>值</prop>来指定键值对,具体配置如下:



如果练习时遇到配置问题,可以参考cn.javass.spring.chapter3.DependencyInjectTest测试类中的testPropertiesInject测试方法中的代码。 到此我们已经把简单类型及集合类型介绍完了,大家可能会问怎么没见注入“Bean之间关系”的例子呢?接下来就让我们来讲解配置Bean之间依赖关系,也就是注入依赖Bean。

3.1.7 引用其它Bean

上边章节已经介绍了注入常量、集合等基本数据类型和集合数据类型,本小节将介绍注入依赖Bean及注入内部Bean。 引用其他Bean的步骤与注入常量的步骤一样,可以通过构造器注入及setter注入引用其他Bean,只是引用其他Bean的注入配置稍微变化了一下:可以将“<constructor-arg index="0" value="Hello World!"/>”和“<property name="message" value="Hello World!"/>”中的value属性替换成bean属性,其中bean属性指定配置文件中的其他Bean的id或别名。另一种是把<value>标签替换为<.ref bean=”beanName”>,bean属性也是指定配置文件中的其他Bean的id或别名。那让我们看一下具体配置吧:
一、构造器注入方式:(1)通过” <constructor-arg>”标签的ref属性来引用其他Bean,这是最简化的配置:

(2)通过” <constructor-arg>”标签的子<ref>标签来引用其他Bean,使用bean属性来指定引用的Bean:

二、setter注入方式:(1)通过” <property>”标签的ref属性来引用其他Bean,这是最简化的配置:

(2)通过” <property>”标签的子<ref>标签来引用其他Bean,使用bean属性来指定引用的Bean:

三、接下来让我们用个具体例子来讲解一下具体使用吧:(1)首先让我们定义测试引用Bean的类,在此我们可以使用原有的HelloApi实现,然后再定义一个装饰器来引用其他Bean,具体装饰类如下:
java代码:查看复制到剪贴板打印package cn.javass.spring.chapter3.bean;
import cn.javass.spring.chapter2.helloworld.HelloApi;
publicclass HelloApiDecorator implements HelloApi {
private HelloApi helloApi;
//空参构造器
public HelloApiDecorator() {
}
//有参构造器
public HelloApiDecorator(HelloApi helloApi) {
this.helloApi = helloApi;
}
publicvoid setHelloApi(HelloApi helloApi) {
this.helloApi = helloApi;
}
@Override
publicvoid sayHello() {
System.out.println("==========装饰一下===========");
helloApi.sayHello();
System.out.println("==========装饰一下===========");
}
}

(2)定义好了测试引用Bean接下来该在配置文件(resources/chapter3/beanInject.xml)进行配置Bean定义了,在此将演示通过构造器及setter方法方式注入依赖Bean:
java代码:查看复制到剪贴板打印<!-- 定义依赖Bean -->
<bean id="helloApi"class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
<!-- 通过构造器注入 -->
<bean id="bean1"class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<constructor-arg index="0" ref="helloApi"/>
</bean>
<!-- 通过构造器注入 -->
<bean id="bean2"class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<property name="helloApi"><ref bean=" helloApi"/></property>
</bean>

(3)测试一下吧,测试代码(cn.javass.spring.chapter3.DependencyInjectTest)片段如下:
java代码:查看复制到剪贴板打印@Test
publicvoid testBeanInject() {
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("chapter3/beanInject.xml");
//通过构造器方式注入
HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);
bean1.sayHello();
//通过setter方式注入
HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);
bean2.sayHello();
}

四、其他引用方式:除了最基本配置方式以外,Spring还提供了另外两种更高级的配置方式,<ref local=””/>和<ref parent=””/>(1)<ref local=””/>配置方式:用于引用通过<bean id=”beanName”>方式中通过id属性指定的Bean,它能利用XML解析器的验证功能在读取配置文件时来验证引用的Bean是否存在。因此如果在当前配置文件中有相互引用的Bean可以采用<ref local>方式从而如果配置错误能在开发调试时就发现错误。如果引用一个在当前配置文件中不存在的Bean将抛出如下异常:org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line21 inXML document from class path resource [chapter3/beanInject2.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'helloApi'.<ref local>具体配置方式如下:

(2)<ref parent=””/>配置方式:用于引用父容器中的Bean,不会引用当前容器中的Bean,当然父容器中的Bean和当前容器的Bean是可以重名的,获取顺序是直接到父容器找。具体配置方式如下:

接下来让我们用个例子演示一下<ref local>和<ref parent>的配置过程:首先还是准备测试类,在此我们就使用以前写好的HelloApiDecorator和HelloImpl4类;其次进行Bean定义,其中当前容器bean1引用本地的”helloApi”,而”bean2”将引用父容器的”helloApi”,配置如下:
java代码:查看复制到剪贴板打印<!-- sources/chapter3/parentBeanInject.xml表示父容器配置-->
<!--注意此处可能子容器也定义一个该Bean-->
<bean id="helloApi"class="cn.javass.spring.chapter3.HelloImpl4">
<property name="index" value="1"/>
<property name="message" value="Hello Parent!"/>
</bean>

java代码:查看复制到剪贴板打印<!-- sources/chapter3/localBeanInject.xml表示当前容器配置-->
<!-- 注意父容器中也定义了id 为 helloApi的Bean -->
<bean id="helloApi"class="cn.javass.spring.chapter3.HelloImpl4">
<property name="index" value="1"/>
<property name="message" value="Hello Local!"/>
</bean>
<!-- 通过local注入 -->
<bean id="bean1"class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<constructor-arg index="0"><ref local="helloApi"/></constructor-arg>
</bean>
<!-- 通过parent注入 -->
<bean id="bean2"class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<property name="helloApi"><ref parent="helloApi"/></property>
</bean>

(3)写测试类测试一下吧,具体代码片段如下:
java代码:查看复制到剪贴板打印@Test
publicvoid testLocalAndparentBeanInject() {
//初始化父容器
ApplicationContext parentBeanContext =
new ClassPathXmlApplicationContext("chapter3/parentBeanInject.xml");
//初始化当前容器
ApplicationContext beanContext = new ClassPathXmlApplicationContext(
new String[] {"chapter3/localBeanInject.xml"}, parentBeanContext);
HelloApi bean1 = beanContext.getBean("bean1", HelloApi.class);
bean1.sayHello();//该Bean引用local bean
HelloApi bean2 = beanContext.getBean("bean2", HelloApi.class);
bean2.sayHello();//该Bean引用parent bean
}

“bean1”将输出“Hello Local!”表示引用当前容器的Bean,”bean2”将输出“Hello Paren!”,表示引用父容器的Bean,如配置有问题请参考cn.javass.spring.chapter3.DependencyInjectTest中的testLocalAndparentBeanInject测试方法。

本文出自 “CEO之路” 博客,请务必保留此出处http://zhaohaibo.blog.51cto.com/7808533/1284594
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: