- 一、注入分类
- 二、set注入
- 1. 简单类型
- 2. 引用类型
- 三、构造注入
- 四、引用类型属性自动注入
- 1. byName 方式自动注入
- 2. byType 方式自动注入
- 五、指定多个 Spring 配置文件
- 六、总结
- 1. set注入
- 2. 构造注入
- 3. 自动注入
DI 是ioc(控制反转)的技术实现
ioc技术实现使用的DI(Dependency Injection) :依赖注入, 只需要在程序中提供要使用的对象名称就可以, 至于对象如何在容器中创建,赋值,查找都由容器内部实现。
spring是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制。
spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象
一、注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。
初始化是由容器自动完成的,称为注入
根据注入方式的不同,常用的有两类:set 注入、构造注入
二、set注入
set 注入也叫设值注入,是指通过 setter 方法传入被调用者的实例,这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用
1. 简单类型
项目的具体创建看上一篇就可以了,这里直接写重点
首先声明一个Studnet的类
package com.md.b1;
/**
* @author MD
* @create 2020-08-07 19:55
*/
public class Student {
private String name;
private int age;
public Student() {
System.out.println("我是Student类的无参构造方法");
}
public void setName(String name) {
System.out.println("setName:"+name);
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
然后写对应的配置文件
结构图
测试类
注意:此时由于这个文件不是直接在resources下面,而是在下面的b1包的下面,所以指定的路径得加上
@Test
public void test01(){
String config = "b1/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
// 从容器中获取Student的对象
Student student = (Student) ac.getBean("student");
System.out.println(student);
// 我是Student类的无参构造方法
// setName:张三
// Student{name='张三', age=20}
}
注意一:没有属性但有set方法
还可以在Student的类中加入这个方法,
public void setEmail(String eamil) {
System.out.println("setEmail:"+eamil);
}
对应的配置文件
此时在Student类中没有email属性,但是有setEmail方法,能顺利执行不?
能,只要有对应的set方法都是正确的,无论属性名是否存在
测试:
@Test
public void test01(){
// 注意:此时由于这个文件不是直接在resources下面,而是在下面的b1包的下面,所以指定的路径得加上
String config = "b1/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
// 从容器中获取Student的对象
Student student = (Student) ac.getBean("student");
System.out.println(student);
// 我是Student类的无参构造方法
// setName:张三
// setEmail:[email protected]
// Student{name='张三', age=20}
}
注意二:对于非自定义的类
在配置文件中
测试:
@Test
public void test02(){
String config = "b1/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Date mydate = (Date) ac.getBean("mydate");
System.out.println(mydate);
}
2. 引用类型
当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系
ref的值必须为某 bean 的 id 值
如下:
先创建一个School类
package com.md.b2;
/**
* @author MD
* @create 2020-08-07 20:40
*/
public class School {
private String name;
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
再创建一个Student类,在里面引用School的类的对象
package com.md.b2;
/**
* @author MD
* @create 2020-08-07 19:55
*/
public class Student {
private String name;
private int age;
// 声明一个引用数据类型
private School school;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
System.out.println("setSchool:"+school);
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
写对应的配置文件
测试:
@Test
public void test02(){
// 注意:此时由于这个文件不是直接在resources下面,而是在下面的b2包的下面,所以指定的路径得加上
String config = "b2/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("student");
System.out.println(student);
// setSchool:School{name='清华', address='北京'}
// Student{name='张三', age=40, school=School{name='清华', address='北京'}}
}
三、构造注入
构造注入是指,spring在调用类的有参构造方法,在创建对象的同时,在构造方法中进行属性的赋值
语法:使用
首先还在Student类中写有参构造器
public Student(String name, int age, School school) {
System.out.println("我是Student类的有参构造方法");
this.name = name;
this.age = age;
this.school = school;
}
然后在配置文件中
测试:
@Test
public void test01(){
// 注意:此时由于这个文件不是直接在resources下面,而是在下面的b3包的下面,所以指定的路径得加上
String config = "b3/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = (Student) ac.getBean("student");
System.out.println(student);
// 我是Student类的有参构造方法
// Student{name='张三', age=30, school=School{name='清华', address='北京'}}
}
四、引用类型属性自动注入
对于引用类型属性的注入,也可不在配置文件中显示的注入。可以通过为
根据自动注入判断标准的不同,可以分为两种:
- byName:根据名称自动注入
- byType: 根据类型自动注入
1. byName 方式自动注入
当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的
语法:
byName(按名称注入) : java类中引用类型的属性名和spring容器中(配置文件)的id名称一样,
且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。
语法:
简单类型属性赋值
例子:
public class School {
private String name;
private String address;
// 省略set
}
//---------------------------------
public class Student {
private String name;
private int age;
// 声明一个引用数据类型
private School school;
// 省略set
}
在配置文件中
如上:
java类中引用类型的属性名school 和 spring容器中(配置文件)
2. byType 方式自动注入
使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)
但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个了
语法:
byType(按类型注入) : java类中引用类型的数据类型和spring容器中(配置文件)的class属性
是同源关系的,这样的bean能够赋值给引用类型
同源就是一类的意思:
1.java类中引用类型的数据类型和bean的class的值是一样的。
2.java类中引用类型的数据类型和bean的class的值父子类关系的。
3.java类中引用类型的数据类型和bean的class的值接口和实现类关系的
语法:
简单类型属性赋值
注意:在byType中, 在xml配置文件中声明bean只能有一个符合条件的,
多余一个是错误的
还是上面的例子:
五、指定多个 Spring 配置文件
在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring 配置文件分解成多个配置文件,其中一个为主配置文件
total.xml
六、总结
1. set注入
spring调用类的set方法实现属性赋值
- 简单类型的set注入:
- 引用类型的set注入:
2. 构造注入
spring调用有参数的构造方法
的name属性,name表示构造方法的形参名 的index属性,表示构造方法形参的位置,从0开始
3. 自动注入
由spring根据某些规则,给引用类型完成赋值,有byName、byType
- byName:按名称注入,
java类中引用类型的属性名和spring容器中bean的id一样,数据类型一样
- byType:按类型注入,
java类中引用类型的数据类型和spring容器中bean的class是同源关系