spring Ioc 依赖注入的三种方式:构造函数注入、setter方法注入和接口注入

来源:互联网 发布:python编程第4版中文 编辑:程序博客网 时间:2024/05/22 01:40
BeanFactory作为一个IoC Service Provider,为了能够明确管理各个业务对象以及业务对象之间的依赖绑定关系,同样需要某种途径来记录和管理这些信息。通常会有三种方式来管理这些信息:直接编码方式、外部配置文件方式、注解方式。

最常用的是外部配置文件方式,Spring的IoC容器支持两种配置文件格式:Properties文件格式和XML文件格式。下面主要讲解XML格式的配置文件。

applicationContext.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="……"
      class="……">
    ……………………
</bean>
</beans>

<beans>是XML配置文件中最顶层的元素,它下面可以包含0或者1个<description>和多个<bean>以及<import>或者<alias>、<bean>

1. 构造方法注入的XML之道
按照Spring的IoC容器配置格式,要通过构造方法注入方式,为当前业务对象注入其所依赖的对象,需要使用<constructor-arg>。正常情况下,如以下代码所示:
<bean id="djNewsProvider" class="..FXNewsProvider">
<constructor-arg>
<ref bean="djNewsListener"/>
</constructor-arg>
<constructor-arg>
<ref bean="djNewsPersister"/>
</constructor-arg>
</bean>
对于<ref>元素,稍后会进行详细说明。这里你只需要知道,通过这个元素来指明容器将为djNewsProvider这个<bean>注入通过<ref>所引用的Bean实例。这种方式可能看起来或者编写起来不是很简洁,最新版本的Spring也支持配置简写形式,如以下代码所示:
<bean id="djNewsProvider" class="..FXNewsProvider">
<constructor-arg ref="djNewsListener"/>
<constructor-arg ref="djNewsPersister"/>
</bean>
简洁多了不是嘛?其实,无非就是表达方式不同而已,实际达到的效果是一样的。

有些时候,容器在加载XML配置的时候,因为某些原因,无法明确配置项与对象的构造方法参数列表的一一对应关系,就需要请<constructor-arg>的type或者index属性出马。比如,对象存在多个构造方法,当参数列表数目相同而类型不同的时候,容器无法区分应该使用哪个构造方法来实例化对象,或者构造方法可能同时传入最少两个类型相同的对象。
    (1) type属性
 public class MockBusinessObject {
private String dependency1;
private String dependency2;
public MockBusinessObject(String dependency)
{
this.dependency1 = dependency;
}
public MockBusinessObject(int dependency)
{
this.dependency2 = dependency;
}
…………
}
这个类有两个构造方法,但参数类型不同的。
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg>
<value>111111</value>
</constructor-arg>
</bean> 
如果从BeanFactory取得该对象并调用toString()查看的话,我们会发现Spring调用的是第一个构造方法,因为输出是如下内容:
.MockBusinessObject@f73c1[dependency1=111111,dependency2=0]

但是,如果我们想调用的却是第二个传入int类型参数的构造方法,又该如何呢?可以使用type属性,通过指定构造方法的参数类型来解决这一问题,配置内容如下代码所示:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg type="int">
<value>111111</value>
</constructor-arg>
</bean>
(2)index 属性
当某个业务对象的构造方法同时传入了多个类型相同的参数时,Spring又该如何将这些配置中的信息与实际对象的参数一一对应呢?好在,如果配置项信息和对象参数可以按照顺序初步对应的话,Spring还是可以正常工作的。
public class MockBusinessObject {
private String dependency1;
private String dependency2;
public MockBusinessObject(String dependency1,String dependency2)
{
this.dependency1 = dependency1;
this.dependency2 = dependency2;
}
}
并且,配置内容如以下代码所示:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg value="11111"/>
<constructor-arg value="22222"/>
</bean>
那么,我们可以得到如下对象:
MockBusinessObject@1ef8cf3[dependency1=11111,dependency2=22222]
但是,如果要让“11111”作为对象的第二个参数,而将“22222”作为第一个参数来构造对象,又该如何呢?好!可以颠倒配置项,如以下代码所示:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg value="22222"/>
<constructor-arg value="11111"/>
</bean>
不过,还有一种方式,那就是像如下代码所示的那样,使用index属性:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg index="1" value="11111"/>
<constructor-arg index="0" value="22222"/>
</bean>
2. setter方法注入的XML之道
与构造方法注入可以使用<constructor-arg>注入配置相对应,Spring为setter方法注入提供了<property>元素。
<property>有一个name属性(attribute),用来指定该<property>将会注入的对象所对应的实例变量名称。之后通过value或者ref属性或者内嵌的其他元素来指定具体的依赖对象引用或者值,如以下代码所示:
<bean id="djNewsProvider" class="..FXNewsProvider">
<property name="newsListener">
<ref bean="djNewsListener"/>
</property>
<property name="newPersistener">
<ref bean="djNewsPersister"/>
</property>
</bean>
当然,如果只是使用<property>进行依赖注入的话,请确保你的对象提供了默认的构造方法,也就是一个参数都没有的那个。
以上配置形式还可以简化为如下形式:
<bean id="djNewsProvider" class="..FXNewsProvider">
<property name="newsListener" ref="djNewsListener"/>
<property name="newPersistener" ref="djNewsPersister"/>
</bean>

使用<property>的setter方法注入和使用<constructor-arg>的构造方法注入并不是水火不容的。实际上,如果需要,可以同时使用这两个元素:
<bean id="mockBO" class="..MockBusinessObject">
<constructor-arg value="11111"/>
<p
原创粉丝点击