跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Spring IoC 与依赖注入核心原理

Spring IoC(控制反转)将对象创建权交给容器,解决传统开发中类间高耦合问题。通过依赖注入(DI),对象不再主动创建依赖,而是被动接收。这种模式实现了资源集中管理,降低模块依赖,提升系统灵活性与可维护性。IoC 是思想目标,DI 是具体实现手段,两者共同构成了 Spring 框架的基础。

极光发布于 2026/3/15更新于 2026/10/2694 浏览
Spring IoC 与依赖注入核心原理

文章配图

什么是 IoC?

Spring 本质上是一个包含众多工具方法的 IoC 容器。当我们给类添加 @RestController 或 @Controller 注解时,实际上是将对象的生命周期管理权交给了 Spring。框架启动后会自动加载并管理这些类,这种思想就是控制反转(Inversion of Control, IoC)。

简单来说,控制权发生了反转。在传统开发中,需要某个对象时,我们通常通过 new 关键字自己创建;而在 IoC 模式下,创建对象的任务被移交给了容器,程序只需要关注如何获取和使用这个依赖对象即可。这个负责管理的容器被称为 IoC 容器,Spring 正是这样一个典型的 IoC 容器。

传统实现思路的痛点

为了理解为什么需要 IoC,我们可以先看一个经典的汽车制造案例。假设我们要设计一辆车,逻辑是这样的:先设计轮胎 (Tire),再根据轮胎大小设计底盘 (Bottom),接着根据底盘设计车身 (Framework),最后组装成整车 (Car)。

这里存在明显的依赖关系:汽车依赖车身,车身依赖底盘,底盘依赖轮胎。

文章配图

在这种传统模式下,代码结构如下:

public class Main {
    public static void main(String[] args) {
        Car car = new Car(21);
        car.run();
        Car car2 = new Car(17);
        car2.run();
    }
}

// 汽车
class Car {
    private Framework framework;
    public Car(int size) {
        framework =  (size);
        System.out.println();
    }
       {
        System.out.println();
    }
}


  {
     Bottom bottom;
      {
        bottom =  (size);
        System.out.println();
    }
}


  {
     Tire tire;
      {
        tire =  (size);
        System.out.println();
    }
}


  {
      size;
      {
        System.out.println( + size);
    }
}
new
Framework
"framework init..."
public
void
run
()
"car run..."
// 车身
class
Framework
private
public
Framework
(int size)
new
Bottom
"bottom init...."
// 底盘
class
Bottom
private
public
Bottom
(int size)
new
Tire
"tire init..."
// 轮胎
class
Tire
private
int
public
Tire
(int size)
"tire size:"

乍看之下,这段代码逻辑通顺。但一旦需求变更,比如要增加轮胎颜色属性,问题就暴露了。我们需要在 Tire 类加字段,然后 Bottom、Framework、Car 甚至 Main 方法都要跟着改。最底层变动会引发调用链上所有代码的连锁反应,耦合度极高,维护成本随之飙升。

修改后的完整代码如下:

public class Main {
    public static void main(String[] args) {
        Car car = new Car(21, "aaa");
        car.run();
        Car car2 = new Car(17, "bbb");
        car2.run();
    }
}

// 汽车
class Car {
    private Framework framework;
    public Car(int size, String color) {
        framework = new Framework(size, color);
        System.out.println("framework init...");
    }
    public void run() {
        System.out.println("car run...");
    }
}

// 车身
class Framework {
    private Bottom bottom;
    public Framework(int size, String color) {
        bottom = new Bottom(size, color);
        System.out.println("bottom init....");
    }
}

// 底盘
class Bottom {
    private Tire tire;
    public Bottom(int size, String color) {
        tire = new Tire(size, color);
        System.out.println("tire init...");
    }
}

// 轮胎
class Tire {
    private int size;
    private String color;
    public Tire(int size, String color) {
        System.out.println("tire size:" + size + ",color:" + color);
    }
}

可以看到,只要最底层改动,整个调用链上的所有代码都需要修改。这就是高耦合带来的麻烦。

解决方案:依赖注入

为了解耦,我们尝试改变实现方式:让依赖关系反向流动。即轮胎依赖底盘,底盘依赖车身,车身依赖汽车。更准确地说,是上层对象不再主动创建下层对象,而是由外部传入。

我们将创建子类的行为改为注入传递的方式。改造后的代码如下:

class Main {
    public static void main(String[] args) {
        Tire tire = new Tire(17, "red");
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.run();
    }
}

// 汽车
class Car {
    private Framework framework;
    public Car(Framework framework) {
        this.framework = framework;
        System.out.println("framework init...");
    }
    public void run() {
        System.out.println("car run...");
    }
}

// 车身
class Framework {
    private Bottom bottom;
    public Framework(Bottom bottom) {
        this.bottom = bottom;
        System.out.println("bottom init....");
    }
}

// 底盘
class Bottom {
    private Tire tire;
    public Bottom(Tire tire) {
        this.tire = tire;
        System.out.println("tire init...");
    }
}

// 轮胎
class Tire {
    private int size;
    private String color;
    public Tire(int size, String color) {
        System.out.println("tire size:" + size + ",color:" + color);
    }
}

经过调整,无论底层类如何变化,只要接口不变,整个调用链就不需要做任何修改。这就实现了代码之间的解耦,让程序设计更加灵活通用。

IoC 的优势

对比两种模式,传统代码的对象创建顺序是:Car -> Framework -> Bottom -> Tire。而改进后的解耦代码,对象创建顺序变成了:Tire -> Bottom -> Framework -> Car。

文章配图

我们发现了一个规律:通用程序的实现中,类的创建顺序往往是反的。传统模式中,使用方对象(如 Car)控制并创建了依赖对象(Framework),层层向下;而改进之后,控制权发生了反转。不再是使用方对象去创建和控制依赖对象,而是将依赖对象注入到当前对象中。依赖对象的控制权不再由当前类掌握。

这样一来,即使依赖类发生任何改变,当前类都不受影响。这就是典型的控制反转,也是 IoC 的核心思想。

那么什么是 IoC 容器呢?它负责执行这部分工作:

文章配图

IoC 容器具备以下显著优点:

  1. 资源集中管理:资源不由使用资源的双方直接管理,而是由不直接使用资源的第三方(容器)管理。这带来了极大的便利,IoC 容器帮我们管理对象等资源,使用时直接从容器中获取即可。
  2. 降低耦合度:我们在创建实例时无需了解内部细节,降低了使用资源双方的依赖程度。

Spring 就是一种 IoC 容器,它帮助我们完成了这些资源管理工作。

DI:依赖注入

DI 全称 Dependency Injection(依赖注入)。当容器运行期间,动态地为应用程序提供运行时所依赖的资源,这个过程就称为依赖注入。

程序运行时需要某个资源,此时容器就为其提供这个资源。从这点来看,依赖注入(DI)和控制反转(IoC)是从不同角度描述同一件事情:都是通过引入 IoC 容器,利用依赖关系注入的方式,实现对象之间的解耦。

在前面的代码示例中,我们通过构造函数的参数,把依赖对象注入到了需要使用它的对象中。

文章配图

总结来说,IoC 是一种思想,也是一种目标,它指导我们如何设计系统以降低耦合;而 DI 则是具体的落地方案,是实现 IoC 的一种手段。所以也可以说,DI 是 IoC 的具体实现。

目录

  1. 什么是 IoC?
  2. 传统实现思路的痛点
  3. 解决方案:依赖注入
  4. IoC 的优势
  5. DI:依赖注入

更多推荐文章

查看全部
  • 电科金仓发布融合数据库 KES V9,探索 AI 时代新形态
  • C++ 红黑树详解:原理、插入与验证
  • 基于 OpenCode + OpenSpec 的 AI 编码规范驱动开发实践
  • SLAM Toolbox 机器人建图与定位技术指南
  • Python SQLAlchemy ORM 核心实战指南
  • Claude Code 安装配置与实战使用指南
  • 2026 焊接机器人十大品牌推荐
  • LeetCode 75. 颜色分类
  • 从 CRUD 到架构师:Java 工程师的十年进阶路线图
  • AI 游戏 Agent 训练案例深度拆解
  • Flutter 组件 Spry 适配鸿蒙 HarmonyOS 实战:轻量级端侧 Web 服务
  • VSCode 本地运行 DeepSeek 模型教程
  • ERNIE-4.5-0.3B 超轻量模型部署与实战指南
  • CycleGAN 详解与图像风格转换实现
  • 14 个提升 JavaScript 开发效率的实用技巧
  • Web3 学习指南:从比特币到以太坊的演进
  • 人工智能从入门到实战
  • Linux 系统部署 OpenClaw 并接入 QQ 机器人指南
  • AI 安全高阶:模型可解释性与安全防护结合
  • Python 遍历字典的 8 种常用方法

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online