IoC容器工作原理的通俗版解释
个人名片
🎓作者简介:java领域优质创作者
🌐个人主页:码农阿豪
📞工作室:新空间代码工作室(提供各种软件服务)
💌个人邮箱:[2435024119@qq.com]
📱个人微信:15279484656
🌐个人导航网站:www.forff.top
💡座右铭:总有人要赢。为什么不能是我呢?
- 专栏导航:
码农阿豪系列专栏导航
面试专栏:收集了java相关高频面试题,面试实战总结🍻🎉🖥️
Spring5系列专栏:整理了Spring5重要知识点与实战演练,有案例可直接使用🚀🔧💻
Redis专栏:Redis从零到一学习分享,经验总结,案例实战💐📝💡
全栈系列专栏:海纳百川有容乃大,可能你想要的东西里面都有🤸🌱🚀
目录
IoC容器工作原理的通俗版解释
我们可以用一个"自动玩具工厂"的比喻来理解IoC容器的工作原理,这样会更加形象易懂。
🏭 玩具工厂流水线(IoC容器工作流程)
1️⃣ 设计图纸阶段(配置阶段)
想象你要开一家玩具工厂,首先需要:
- 列出所有玩具种类:比如小熊、小汽车、积木(这相当于各种Bean的定义)
- 注明需要的零件:小熊需要眼睛+填充棉,小汽车需要轮子+车身(这相当于依赖关系)
在Spring中,这个阶段就是:
<!-- 相当于玩具设计图纸 -->
<bean id="teddyBear" class="com.example.TeddyBear">
<property name="eye" ref="blackEye"/> <!-- 需要黑色眼睛 -->
<property name="stuffing" ref="cotton"/> <!-- 需要棉花填充 -->
</bean>
2️⃣ 原材料准备阶段(资源加载)
工厂需要:
- 采购原材料:眼睛、棉花、轮子等(Spring会扫描所有配置的类)
- 分类存放:把不同材料放在不同仓库(Spring将类信息加载到内存)
3️⃣ 组装生产线(实例化过程)
现在开始生产玩具:
-
第一步:先造小零件
工厂会先生产不需要依赖其他零件的简单零件(比如眼睛、轮子)
(Spring先实例化没有依赖的简单Bean) -
第二步:组装复杂玩具
用造好的零件组装更复杂的玩具:
比如先有眼睛和棉花 → 才能组装小熊
先有轮子和车身 → 才能组装小汽车
(Spring会解决依赖关系,按正确顺序实例化Bean)
4️⃣ 质量检查(生命周期回调)
组装完成后:
- 给玩具贴标签:@PostConstruct标注的方法会被调用
- 包装前检查:实现InitializingBean接口的afterPropertiesSet()方法
public class TeddyBear implements InitializingBean {
@PostConstruct
public void addRibbon() {
System.out.println("给小熊系上蝴蝶结");
}
@Override
public void afterPropertiesSet() {
System.out.println("检查小熊缝线是否牢固");
}
}
5️⃣ 成品仓库(单例池)
生产好的玩具会被:
- 放入展示柜:每个款式只放一个样品(默认单例模式)
- 贴上编号标签:比如"teddyBear-001"(Bean的名称)
当顾客想要小熊时,直接从展示柜拿样品,不用每次都重新生产(Spring默认返回同一个实例)
6️⃣ 特需定制(作用域扩展)
有些特殊需求:
- 每次要新玩具:@Scope(“prototype”)标注的Bean每次都会新建
- 限定使用场景:比如只在一次游戏期间有效的玩具(request/session作用域)
7️⃣ 报废处理(销毁阶段)
当工厂关门时:
- 执行清理工作:@PreDestroy方法会被调用
- 回收资源:实现DisposableBean接口的destroy()方法
public class TeddyBear implements DisposableBean {
@PreDestroy
public void removeRibbon() {
System.out.println("解下蝴蝶结回收利用");
}
@Override
public void destroy() {
System.out.println("拆解小熊回收棉花");
}
}
🧩 关键点总结表
| 工厂步骤 | Spring IoC对应概念 | 具体表现 |
|---|---|---|
| 设计图纸 | Bean定义配置 | XML/注解声明哪些类需要被管理 |
| 原材料采购 | 组件扫描 | @ComponentScan扫描包路径 |
| 组装顺序 | 依赖解决 | 先实例化没有依赖的Bean,再逐步组装复杂对象 |
| 质检流程 | 生命周期回调 | @PostConstruct、InitializingBean、@PreDestroy、DisposableBean |
| 展示柜样品 | 单例池(Singleton Pool) | 默认情况下每个Bean只有一个实例 |
| 定制生产 | 作用域(Scope) | prototype/request/session等不同作用域 |
| 清洁工 | 容器关闭回调 | 调用所有Bean的销毁方法 |
🌰 举个实际例子
假设我们要做一个游戏角色系统:
// 定义武器接口
public interface Weapon {
void attack();
}
// 具体武器实现
@Component // 放入工厂的"设计图纸"
public class Sword implements Weapon {
@Override
public void attack() {
System.out.println("剑击!");
}
}
// 角色类
@Component
public class GameCharacter {
private final Weapon weapon;
// 工厂会自动找到合适的Weapon实现注入
@Autowired
public GameCharacter(Weapon weapon) {
this.weapon = weapon;
}
public void fight() {
weapon.attack();
}
}
工作流程:
- Spring发现GameCharacter需要Weapon
- 查找所有Weapon实现类,找到Sword
- 先创建Sword实例(简单Bean)
- 用Sword实例创建GameCharacter
- 当我们获取GameCharacter时,它已经装配好了Sword
就像玩具工厂自动完成了:
- 先生产剑的零件
- 然后把剑装配给游戏角色
- 最后给我们一个拿剑的完整角色
这样的设计让各个组件像积木一样可以灵活替换,比如把Sword换成Gun只需要改配置,不需要修改GameCharacter的代码。这就是IoC容器的魔力所在!


浙公网安备 33010602011771号