依赖注入简介
上面官方文档的解释,以下大概描述一下:
依赖注入 (DI) 是一个过程,其中对象仅通过构造函数参数、工厂方法的参数或对象实例在构造或从工厂方法返回。 然后容器在创建 bean 时注入这些依赖项。 这个过程基本上是 bean 本身通过使用直接构造类或服务定位器模式来控制其依赖项的实例化或位置的逆过程(因此称为控制反转)
依赖注入的方式:
注:DI主要有两种注入方式,即基于构造器注入和基于Setter注入
构造器注入
基于构造器注入 DI通过调用带参数的构造器来实现,每个参数代表着一个依赖关系。此外,还可通过给 静态
工厂方法传参数来构造bean。接下来的介绍将认为给构造器传参数和给静态工厂方法传参数是类似的。
构造器参数解析
构造器参数通过参数类型进行匹配。如果构造器参数的类型定义没有潜在的歧义,那么bean被实例化的时候,bean定义中构造器参数的定义顺序就是这些参数的顺序并依次进行匹配。
举个例子:
在bean定义中指定的构造器参数会被用作ExampleBean
的构造器参数。
使用构造器的例子,Spring调用静态
工厂方法来返回对象的实例:
public class ExampleBean {
// a private constructor
private ExampleBean(...) {
...
}
// a static factory method; the arguments to this method can be
// considered the dependencies of the bean that is returned,
// regardless of how those arguments are actually used.
public static ExampleBean createInstance (
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
ExampleBean eb = new ExampleBean (...);
// some other operations...
return eb;
}
}
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
<constructor-arg ref="anotherExampleBean"/>
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
静态
工厂方法参数由<constructor-arg/>
元素提供,实际上这和使用构造器是一样的。工厂方法 返回的类的类型并不一定要与包含静态
工厂方法的类类型一致,虽然在这个例子中是一样的。 实例工厂方法(不是静态的)与此相同(除了使用factory-bean
属性代替class属性外),所以这里不作详细讨论。
Setter注入
在调用了无参的构造方法或者无参的静态
工厂方法实例化bean之后,容器通过回调bean的setter方法来完成setter注入。
这里结合bean的生命周期更加容易理解:
通过构造器(无参构造)创建bean的实例 --> 为bean的属性设置值和其他的bean的引用(本质调用set方法)--> 调用bean的初始化方法 --> 获取bean对象(可以使用bean对象 )-->容器关闭调用bean的销毁方法
Setter注入例子使用基于XML的配置元数据的方式。相应的Spring XML配置文件:
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested ref element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>
<!-- setter injection using the neater ref attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {
private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;
public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}
public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}
public void setIntegerProperty(int i) {
this.i = i;
}
}
构造器注入还是Setter注入?
混合使用构造器注入和setter注入, 强制性依赖关系 时使用构造器注入, 可选的依赖关系 时使用setter方法或者配置方法是比较好的经验法则。请注意@Required注解在setter方法上可以注入所需要的依赖。