构造函数注入是除属性注入之外的另一种常用的注入方式
构造函数注入的方法:
在类中,可以不用为属性设置setter方法,但是必须要生成该类带参数的构造方法。
在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到 <constructor-arg> 节点。
constructor-arg标签属性:
name属性:通过参数名找到参数列表中对应参数;
index属性:通过参数在参数列表中的索引找到参数列表中对应参数,index从0开始;
type属性:通过参数数据类型找到参数列表中对应参数;
value属性:设置参数列表参数对应的值,用于设定基本数据类型和String类型的数据;
ref属性:如果参数值为非基本数据类型,则可通过ref为参数注入值,其值为另一个bean标签id或name
属性的属性值;
构造器注入案例:
1、编写 com.gx.model.PersonConstructor 类:
public void testPropertySetter(){
//通过Spring容器获取“personSetter”对象
PersonSetter personSetter= (PersonSetter)
context.getBean("personSetter");
System.out.println(personSetter);
}
}
package com.gx.model;
import java.io.Serializable;
public class PersonConstructor implements Serializable {
private String name;
private int age;
private double height;
private Car car;
/*使用name值也会存在歧义的情况,可以配置type属性消除歧义*/
public PersonConstructor(int name, double height, Car car) {
this.name = name+"_i2s";
this.height = height;
this.car = car;
}
public PersonConstructor(String name, int age, double height, Car car) {
this.name = name;
this.age = age;
this.height = height;this.car = car;
}
public PersonConstructor(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public PersonConstructor(String name, double height, Car car) {
this.name = name;
this.height = height;
this.car = car;
}
@Override
public String toString() {
return "PersonSetter{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
", car=" + car +
'}';
}
}
2、在applicationContext.xml中配置:
<!--构造函数注入-->
<!--通过name属性指定参数名匹配入参-->
<bean id="personConstructorByName" class="com.gx.model.PersonConstructor">
<constructor-arg name="name" value="byName匹配入参"/>
<constructor-arg name="age">
<value>22</value>
</constructor-arg>
<constructor-arg name="height" value="1.77"/>
<constructor-arg name="car" ref="carN" />
</bean>
<!--按类型匹配入参-->
<!--String name, int age, Car car-->
<bean id="personConstructorByType" class="com.gx.model.PersonConstructor">
<constructor-arg type="java.lang.String" value="按类型匹配入参"/>
<constructor-arg type="int" value="23"/>
<constructor-arg type="com.gx.model.Car" ref="car"/>
</bean>
<!--按索引匹配入参-->
<!--String name, int age, double height, Car car-->
<bean id="personConstructorByIndex" class="com.gx.model.PersonConstructor">
<constructor-arg index="0" value="按索引匹配入参"/>
<constructor-arg index="1" value="24"/>
<constructor-arg index="2" value="1.74"/>
<constructor-arg index="3" ref="carN"/>
</bean>
<!--对于由于参数数目相同而类型不同所引起的潜在配置歧义问题,
Spring容器可以正确启动且不会给出报错信息,它将随机采用一个匹配的构造函数实例化Bean,
而被选择的构造函数可能并不是用户所希望的。因此,必须特别谨慎,以避免潜在的错误。-->
<!--只按索引匹配入参有时会匹配不准确,如,我想匹配String name, int age, Car car--><bean id="personConstructorByIndexErr" class="com.gx.model.PersonConstructor">
<constructor-arg index="0" value="按索引匹配入参"/>
<!--<constructor-arg index="1" value="24" type="int"/>-->
<constructor-arg index="1" value="24" />
<constructor-arg index="2" ref="carN"/>
</bean>
<!--使用name值也会存在歧义的情况 int name, double height, Car car;
可以通过指定 type属性来消除歧义-->
<bean id="personConstructorByNameErr" class="com.gx.model.PersonConstructor">
<constructor-arg name="name" value="12345" type="int"/>
<constructor-arg name="height" value="1.78"/>
<constructor-arg name="car" ref="car"/>
</bean>
3、编写测试方法:
/**
* 构造函数注入方式测试
*/
@Test
public void testConstructor(){
// 通过name属性指定参数名匹配入参
PersonConstructor personConstructorByName
=(PersonConstructor)context.getBean("personConstructorByName");
System.out.println(personConstructorByName);
// 按类型匹配入参
PersonConstructor personConstructorByType
=(PersonConstructor) context.getBean("personConstructorByType");
System.out.println(personConstructorByType);
// 按索引匹配入参
PersonConstructor personConstructorByIndex=
(PersonConstructor) context.getBean("personConstructorByIndex");
System.out.println(personConstructorByIndex);
// 只按索引匹配入参有时会匹配不准确,如,我想匹配String name, int age, Car car,
// 结果匹配到了String name, double height, Car car
// 可以通过指定type指定具体的类型
PersonConstructor personConstructorByIndexErr=
(PersonConstructor) context.getBean("personConstructorByIndexErr");
System.out.println(personConstructorByIndexErr);
//使用name值也会存在歧义的情况 int name, double height, Car car,可以配合type属性消
除配置
PersonConstructor personConstructorByNameErr=
(PersonConstructor) context.getBean("personConstructorByNameErr");
System.out.println(personConstructorByNameErr);
}
注意: 对于由于参数数目相同(或参数名相同)而类型不同所引起的潜在配置歧义问题,Spring容器可
以正确启动且不会给出报错信息,它将随机采用一个匹配的构造函数实例化Bean,而被选择的构造函数
可能并不是用户所希望的。因此,必须特别谨慎,以避免潜在的错误。