news 2026/3/7 19:59:34

【Spring】超详细!一篇文章让你完全理解Spring Ioc和 DI

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Spring】超详细!一篇文章让你完全理解Spring Ioc和 DI

【Spring】超详细!一篇文章让你完全理解 Spring IoC 和 DI

大家好,我是 Grok。今天我们来聊聊 Spring 框架的核心灵魂——IoC(Inversion of Control,控制反转)DI(Dependency Injection,依赖注入)。如果你是 Spring 小白,或者想彻底搞懂这两个概念,这篇文章绝对够用!我们从基础原理入手,逐步深入到实际代码、配置和高级玩法,保证逻辑清晰、易记。

为什么说“超详细”?因为我会用:

  • 通俗比喻:像“厨师 vs 餐厅老板”来解释抽象概念。
  • 表格对比:快速区分传统方式 vs Spring 方式。
  • 代码示例:Maven + Java 简单项目,复制就能跑。
  • 步骤拆解:从 XML 配置到注解、Java 配置,全覆盖。
  • 常见坑:避免初学者踩雷。

假设你有 Java 基础(类、接口、Maven),没问题就开始吧~

第一部分:基础概念——IoC 和 DI 到底是什么?

1.1 IoC:控制反转(Inversion of Control)

传统编程:你(程序员)像个“厨师”,自己控制一切——创建对象、调用方法、管理依赖。比如,你要一个“汽车”对象,就自己new Car(),然后自己组装轮子、引擎。

IoC 的核心思想:把“控制权”反转给别人(Spring 容器)。你不再自己new对象,而是告诉 Spring:“我需要一个汽车”,Spring 像“餐厅老板”一样,自动帮你组装好、注入依赖、甚至管理生命周期。

  • 为什么需要 IoC?
    传统方式耦合太紧:改一个类,就得改一堆地方。IoC 解耦,让代码更灵活、可测试、可扩展。

  • IoC 的好处(3 大关键词):

    • 解耦:模块间不直接依赖,改动不连锁反应。
    • 复用:对象像“乐高积木”,随时组装。
    • 管理:Spring 统一管理对象创建、销毁、作用域。

IoC 是“思想”,DI 是“实现方式”。IoC 就像“外卖平台”,DI 就像“骑手送餐”。

1.2 DI:依赖注入(Dependency Injection)

DI 是 IoC 的具体实现:Spring 不是让你自己找依赖,而是“注入”给你。

  • 依赖什么?一个对象需要另一个对象才能工作。比如,Car需要EngineWheel
  • 注入怎么做?Spring 通过配置(XML/注解/Java)自动把依赖“塞”进你的对象。

DI 的 3 种方式(按注入时机分):

方式描述优点/缺点示例场景
构造函数注入通过构造方法注入依赖强制依赖(对象创建时就注入),测试友好核心依赖(如数据库连接)
Setter 注入通过 Setter 方法注入灵活(可选依赖),但可能注入不全可选配置(如日志级别)
接口注入通过接口方法注入(较少用)动态,但复杂遗留系统集成

DI 让你的代码从“主动拉取”依赖变成“被动接收”。

1.3 IoC vs DI 的关系(别混淆!)

  • IoC 是大概念:控制反转,包括 DI 和其他(如 AOP)。
  • DI 是 IoC 的子集:具体怎么反转控制?通过注入依赖。
  • Spring 的 IoC 容器:ApplicationContextBeanFactory,管理所有 Bean(对象)。

一句话:IoC 是“老板指挥”,DI 是“老板给你发工具”。

第二部分:Spring 中的 IoC 和 DI 实战

Spring 版本:假设用 Spring Boot 2.7+ 或 Spring Framework 6.x(2026 年主流)。先建个 Maven 项目:

<!-- pom.xml 核心依赖 --><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.0</version><!-- 最新版自行替换 --></dependency></dependencies>

2.1 配置方式 1:XML 配置(经典,但老派)

XML 是 Spring 最早的配置方式,适合理解底层。

步骤拆解

  1. 定义 Bean:XML 文件中声明对象。
  2. 注入依赖:用<property><constructor-arg>
  3. 获取容器:ClassPathXmlApplicationContext加载 XML。

示例代码

  • 接口和类:
publicinterfaceEngine{voidstart();}publicclassPetrolEngineimplementsEngine{publicvoidstart(){System.out.println("Petrol Engine started");}}publicclassCar{privateEngineengine;// 依赖// Setter 注入publicvoidsetEngine(Engineengine){this.engine=engine;}publicvoiddrive(){engine.start();System.out.println("Car is driving");}}
  • XML 配置(applicationContext.xml):
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义 Bean --><beanid="petrolEngine"class="com.example.PetrolEngine"/><beanid="car"class="com.example.Car"><!-- DI:Setter 注入 --><propertyname="engine"ref="petrolEngine"/></bean></beans>
  • 测试:
publicclassMain{publicstaticvoidmain(String[]args){ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");Carcar=(Car)context.getBean("car");// IoC 容器提供car.drive();// 输出: Petrol Engine started \n Car is driving}}

构造函数注入版 XML(替换<property>):

<beanid="car"class="com.example.Car"><constructor-argref="petrolEngine"/></bean>

Car 类加构造:public Car(Engine engine) { this.engine = engine; }

2.2 配置方式 2:注解配置(现代主流,简单)

从 Spring 2.5 开始,注解取代 XML。Spring Boot 默认用这个。

关键注解

注解作用示例
@Component标记类为 Bean(通用)@Component public class Car {}
@Service业务层 Bean@Service
@RepositoryDAO 层 Bean@Repository
@ControllerWeb 层 Bean@Controller
@Autowired自动注入依赖(byType,默认)@Autowired private Engine engine;
@Qualifier指定 Bean 名(当多个同类型时)@Qualifier(“petrol”)
@Configuration配置类(代替 XML)@Configuration public class AppConfig {}
@Bean方法返回 Bean@Bean public Engine engine() {}
@ComponentScan扫描包,自动发现 Bean@ComponentScan(“com.example”)

示例代码(注解版):

  • 类:
@ComponentpublicclassPetrolEngineimplementsEngine{publicvoidstart(){System.out.println("Petrol Engine started");}}@ComponentpublicclassCar{@AutowiredprivateEngineengine;// DI 注入publicvoiddrive(){engine.start();System.out.println("Car is driving");}}
  • 配置类(可选,如果不扫描默认包):
@Configuration@ComponentScan("com.example")// 扫描包publicclassAppConfig{}
  • 测试:
publicclassMain{publicstaticvoidmain(String[]args){ApplicationContextcontext=newAnnotationConfigApplicationContext(AppConfig.class);Carcar=context.getBean(Car.class);car.drive();}}

自动装配模式(@Autowired 的底层):

  • byType:按类型匹配(默认)。
  • byName:按 Bean 名匹配(用 @Qualifier)。

2.3 配置方式 3:Java 配置(纯代码,零 XML/注解污染)

适合大型项目,配置集中。

示例(基于 2.2 的类,去掉 @Component):

@ConfigurationpublicclassAppConfig{@BeanpublicEngineengine(){returnnewPetrolEngine();}@BeanpublicCarcar(){Carc=newCar();c.setEngine(engine());// 手动 DIreturnc;}}

测试同上:new AnnotationConfigApplicationContext(AppConfig.class)

第三部分:高级玩法——Bean 管理和优化

3.1 Bean 作用域(Scope)

默认 Singleton(单例),但可以改。

Scope描述注解/配置
singleton全局唯一实例默认
prototype每次 getBean 都新创建@Scope(“prototype”)
request每个 HTTP 请求一个@Scope(“request”) (Web)
session每个会话一个@Scope(“session”)

示例:@Scope("prototype") public class Car {}

3.2 Bean 生命周期

IoC 容器管理从创建到销毁的全过程:

  1. 实例化(new)。
  2. 属性注入(DI)。
  3. 初始化(@PostConstruct 或 init-method)。
  4. 使用。
  5. 销毁(@PreDestroy 或 destroy-method)。

自定义:

publicclassCar{@PostConstructpublicvoidinit(){System.out.println("Init");}@PreDestroypublicvoiddestroy(){System.out.println("Destroy");}}

3.3 自动装配(Autowiring)

  • @EnableAutoConfiguration(Spring Boot 用):自动配置常见 Bean(如 DataSource)。
  • 问题:多个同类型 Bean?用 @Primary 标记首选,或 @Qualifier 指定。

第四部分:常见问题 & 踩坑指南

问题/坑原因解决
NoSuchBeanDefinitionExceptionBean 未定义或未扫描检查 @Component / @Bean / 扫描包
UnsatisfiedDependencyException依赖未注入检查 @Autowired / 类型匹配
循环依赖A 依赖 B,B 依赖 A用 Setter 注入 / @Lazy 延迟
XML vs 注解性能XML 解析慢优先注解 / Java 配置
测试时注入失败上下文未加载用 @SpringBootTest

调试技巧:日志级别调到 DEBUG,看 Spring 如何装配 Bean。

第五部分:总结 & 扩展学习

  • 核心回顾:IoC 是反转控制,DI 是注入依赖。Spring 通过容器(ApplicationContext)管理 Bean,实现解耦和灵活。
  • 为什么 Spring 牛?因为 IoC/DI 让大型项目像“积木”一样搭建,易维护。
  • 下一步:学 AOP(切面编程),然后 Spring Boot(简化版 Spring)。
  • 练习建议:建个小项目,注入 Service 到 Controller,模拟用户注册。

如果你有具体代码问题、或想看 Spring Boot 版示例,继续问我~比如“帮我写个带数据库的 DI 示例”?😄

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/3 19:30:44

收藏!华为员工转岗大模型拿百万年薪,小白/程序员入门LLM必看指南

近日&#xff0c;我在技术社群刷到一则刷屏热议帖&#xff1a;一位华为在职员工&#xff0c;从传统开发岗成功转型大模型算法岗后&#xff0c;高调晒出百万年薪收入条&#xff0c;还毫无保留地分享了自己的转岗全流程心得。这则帖子瞬间在程序员圈引爆讨论——评论区里&#xf…

作者头像 李华
网站建设 2026/3/4 10:28:07

基于vue3实施部门权限分配及审批的监管系统-开题报告 黄耀兴202006050071 (2)

目录研究背景与意义系统目标技术选型系统模块设计创新点预期成果项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作研究背景与意义 部门权限分配及审批监管系统在现代企业管理中具有重要作用。随着企业规模扩…

作者头像 李华
网站建设 2026/3/3 20:55:54

基于Vue技术的营养食品搭配系统的设计与实现任务书

目录系统背景与目标技术选型核心功能模块关键实现技术预期成果备注项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作系统背景与目标 现代人对健康饮食需求日益增长&#xff0c;但缺乏专业营养知识。该系统基…

作者头像 李华
网站建设 2026/3/4 10:19:48

域控制器架构十年演进

域控制器&#xff08;Domain Control Unit, DCU&#xff09; 的十年&#xff08;2015–2025&#xff09;&#xff0c;是汽车电子电气架构&#xff08;EEA&#xff09;从“诸侯割据”走向“高度中央集权”的剧变史。 它完成了从上百个分散的 ECU 到几个核心“域”的集成&#x…

作者头像 李华
网站建设 2026/3/4 8:58:41

视觉感知十年演进

视觉感知&#xff08;Visual Perception&#xff09; 的十年&#xff08;2015–2025&#xff09;&#xff0c;是从“识别照片里的像素”向“重建实时三维物理世界”的跨越。 视觉感知是自动驾驶的“眼睛”。这十年间&#xff0c;视觉算法完成了从 2D 到 3D、从局部到全局、从“…

作者头像 李华
网站建设 2026/3/4 12:06:48

什么是护网行动?

随着企业上云加速&#xff0c;护网行动的战场已延伸至云原生环境。多云架构的安全割裂、容器逃逸风险、Serverless 无服务器攻击等新挑战&#xff0c;要求防御体系从 “边界防护” 转向 “云原生全链路防护”。本文拆解云原生场景的核心风险与攻防技巧。 一、云原生环境三大核…

作者头像 李华