依赖注入是Spring IoC容器实现反转控制的方式,Spring的IoC容器以依赖注入的方式实现了Bean对象之间关联关系的维护。
Spring的IoC容器实现了两种方式的对象注入,一种是构造方法,一种是setter方法。
基于构造方法的依赖注入
基于构造方法的依赖注入是通过调用带参数的构造器来实现的,每个参数代表着一个此对象的依赖者。
ConstructInjectionBean.java
public class ConstructInjectionBean {
private AnotherBean anotherBean;
private YetAnotherBean yetAnotherBean;
private int i;
public ConstructInjectionBean(AnotherBean anotherBean,YetAnotherBean yetAnotherBean,int i){
this.anotherBean = anotherBean;
this.yetAnotherBean = yetAnotherBean;
this.i = i;
}
}
配置Bean
<bean id="anotherBean" class="com.hd.injection.AnotherBean" />
<bean id="yetAnotherBean" class="com.hd.injection.YetAnotherBean" />
<bean id="constructInjectionBean" class="com.hd.injection.ConstructInjectionBean">
<!-- 使用<ref>元素来指定被注入的参数 -->
<constructor-arg>
<ref bean="anotherBean"/>
</constructor-arg>
<!-- 使用ref属性来指定被注入的参数 -->
<constructor-arg ref="yetAnotherBean" />
<!-- 直接定义常量来作为被注入的参数 -->
<constructor-arg type="int" value="1" />
</bean>
以上配置文件类似于如下Java代码:
AnotherBean anotherBean = new AnotherBean();
YetAnotherBean yetAnotherBean = new YetAnotherBean();
ConstructInjectionBean constructInjectionBean = new ConstructInjectionBean(anotherBean, yetAnotherBean, 1);
在使用基于构造方法的依赖注入时,Bean类中构造方法的参数与XML配置文件中的配置元素应该是一一对应的。
基于setter方法的依赖注入
在使用基于setter方法的依赖注入时,需要首先通过调用无参构造器或无参静态工厂方法实例化Bean之后,再调用该Bean的setter方法,这样就可以实现基于setter的依赖注入了。
SetterInjectionBean.java
public class SetterInjectionBean {
private AnotherBean anotherBean;
private YetAnotherBean yetAnotherBean;
private int i;
public AnotherBean getAnotherBean() {
return anotherBean;
}
public void setAnotherBean(AnotherBean anotherBean) {
this.anotherBean = anotherBean;
}
public YetAnotherBean getYetAnotherBean() {
return yetAnotherBean;
}
public void setYetAnotherBean(YetAnotherBean yetAnotherBean) {
this.yetAnotherBean = yetAnotherBean;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
配置Bean
<bean id="anotherBean" class="com.hd.injection.AnotherBean" />
<bean id="yetAnotherBean" class="com.hd.injection.YetAnotherBean" />
<bean id="setterInjectionBean" class="com.hd.injection.SetterInjectionBean">
<!-- 通过<ref> 元素实现setter方式的依赖注入的配置 -->
<property name="anotherBean">
<ref bean="anotherBean"/>
</property>
<!-- 通过ref属性来实现setter方式的依赖注入的配置 -->
<property name="yetAnotherBean" ref="yetAnohterBean"></property>
<!-- 通过value属性来直接定义注入的值 -->
<property name="i" value="1"></property>
</bean>
以上配置文件类似如下Java代码:
AnotherBean anotherBean = new AnotherBean();
YetAnotherBean yetAnotherBean = new YetAnotherBean();
int i = 1;
SetterInjectionBean setterInjectionBean = new SetterInjectionBean();
setterInjectionBean.setAnotherBean(anotherBean);
setterInjectionBean.setYetAnotherBean(yetAnotherBean);
setterInjectionBean.setI(i);
使用setter方法来实现依赖注入的时候,Bean类中的setter方法与xml文件中配置的属性是一一对应的。
两种依赖注入方式的比较:
使用构造方法实现依赖注入时可以一次性完成对象的创建和依赖关系的设置,保证是在完全初始化的基础上将对象的实例返回给客户的。更重要的是,采用构造方法实现的依赖注入不能再进行重新注入。而使用setter方法实现的依赖注入在需要的时候还可以进行重新注入。
使用构造方法实现依赖注入还有一个缺点,就是在属性很多的情况下,构造方法会过于复杂和庞大。因此灵活性会比较差。因此在实际开发中,一般使用基于setter方法的依赖注入。