前面已经介绍过,通过setter方法为目标Bean注入依赖关系的方式被称为设置注入;另外还有一种注入方式,这种方式在构造实例时,已经为其完成了依赖关系的初始化。这种利用构造器来设值依赖关系的方式被称为构造注入。
修改Chinese.java代码:
package org.crazyit.app.service.impl;
import org.crazyit.app.service.*;
public class Chinese
implements Person
{
private Axe axe;
//默认的构造器
public Chinese()
{
}
//构造注入所需的带参数的构造器
public Chinese(Axe axe)
{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe()
{
//调用axe的chop()方法
//表明Person对象依赖于axe对象
System.out.println(axe.chop());
}
}
上面的Chinese类没有提供设置axe属性的setter方法,仅仅提供了一个带Axe属性的构造器,Spring将通过该构造器为Chinese注入所以来的Bean实例。
构造注入的配置文件也需要做简单的修改,为了使用构造注入,使用<constructor-arg...../>元素指定构造器的参数。
bean.xml如下:
<?xml version="1.0" encoding="GBK"?>
<!-- Spring配置文件的根元素,使用spring-beans-3.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 配置chinese实例,其实现类是Chinese -->
<bean id="chinese" class="org.crazyit.app.service.impl.Chinese">
<!-- 使用构造注入,为chinese实例注入steelAxe实例 -->
<constructor-arg ref="steelAxe"/>
</bean>
<!-- 配置stoneAxe实例,其实现类是StoneAxe -->
<bean id="stoneAxe" class="org.crazyit.app.service.impl.StoneAxe"/>
<!-- 配置steelAxe实例,其实现类是SteelAxe -->
<bean id="stelAxe" class="org.crazyit.app.service.impl.SteelAxe"/>
</beans>
上面的配置文件的粗体字体代码使用<constructor-arg.../>元素指定了一个构造器函数,该参数类型是Axe,这指定Spring调用Chinese类里带一个Axe参数的构造器来创建chinese实例,因为使用了有参数的构造器创建实例,所以当Bean实例被创建完成后,该Bean的依赖关系已经设置完成。
配置<constructor-arg.../>元素可指定一个index属性,用于指定该构造参数值将作为第几个构造参数,例如,index="0"表明该构造参数值将作为第一个构造参数。
执行效果与使用steelAxe设置注入时的执行效果完全一样。区别在于:创建Person实例中Axe属性的时机不同——设置注入的时候先通过无参数构造器创建一个Bean实例,然后调用对应的Setter方法注入依赖关系;而构造注入则直接调用有参数的构造器,当Bean实例创建完成后,已经完成了依赖关系的注入。