上一章,我们从零开始配置了一个简单的spring项目,并提到了spring的一个核心:IOC,即控制反转。这一章,我们会讲一下spring的另一个核心:DI(依赖注入)的配置方式。
一、DI概述
DI,依赖注入,Dependency Injection 的首字母缩写,是指在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件(简单的说,可以将另外一个bean对象动态的注入到另外一个bean中)。
例如,Spring创建了Service、Dao对象,在配置中将Dao传入Servcie,那么Service对象就包含了Dao对象的引用。
二、DI注入的方式
1、setter注入
利用属性的setter方法注入属性。属性类型是简单类型(基本类型和String)和bean类型时的写法又略有不同。
(1)简单类型属性
<!-- 简单类型属性注入使用value -->
<bean id="user" class="bean.User">
<property name="name" value="Jack"></property>
<property name="age" value="18"></property>
</bean>
(2)bean类型属性
<bean id="address" class="bean.Address"></bean>
<!-- bean类型属性注入使用ref -->
<bean id="user" class="bean.User">
<property name="address" ref="address"></property>
</bean>
这种在bean标签内使用property标签的方法显得有的繁琐和臃肿,因此,为简化XML文件的配置,Spring2.5版本开始引入了一个新的p命名空间。简单的说,它的作用是为了简化setter方法属性依赖注入配置的,它不是真正的命名空间。
在使用p命名空间前,我们需要在配置文件beans标签内加上p命名空间的定义:
xmlns:p=“http://www.springframework.org/schema/p”
然后按照下面的格式,使用p命名空间简化setter方式依赖注入。
<!-- p命名空间依赖注入 -->
<bean id="user" class="bean.User" p:name = "Tom" p:age="20" p:address-ref="address"></bean>
2、构造器注入
<bean id="address" class="bean.Address"></bean>
<!-- 构造器注入,index为构造器参数索引,从0开始 -->
<bean id="user" class="bean.User">
<constructor-arg index="0" name="name" value="Tom"></constructor-arg>
<constructor-arg index="1" name="age" value="12"></constructor-arg>
<constructor-arg index="2" name="address" ref="address"></constructor-arg>
</bean>
3、集合注入
集合注入本质还是setter注入,只是通过list 、set、map及props标签来定义和设置与java类型中对应的list、set、map以及properties。
对于属性为集合的bean来说,属性注入时可以使用list、set、map、props等标签来注入。
public class CollectionEntity {
//集合内为简单类型
private List<String> list;
private Set<String> set;
private Map<String,String> map;
//集合内为bean类型
private List<Address> list2;
private Set<Address> set2;
private Map<String,Address> map2;
private Properties properties;
//get\set方法省略
....
}
(1)简单类型
<bean id="collectionEntity" class="net.baiqu.entity.CollectionEntity">
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<property name="set">
<set>
<value>1</value>
<value>1</value>
<value>3</value>
</set>
</property>
<property name="map">
<map>
<entry key="1" value="2" />
<entry key="3">
<value>4</value>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="name">Jack</prop>
<prop key="age">12</prop>
</props>
</property>
</bean>
也可以使用util来定义list、set、map和properties。
<util:list id="list">
<value>1</value>
<value>2</value>
<value>3</value>
</util:list>
<util:set id="set">
<value>1</value>
<value>1</value>
<value>3</value>
</util:set>
<util:map id="map">
<entry key="1" value="2" />
<entry key="3">
<value>4</value>
</entry>
</util:map>
<util:properties id="properties">
<prop key="name">Jack</prop>
<prop key="age">12</prop>
</util:properties>
<bean id="collectionEntity" class="net.baiqu.entity.CollectionEntity">
<property name="list">
<ref bean="list"></ref>
</property>
<property name="set">
<ref bean="set"></ref>
</property>
<property name="map">
<ref bean="map"></ref>
</property>
<property name="properties">
<ref bean="properties"></ref>
</property>
</bean>
(2) bean类型
<bean id="address1" class="net.baiqu.entity.Address" />
<bean id="address2" class="net.baiqu.entity.Address" />
<bean id="collectionEntity" class="net.baiqu.entity.CollectionEntity">
<property name="list2">
<list>
<ref bean="address1"></ref>
<ref bean="address2"></ref>
</list>
</property>
<property name="set2">
<set>
<ref bean="address1"></ref>
<ref bean="address2"></ref>
</set>
</property>
<property name="map2">
<map>
<entry key="home" value-ref="address1"></entry>
<entry key="school" value-ref="address2"></entry>
</map>
</property>
</bean>
同样的,可以使用util进行注入。
<util:list id="list2">
<ref bean="address1" />
<ref bean="address2" />
</util:list>
<util:set id="set2">
<ref bean="address1" />
<ref bean="address2" />
</util:set>
<util:map id="map2">
<entry key="home" value-ref="address1"></entry>
<entry key="school" value-ref="address2"></entry>
</util:map>
<bean id="collectionEntity" class="net.baiqu.entity.CollectionEntity">
<property name="list2">
<ref bean="list2"></ref>
</property>
<property name="set2">
<ref bean="set2"></ref>
</property>
<property name="map">
<ref bean="map"></ref>
</property>
<property name="properties">
<ref bean="properties"></ref>
</property>
</bean>
4、SpEL表达式注入
SpEL(Spring Expression Language)是一种表达式语言,它是spring3.x版本的新特性。
它的作用是:支持在运行时操作和查询对象,其语法类似统一的EL语言,但是SpEL提供了额外的功能,功能更强大。
当properties属性注入的值是从properties文件中读取时,那么可以采用下面的两种方式,其中第二种就是SpEL表达式注入。
<!-- 方法1 -->
<util:properties id="config" location="classpath:config.properties"/>
<bean id="colBean" class="com.niit.bean.CollectionBean">
<property name="properties" ref="config"/>
</bean>
<!-- 方法2 -->
<util:properties id="config" location="classpath:config.properties"/>
<bean id="colBean" class="com.niit.bean.CollectionBean">
<property name="properties">
<props>
<prop key="name">#{config.userName}</prop>
<prop key="pwd">#{config.pwd}</prop>
</props>
</property>
</bean>