0%

Spring IOC

1 概述

先简单的解释一下这两个总是一同出现的概念,

  1. IOC(控制反转):就是字面意思,由Spring容器来管理实例对象的生命周期,包括对象的创建与销毁等,而不是开发者或者程序本身;
  2. DI(依赖注入):对象有了,我们用的时候直接找Spring要就行了,Spring给我们的这个过程就是依赖注入。

其实IOC和DI是从不同角度去描述了同一件事情,对象之间的解耦。

为什么使用?解了什么耦?

不使用IOC的话,对象之间相互调用错综复杂,创建销毁也频繁发生,一个对象发生错误可能导致整个系统完蛋。但是对象之间的耦合是不能避免的,所以,使用IOC容器作为中间件来耦合这些对象,对象之间相互独立,就达到了解耦的目的。

接触过单例模式的同学应该都知道,Spring IOC就是基于注册登记式的单例模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ContainerSingleton {
private ContainerSingleton() {}

private volatile static Map<String, Object> ioc = new HashMap<>();

public static Object getInstance(String name) {
Object instance = null;
if (!ioc.containsKey(name)) {
synchronized (ContainerSingleton.class) {
if (!ioc.containsKey(name)) {
try {
instance = Class.forName(name).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
ioc.put(name, instance);
}
}
}
return ioc.get(name);
}
}

回顾一下就是,创建一个容器(HashMap),容器中的key就是这个实例的唯一标识,使用的时候通过key去获取就行了。

2 进阶

我们通过一个简单的例子来说明一下IoC思想,假如有两个类,Company和Employee,并且Company依赖于Employee。

1
2
3
4
5
6
7
8
9
public class Employee {
private String name;
private int age;

public Employee(String name, int age) {
this.name = name;
this.age = age;
}
}
  1. 符合IoC的做法

    1
    2
    3
    4
    5
    6
    7
    public class Company {
    private Employee employee;

    public Company(Employee employee) {
    this.employee = employee;
    }
    }
  2. 不符合IoC的做法(直接在Company里面实例化Employee)

    1
    2
    3
    public class Company {
    private Employee employee = new Employee("马玉", 26);
    }
  3. 不符合IoC的做法(非构造函数传入依赖)

    1
    2
    3
    4
    5
    6
    7
    public class Company {
    private Employee employee;

    public void init(Employee employee) {
    this.employee = employee;
    }
    }

    所以,Spring 启动时会把所需的类实例化成对象,如果需要依赖,则先实例化依赖,然后实例化当前类。因为依赖必须通过构建函数传入,所以实例化时,当前类就会接收并保存所有依赖的对象。这一步也就是所谓的依赖注入