一、注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。
根据注入方式的不同,常用的有两类:set 注入、构造注入。
1、set注入
spring调用类的set方法,可以在set方法中完成属性的赋值
A、简单类型
- 语法格式:
<bean id="xx" class="yy">
<property name="属性的名称" value="此属性的值"/>
</bean>
- 创建Student类,为其属性定义各自的set方法
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName:"+name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("setAge:"+age);
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 创建spring配置文件
<bean id="myStudent" class="com.hcz.ba01.Student">
<property name="name" value="李四"/><!--setName("李四")-->
<property name="age" value="23"/><!--setAge(23)-->
</bean>
注意:
1、一个< property >只能给一个属性赋值
2、如果这这里name属性名有对应的set方法,则一定会执行该属性
- 创建测试方法
@Test
public void test01(){
//1.指定spring的配置文件
String config = "/ba01/applicationContext.xml";
//2.创建表示spring容器的对象,ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象
Student student = (Student) context.getBean("myStudent");
System.out.println(student);
}
B、引用类型
当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系。ref的值必须为某 bean 的 id 值。
- 语法格式:
<bean id="xx" class="yy">
<property name="属性的名称" ref="外部bean的id(对象的名称)"/>
</bean>
- 创建Student类,为其属性定义各自的set方法
public class Student {
private String name;
private Integer age;
//声明一个引用类型
private School school;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName:"+name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("setAge:"+age);
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
- 创建spring配置文件
<bean id="myStudent" class="com.hcz.ba02.Student">
<property name="name" value="李四"/><!--setName("李四")-->
<property name="age" value="23"/><!--setAge(23)-->
<!--引用类型-->
<property name="school" ref="mySchool"/><!--setSchool(mySchool)-->
</bean>
<!--声明School对象-->
<bean id="mySchool" class="com.hcz.ba02.School">
<property name="name" value="xx大学"/>
<property name="address" value="广东省xx市"/>
</bean>
注意:
ref:这里ref的值为引用类型的bean的id值
- 创建测试方法
@Test
public void test01(){
//1.指定spring的配置文件
String config = "/ba02/applicationContext.xml";
//2.创建表示spring容器的对象,ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象
Student student = (Student) context.getBean("myStudent");
System.out.println(student);
}
C、复杂类型
(1)给数组赋值
private String[] hobbies;
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
<property name="hobbies">
<array>
<value>book</value>
<value>gril</value>
<value>movie</value>
</array>
</property>
输出结果为:
hobbies=[book, gril, movie]
(2)给list集合赋值
private List<Address> lists;
public void setLists(List<Address> lists) {
this.lists = lists;
}
<bean id="person5" class="bean.Person1">
<property name="lists">
<list>
<!--使用内部bean,无法从IOC容器获取对象的值-->
<bean id="address2" class="bean.Address">
<property name="province" value="广东省"></property>
<property name="city" value="xx市"></property>
<property name="town" value="xx区"></property>
</bean>
<!--使用外部bean-->
<ref bean="address"></ref>
</list>
</property>
</bean>
<bean id="address" class="bean.Address">
<property name="province" value="广东省"></property>
<property name="city" value="xx市"></property>
<property name="town" value="xx市"></property>
</bean>
输出结果为:
lists=[Address{province=‘广东省’, city=‘梅州市’, town=‘梅江区’}, Address{province=‘广东省’, city=‘广州市’, town=‘黄浦区’}]
(3)给set集合赋值
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
<!--给set属性赋值-->
<property name="sets">
<set>
<value>张三</value>
<value>张三</value>
<value>李四</value>
</set>
</property>
输出结果为:
sets=[张三, 李四]
(4)给map集合赋值
private Map<String,Object> maps;
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
<!--给map属性赋值-->
<property name="maps">
<map>
<entry key="a" value="aaa"></entry>
<entry key="address" value-ref="address"></entry>
<entry key="address2">
<bean class="bean.Address">
<property name="province" value="上海市"></property>
</bean>
</entry>
<entry>
<key>
<value>b</value>
</key>
<value>bbb</value>
</entry>
<entry key="list">
<list>
<value>1</value>
<value>2</value>
</list>
</entry>
</map>
</property>
输出结果为:
maps={a=aaa, address=Address{province=‘广东省’, city=‘广州市’, town=‘黄浦区’}, address2=Address{province=‘上海市’, city=‘null’, town=‘null’}, b=bbb, list=[1, 2]}
2、构造注入
构造注入是指:
spring调用类有参构造方法,在创建对象的同时,在构造方法中给属性赋值
- 语法格式:
<bean id="xx" class="yy">
<constructor-arg name="" value=""/>
</bean>
解析:
name : 表示构造方法的形参名。
index : 表示构造方法的参数位置,参数从左往右位置是0,1,2的顺序,可不需要该属性,但需要保证赋值顺序要与构造方法中的参数顺序一致。
value : 构造方法的形参是简单类型的使用value。
ref : 构造方法的形参是引用类型的使用ref。
- 创建Student类,定义有参构造方法
public Student(String name, Integer age, School school) {
System.out.println("Student有参构造方法");
this.name = name;
this.age = age;
this.school = school;
}
- 创建spring配置文件
<bean id="myStudent" class="com.hcz.ba03.Student">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="34"/>
<constructor-arg name="school" ref="mySchool"/>
</bean>
<!--声明School对象-->
<bean id="mySchool" class="com.hcz.ba03.School">
<property name="name" value="xx大学"/>
<property name="address" value="广东省xx市"/>
</bean>
- 创建测试方法
@Test
public void test01(){
//1.指定spring的配置文件
String config = "/ba03/applicationContext.xml";
//2.创建表示spring容器的对象,ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象
Student student = (Student) context.getBean("myStudent");
System.out.println(student);
}
注意:
1、当有多个相同参数的构造方法存在的时候,默认情况下是覆盖的过程,后面的构造方法会覆盖前面的构造方法
2、如果非要赋值给另外一个构造方法的话,可以使用type的参数进行指定,例如:
<constructor-arg value="25" type="java.lang.Integer"/>
3、引用类型属性自动注入
对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为< bean/ >标签
设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属性)。
根据自动注入判断标准的不同,可以分为两种:
- byName:根据名称自动注入
- byType: 根据类型自动注入
(1)byName(按名称)方式自动注入
当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用 byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。
简单来说就是:
java类中引用类型的属性名School school和spring容器中< bean >的 id 名称一样且数据类型是一致的
- 语法格式:
<bean id="xx" class="yy" autowire="byName">
简单类型属性赋值
</bean>
- 创建spring配置文件
<!--byName-->
<bean id="myStudent" class="com.hcz.ba04.Student" autowire="byName">
<property name="name" value="张三"/>
<property name="age" value="45"/>
</bean>
<!--声明School对象:这里的id值改为和Student中的School属性名一样-->
<bean id="school" class="com.hcz.ba04.School">
<property name="name" value="xx大学"/>
<property name="address" value="广东省xx市"/>
</bean>
(2)byType(按类型)方式自动注入
使用 byType 方式自动注入,要求:java类中引用类型的数据类型和spring配置文件中< bean >的 class 属性是同源关系的,这样的bean能够赋值给引用类型
这里同源关系就是一类的意思:
1、Java类中引用类型的数据类型和 bean 的 class 的值是一样的
2、Java类中引用类型的数据类型和 bean 的 class 的值是父子类关系的
3、Java类中引用类型的数据类型和 bean 的 class 的值是接口和实现类关系的
- 语法格式:
<bean id="xx" class="yy" autowire="byType">
简单类型属性赋值
</bean>
- 创建spring配置文件
<!--byType-->
<bean id="myStudent" class="com.hcz.ba05.Student" autowire="byType">
<property name="name" value="张三"/>
<property name="age" value="45"/>
</bean>
<!--声明School对象:同源关系的第一种-->
<!--<bean id="mySchool" class="com.hcz.ba05.School">-->
<!--<property name="name" value="xx大学"/>-->
<!--<property name="address" value="广东省xx市"/>-->
<!--</bean>-->
<!--声明School子类:同源关系的第二种-->
<bean id="primarySchool" class="com.hcz.ba05.PrimarySchool">
<property name="name" value="xx小学"/>
<property name="address" value="xx市"/>
</bean>
- 执行后的结果为:
Student{name='张三', age=45, school=School{name='xx小学', address='xx市'}}
二、为应用指定多个 Spring 配置文件
1、多个配置优势
1、每个文件的大小比一个文件要小很多,所以执行效率高
2、避免多人竞争带来的冲突,例如:多人开发一个学生管理系统项目时,张三负责学生考勤模块,李四负责学生成绩模块,那么他们模块都应对应一个配置文件,这样才不会冲突。
2、多文件的分配方式:
- 按功能模块,一个模块一个配置文件
- 按类的功能,数据库相关的配置一个文件配置文件, 做事务的功能一个配置文件, 做业务service功能的一个配置文件等
3、包含关系的配置文件
多个配置文件中有一个总文件,总配置文件将各其它子文件通过< import/ >引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可
- 创建功能模块spring配置文件
ba06/spring-school.xml
<bean id="mySchool" class="com.hcz.ba06.School">
<property name="name" value="xx大学"/>
<property name="address" value="广东省xx市"/>
</bean>
ba06/spring-student.xml
student模块所有的bean声明
<bean id="myStudent" class="com.hcz.ba06.Student" autowire="byType">
<property name="name" value="lisi"/>
<property name="age" value="45"/>
</bean>
- 创建spring主配置文件
- 语法格式:
<import resource="其它配置文件的路径"/>
- 关键字:
classpath : 表示类路径(class文件所在的目录),
在spring的配置文件中要指定其他文件的位置,需要使用classpath,告诉spring到哪里去加载读取文件
ba06/total.xml
<import resource="classpath:ba06/spring-*.xml"/>
注意:
在包含关系的配置文件中,可以使用通配符( * : 表示任意字符 ),
但是主配置文件名称不能包含在通配符的范围内
- 创建测试方法
@Test
public void test01(){
//1.指定spring的配置文件
String config = "/ba06/total.xml";
//2.创建表示spring容器的对象,ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象
Student student = (Student) context.getBean("myStudent");
System.out.println(student);
}