文章目录
一、IOC是什么?
控制反转IOC(Inversion of Control)是一个概念,是一种思想。由Spring容器进行对象的创建和依赖注入。程序员在使用时直接取出使用即可。
正转:由程序员进行对象的创建和依赖注入称为正转。程序员说了算。
Student stu = new Student(); =====>程序员创建对象
stu.setName("小明"); =====>程序员进行赋值
stu.setAge(22);
反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走,交给Spring容器,称为反转。
<bean id="stu" class="com.bjpowernode.pojo.Student"> ==>Spring容器创建对象
<property name="name" value="小明"> ==>Spring容器依赖注入值
<property name="age" value="22">
</bean>
测试:
学生实体类:
public class Student {
private String name;
private int age;
public Student() {
System.out.println("创建学生对象");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
由程序员创建对象:
@Test
public void testStudent1(){
Student stu = new Student();
}
运行结果:
applicationContext.xml
<bean id="stu" class="com.bjpowernode.pojo.Student"></bean>
由Spring容器创建对象:
@Test
public void testStudent2(){
//由Spring容器进行对象创建
//如果想从Spring容器中取出对象,则要先创建容器对象并启动才可以取对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//取对象
Student stu = (Student) ac.getBean("stu");
}
运行结果同上。
二、基于XML的IOC
2.1 创建对象
<bean id="stu" class="com.bjpowernode.pojo.Student"></bean>
2.2 给创建的对象赋值
2.2.1 使用setter注入
注入分为简单类型注入和引用类型注入
2.2.1.1 简单类型注入使用value属性
同上。
2.1.1.2 引用类型注入使用ref属性
注意:使用setter注入必须提供无参的构造方法,必须提供setXXX()方法
引用类型注入代码(给学生添加一个学校属性,表明这个学生是哪个学校的):
School实体类:
public class School {
private String name;
private String address;
//为了给成员变量注入值,必须提供无参构造方法和setXXX()方法
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
public School(){
System.out.println("学校的无参构造方法被调用。。。");
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
applicationContext.xml文件,创建学校对象:
<bean id="school" class="com.bjpowernode.pojo.School">
<property name="name" value="西西大学"></property>
<property name="address" value="西西区"></property>
</bean>
Student实体类(加入学校属性以及set方法):
public class Student {
private String name;
private int age;
private School school;
public void setSchool(School school) {
this.school = school;
}
public Student() {
System.out.println("创建学生对象");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
applicationContext.xml文件,创建学生对象,对于学校属性使用ref注入:
<bean id="stu" class="com.bjpowernode.pojo.Student">
<property name="name" value="小明"></property>
<property name="age" value="22"></property>
<property name="school" ref="school"></property>
</bean>
测试:
@Test
public void testStudent2(){
//由Spring容器进行对象创建
//如果想从Spring容器中取出对象,则要先创建容器对象并启动才可以取对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//取对象
Student stu =(Student) ac.getBean("stu");
System.out.println(stu);
}
运行结果:
2.2.2 使用构造方法注入
Student stu = new Student(“小明”,22);
2.2.2.1 使用构造方法的参数名称进行注入值
学校实体类(没有无参构造方法、没有set方法):
public class School {
private String name;
private String address;
//使用带参构造方法注入值
public School(String name, String address) {
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
创建学校对象,并注入值:
<bean id="school" class="com.bjpowernode.pojo.School">
<constructor-arg name="name" value="西西大学"></constructor-arg>
<constructor-arg name="address" value="西西区"></constructor-arg>
</bean>
2.2.2.2 使用构造方法参数的下标注入值
<bean id="school" class="com.bjpowernode.pojo.School">
<constructor-arg index="0" value="西西大学"></constructor-arg>
<constructor-arg index="1" value="西西区"></constructor-arg>
</bean>
2.2.2.3 使用默认的构造方法的参数的顺序注入值
<bean id="school" class="com.bjpowernode.pojo.School">
<constructor-arg value="西西大学"></constructor-arg>
<constructor-arg value="西西区"></constructor-arg>
</bean>
三、基于注解的IOC
也成为DI(Dependency Injection),它是IOC具体实现的技术。
基于注解的IOC,必须要在Spring的核心配置文件中添加包扫描。
当前实体类所在的包名:
<context:component-scan base-package="com.bjpowernode.pojo"></context:component-scan>
3.1 创建对象的注解
@Component:可以创建任意的对象
@Component
public class Student {
private String name;
private int age;
public Student() {
System.out.println("学生的无参构造方法调用了。。。");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类:
@Test
public void testStudent1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
}
运行结果:
@Controller:专门用来创建控制器的对象,这种对象可以接受用户的请求,可以返回处理结果给客户端
@Service:专门用来创建业务逻辑层的对象,负责向下访问数据访问层,处理完毕后的结果返回给界面层
@Repository:专门用来创建数据访问层的对象,负责数据库中的增删改查所有操作
3.2 依赖注入的注解
3.2.1 值类型的注入:
@Value:用来给简单类型注入值
@Component("stu")
public class Student {
@Value("小红")
private String name;
@Value("22")
private int age;
public Student() {
System.out.println("学生的无参构造方法调用了。。。");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试:
@Test
public void testStudent1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu = (Student) ac.getBean("stu");
System.out.println(stu);
}
运行结果:
3.2.1 引用类型的注入:
@Autowired:使用类型注入值,从整个Bean工厂中搜索同源类型的对象进行注入。
什么是同源类型:
- 被注入的类型与注入的类型是完全相同的类型
- 被注入的类型(父)与注入的类型(子)是父子类
在有父子类的情况下,使用按类型注入,就意味着有多个可注入的对象,此时按照名称进行二次筛选,选中与被注入对象相同名称的对象进行注入。 - 被注入的类型(接口)与注入的类型(实现类)是接口和实现的类型
学校实体类:
@Component//交给spring去创建对象
public class School {//此时school对象的名称就是school
@Value("西西西大学")
private String name;
@Value("西西西区")
private String address;
public School() {
System.out.println("school的无参构造方法调用了。。。");
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
学生实体类:
@Component("stu")//交给spring去创建对象
public class Student {
@Value("小红")
private String name;
@Value("22")
private int age;
//引用类型按类型注入
@Autowired
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
XML文件中的包扫描记得添加
测试类同3.2.1中的测试
运行结果:
@Qualifier:使用名称注入值,从整个Bean工厂中搜索相同名称的对象进行注入
学生实体类 (多添加一个@Qualifier):
@Component("stu")
public class Student {
@Value("小红")
private String name;
@Value("22")
private int age;
//引用类型按类型注入
@Autowired
private School school;
@Override
@Qualifier("school")
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
其余都一样。