注入方式
具体有3种注入方式:通过构造方法的 a.参数名称注入 b.参数下标注入 c.默认参数顺序注入
参数名称注入
School实体类
packagecom.example.pojo03;
publicclassSchool{
privateString name;
privateString address;
@Override
publicString toString() {
return"School{"+
"name='"+ name +'\''+
", address='"+ address +'\''+
'}';
}
publicSchool(String name, String address) {
this.name = name;
this.address = address;
System.out.println("School有参构造方法执行,实例对象被创建....");
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- bean工厂 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 通过构造方法的参数名称,注册School实例对象 -->
<bean id="school" class="com.example.pojo03.School">
<constructor-arg name="name" value="nefu"/>
<constructor-arg name="address" value="哈尔滨"/>
</bean>
</beans>
测试
packagecom.example.test;
importorg.junit.Test;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
public classTestConstructor{
//测试:通过构造方法的参数名称注入
@Test
publicvoidtestConstructorArgs(){
//创建Spring容器
ApplicationContext ac =newClassPathXmlApplicationContext("source03/applicationContext.xml");
//取出School对象并打印输出
System.out.printf("School实例对象: "+ ac.getBean("school"));
}
}
测试结果
School有参构造方法执行,实例对象被创建....School实例对象: School{name='nefu', address='哈尔滨'}Process finished withexitcode0
参数下标注入
实体类:新增Student实体类,持有School实例对象的引用
packagecom.example.pojo03;
publicclassStudent{
privateString name;
privateint age;
privateSchool school;
@Override
publicString toString() {
return"Student{"+
"name='"+ name +'\''+
", age="+ age +
", school="+ school +
'}';
}
publicStudent(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
System.out.println("Student有参构造方法执行,实例对象被创建....");
}
}
applicationContext.xml:新增bean标签,注册Student实例对象
<!-- 通过构造方法的参数下标,注册Student实例对象 -->
<bean id="student" class="com.example.pojo03.Student">
<constructor-arg index="0" value="荷包蛋"/>
<constructor-arg index="1" value="20"/>
<constructor-arg index="2" ref="school"/>
</bean>
测试:新增测试方法
//测试:通过构造方法的参数下标注入
@Test
publicvoidtestConstructorIndex(){
//创建Spring容器
ApplicationContext ac =newClassPathXmlApplicationContext("source03/applicationContext.xml");
//取出Student对象并打印输出
System.out.printf("Student实例对象: "+ ac.getBean("student"));
}
测试结果
School有参构造方法执行,实例对象被创建....
Student有参构造方法执行,实例对象被创建....
Student实例对象: Student{name='荷包蛋', age=20, school=School{name='nefu', address='哈尔滨'}}
Process finished withexitcode0
默认参数顺序注入
applicationContext.xml:新增bean标签,通过构造方法默认参数顺序注册Student实例对象,注意将之前对Student实例对象的注册先注释掉
<!-- 通过构造方法的参数下标,注册Student实例对象 -->
<bean id="student" class="com.example.pojo03.Student">
<constructor-arg index="0" value="荷包蛋"/>
<constructor-arg index="1" value="20"/>
<constructor-arg index="2" ref="school"/>
</bean>
测试:新增测试方法
//测试:通过构造方法默认参数顺序注入
@Test
public void testConstructorDefaultOrder(){
//创建Spring容器
ApplicationContext ac =newClassPathXmlApplicationContext("source03/applicationContext.xml");
//取出Student对象并打印输出
System.out.printf("Student实例对象: "+ ac.getBean("student02"));
}
测试结果
School有参构造方法执行,实例对象被创建....
Student有参构造方法执行,实例对象被创建....
Student实例对象: Student{name='荷包蛋', age=20, school=School{name='nefu', address='哈尔滨'}}
Process finished withexitcode0
注意
前两种注入方式,由于一种依靠参数名和待注入值绑定,一种依靠参数下标和待注入值绑定,做到了注入值与待注入目标一一对应
所以注入标签顺序随意,调换 < constructor-arg />标签的前后顺序,仍可正确注入数据
<!-- 通过构造方法的参数下标,注册Student实例对象 -->
<bean id="student" class="com.example.pojo03.Student">
<constructor-arg index="0" value="荷包蛋"/>
<constructor-arg index="2" ref="school"/>
<constructor-arg index="1" value="20"/>
</bean>
但是依靠参数默认顺序注入时,要严格参考实体类中待注入属性的顺序和类型,保证与标签中的待注入值的类型相同,不然会类型解析错误,数据注入失败
<!-- 通过构造方法默认参数顺序,注册Student实例对象 -->
<bean id="student02" class="com.example.pojo03.Student">
<constructor-arg value="荷包蛋"/>
<constructor-arg ref="school"/>
<constructor-arg value="20"/>
</bean>
容器启动时,School实例对象成功创建并注入数据,但创建Student对象时,待注入数据类型和目标属性类型不对应,类型解析错误,创建失败

image