基于构造器的依赖注入

基于构造器的依赖注入(DI)是通过调用带有代表依赖参数的构造器来实现的。调用带有指定给Bean构造器的参数的静态工厂方法也是相似的,并且有关把给构造器和静态工厂方法传递参数的讨论也是类似的。下面的示例展示了使用构造器来注入依赖的类。注意这个 类没有特殊的依赖,它只是一个不依赖于容器特定接口、基类或注解的POJO对象。


public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic that actually uses the injected MovieFinder is omitted...
}


构造器参数的解析

构造器参数的解析时通过相关参数的类型来匹配的。如果Bean定义的构造器中的参数对象不存在,那么Bean定义中的构造器的参数的顺序就是在示例化Bean的时候提供给对应构造器的参数的顺序,例如:


package x.y;
public class Foo {
public Foo(Bar bar, Baz baz) {
// ...
}
}


如果构造器参数bar和baz不存在,并且假设Bar类和Baz类没有相关的继承,这样下面的配置就可以很好的工作,并且不需要再<constructor-arg/>元素中明确的指定构造器参数的索引或/和类型。


<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>


在引用其他的Bean的时候,类型是已知的,并且匹配能够发生(像上述的示例那样)。当使用简单的类型时,如<value>true</value>,Spring不能够判断值的类型,在没有帮助的情况下不能匹配到正确的类型,因此要像下面的示例那样使用type属性来指定值的类型。


package examples;
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private int years;
// The Answer to Life, the Universe, and Everything
private String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}


 


<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>


使用index属性来明确的指定构造器参数的索引,这样就可以解决带有多个相同简单类型参数的所引入的歧义性。注意:索引是从0开始的。例如:


<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>


还可以使用构造器的参数名称来消除歧义,例如:


<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>


请记住,要让代码即插即用,就必须在可调式模式下来编译,这样Spring才能够查找来自构造器的参数名称。如果不想在可调式模式来编译,可以使用JDK的@ConstructorProperties注解来明确构造器参数的名称,例如:


package examples;
public class ExampleBean {
// Fields omitted
@ConstructorProperties({"years", "ultimateAnswer"})
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}