DEV Community

Liu yu
Liu yu

Posted on

IOC

⭐ *Spring IOC(控制反转)


1️⃣ IOC 是什么?(一句话)

IOC(控制反转)是把“对象创建与依赖管理”的控制权,从代码本身反转到 Spring 容器,由容器来统一创建、管理和装配 Bean。

这意味着:

  • 你不再 new 对象
  • 不再手动管理依赖
  • 只需要声明“我需要什么”,Spring 自动帮你准备好

2️⃣ DI(依赖注入)是什么?IOC 如何落地?

IOC 是思想,DI 是实现 IOC 的具体方式

Spring 通过三种方式实现依赖注入:

✔ 构造器注入(推荐)

public UserService(UserRepository repo) { ... }
Enter fullscreen mode Exit fullscreen mode

Spring 会:

查构造器 → 查参数类型 → 找到对应 Bean → 自动注入
Enter fullscreen mode Exit fullscreen mode

✔ Setter 注入

✔ 字段注入(常用但不推荐)

构造器注入从 Spring 4.3 起,只有一个构造器时甚至不需要 @Autowired


3️⃣ Spring 如何实现依赖注入?(最关键的部分)

当 Spring 要创建一个 Bean 时,它会:

1. 找到 Bean 的构造器
2. 查看构造器需要哪些参数(依赖)
3. 到 IOC 容器查找对应类型的 Bean 实例
4. 若依赖 Bean 尚未创建 → 先创建依赖 Bean
5. 使用构造器创建当前 Bean(依赖注入发生在此处)
6. 完成初始化,放入 IOC 容器中
Enter fullscreen mode Exit fullscreen mode

核心点:

依赖注入发生在“创建 Bean 的瞬间”,不是创建后再塞进去。


4️⃣ IOC 容器到底是什么?它管理什么?

IOC容器是一个“智能工厂”,内部用一个大 Map 存 Bean:

Map<String, Object> singletonObjects
Enter fullscreen mode Exit fullscreen mode

它负责:

  • 创建 Bean(实例化)
  • 注入依赖(DI)
  • 管理生命周期(初始化、销毁)
  • 处理代理(AOP、事务)

Spring 容器的两大核心实现:

容器类型 含义
BeanFactory 最基础的 IOC 工厂
ApplicationContext BeanFactory 的增强版,是我们实际使用的容器

我们日常说的“Spring IOC 容器”基本指 ApplicationContext


5️⃣ 为什么这一行代码就自动注入了?

public UserService(UserRepository repo)
Enter fullscreen mode Exit fullscreen mode

因为 Spring:

  1. 类只有一个构造器 → 默认用它进行依赖注入
  2. 构造器参数类型为 UserRepository
  3. 容器中刚好存在该类型的 Bean
  4. Spring 自动匹配并注入

背后的执行者是:

AutowiredAnnotationBeanPostProcessor

它负责解析构造器、字段、setter,并完成注入。


6️⃣ IOC 的核心价值(面试会问)

✔ 解耦(最重要)

类之间不再主动 new 依赖对象,不再绑定具体实现。

✔ 更容易测试

可以随时替换依赖为 Mock 对象。

✔ 生命周期统一管理

由容器统一创建、销毁 Bean。

✔ 更容易扩展

只需要加一个实现类,Spring 就能自动装配。


7️⃣ IOC + DI 最简公式(面试必背)

IOC:对象创建与依赖管理反转给容器。
DI:容器在创建 Bean 时自动将其依赖注入进去。
ApplicationContext 是实际使用的 IOC 容器。


📌 最终浓缩版(你可以背这个):

IOC 是把控制权从代码反转给 Spring 容器,让容器负责 Bean 的创建、依赖注入和生命周期管理。
DI 是 IOC 的实现方式,通过构造器/Setter/字段让容器在创建 Bean 时自动注入依赖。
Spring 在创建 Bean 时解析构造器参数,找到依赖 Bean,从容器取出并注入进去。
IOC 容器本质是一个管理 Bean 的智能工厂,常用实现是 ApplicationContext。


🔹 一个手写 mini-IOC(20行代码)让你彻底理解原理


import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

class MiniIOC {

    private Map<Class<?>, Object> singletonObjects = new HashMap<>();

    // 获取 Bean
    public Object getBean(Class<?> clazz) throws Exception {

        // 1. 单例池中已有 → 直接返回
        if (singletonObjects.containsKey(clazz)) {
            return singletonObjects.get(clazz);
        }

        // 2. 创建 Bean(核心逻辑)

        // 找构造器
        Constructor<?> constructor = clazz.getDeclaredConstructors()[0]; 


        // 找参数类型
        Class<?>[] paramTypes = constructor.getParameterTypes();         

        // 3. 递归创建依赖 Bean
        Object[] dependencies = new Object[paramTypes.length];
        for (int i = 0; i < paramTypes.length; i++) {
            dependencies[i] = getBean(paramTypes[i]); // 递归调用
        }

        // 4. 调用构造器创建 Bean
        Object bean = constructor.newInstance(dependencies);

        // 5. 放入单例池
        singletonObjects.put(clazz, bean);

        return bean;
    }
}
Enter fullscreen mode Exit fullscreen mode

🎯 一句话本质总结(你可以背的)

IOC 本质就是:一个 Map 作为单例工厂 + 通过反射分析构造器参数,在创建 Bean 时递归创建依赖 Bean,实现自动注入。


为什么要用 IOC?

IOC 的核心价值是解耦。
以前对象之间通过 new 互相依赖,耦合度高、难以替换实现、难测试、生命周期难管理。

使用 IOC 后,Bean 的创建、依赖注入由容器统一管理,业务类只声明自己需要什么,从而实现:

  1. 解耦(不再自己 new)
  2. 易扩展(可随时替换实现)
  3. 易测试(能轻松注入 Mock)
  4. 易管理(生命周期、单例等)

IOC 是 Spring 能够模块化、可扩展、易维护的基础。


一句话总结:

IOC = 解耦 + 易扩展 + 易测试 + 统一管理。


Top comments (0)