深入浅出Spring IoC:手把手教你实现一个简易IoC容器
前言
在Spring框架中,IoC(控制反转) 和 AOP(面向切面编程) 是两大核心特性。很多开发者每天都在使用Spring,却对IoC容器的内部实现原理一知半解。你是否想过:Spring是如何管理Bean的?为什么我们不再需要手动new对象了?Bean工厂到底做了什么?
本文将从零开始,带你手写实现一个简易的IoC容器,深入理解Spring的核心原理。通过一步步的设计和代码实现,你将彻底掌握Bean工厂、Bean定义、Bean注册等核心概念,为后续学习Spring源码打下坚实基础。
目录
一、IoC核心概念分析
1. Spring的核心是什么
在Spring框架中,最核心的两个特性就是 IoC 和 AOP。本文我们将重点剖析IoC的实现原理。

2. IoC的四个关键问题
2.1 IoC是什么?
IoC(Inversion of Control),即控制反转。简单来说:依赖对象的获得被翻转了。
传统开发模式中,我们需要自己创建依赖对象:
// 传统方式:手动创建依赖对象
UserService userService = new UserService();
UserDao userDao = new UserDao();
userService.setUserDao(userDao);
使用IoC后,对象由容器创建和管理:
// IoC方式:从容器获取对象
UserService userService = (UserService) context.getBean("userService");

2.2 IoC有什么好处?
IoC带来的三大核心优势:
- 代码更简洁:不需要手动new对象,减少样板代码
- 解耦更彻底:面向接口编程,使用者与具体实现解耦,易于扩展和替换
- AOP支持:IoC为AOP提供了基础,方便进行横切关注点的编程

2.3 IoC容器做什么?
IoC容器的核心职责:
- 创建 Bean实例
- 管理 Bean的生命周期
- 提供 Bean实例给使用者

2.4 IoC容器与工厂模式
是的!IoC容器本质上就是工厂模式的实现。IoC容器负责创建对象实例,使用者通过getBean方法获取。因此,IoC容器也被称为Bean工厂。

关键概念:Bean = 组件 = 类的对象实例
二、IoC容器实现
通过上述分析,我们明确了IoC的核心是Bean工厂。下面让我们一步步实现它。
1. Bean工厂的作用
Bean工厂的三大核心职责:
- 创建Bean
- 管理Bean
- 对外提供Bean实例

2. Bean工厂初步设计
基于Bean工厂的职责,我们来分析它应该具备的行为:

首先,Bean工厂需要对外提供获取Bean实例的方法,因此需要定义 getBean() 方法。同时,工厂需要知道要生产的Bean类型,所以getBean方法需要接受参数,返回类型用Object表示:
public interface BeanFactory {
Object getBean(String beanName);
}

核心问题:Bean工厂如何知道要创建什么对象?如何创建?

解决方案:
- 定义一个模型来表示如何创建Bean实例的信息 → Bean定义
- Bean工厂提供接收Bean定义信息的行为 → 注册机制
3. Bean定义详解
3.1 BeanDefinition的作用
告诉Bean工厂如何创建某个类的Bean实例。
3.2 获取Bean实例的方式

主要有两种方式:
- 通过构造方法反射创建
- 通过工厂方法创建
3.3 BeanDefinition需要提供的信息

核心信息包括:
- Bean的Class类型
- Scope(作用域:单例/原型)
- 工厂Bean名称和工厂方法名称
- 初始化方法和销毁方法
3.4 BeanDefinition接口实现
完整代码如下:
/**
* Bean定义接口
*/
public interface BeanDefinition {
String SCOPE_SINGLETION = "singleton";
String SCOPE_PROTOTYPE = "prototype";
/**
* 获取Bean的Class类型
*/
Class<?> getBeanClass();
/**
* 获取作用域
*/
String getScope();
/**
* 是否单例
*/
boolean isSingleton();
/**
* 是否原型
*/
boolean isPrototype();
/**
* 工厂Bean名称
*/
String getFactoryBeanName();
/**
* 工厂方法名称
*/
String getFactoryMethodName();
/**
* 初始化方法名称
*/
String getInitMethodName();
/**
* 销毁方法名称
*/
String getDestroyMethodName();
/**
* 是否主要候选Bean
*/
boolean isPrimary();
/**
* 校验Bean定义的合法性
*/
default boolean validate() {
// 没定义class,工厂bean或工厂方法没指定,则不合法
if (this.getBeanClass() == null) {
if (StringUtils.isBlank(getFactoryBeanName()) || StringUtils.isBlank(getFactoryMethodName())) {
return false;
}
}
// 定义了类,又定义工厂bean,不合法
if (this.getBeanClass() != null && StringUtils.isNotBlank(getFactoryBeanName())) {
return false;
}
return true;
}
}
同时创建通用实现类 GenericBeanDefinition:
public class GenericBeanDefinition implements BeanDefinition {
private Class<?> beanClass;
private String scope = SCOPE_SINGLETION;
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
private boolean primary = false;
// getter和setter方法省略...
}
4. Bean注册机制
BeanDefinition定义好后,需要将其注册到Bean工厂。为此,我们定义 BeanDefinitionRegistry 接口:

4.1 BeanDefinitionRegistry接口设计
需要具备两大功能:
- 注册BeanDefinition
- 获取BeanDefinition
为保证能区分每个BeanDefinition,需要为每个Bean定义唯一名称。

代码实现:
public interface BeanDefinitionRegistry {
/**
* 注册Bean定义
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionRegistException;
/**
* 获取Bean定义
*/
BeanDefinition getBeanDefinition(String beanName);
/**
* 是否包含指定Bean定义
*/
boolean containsBeanDefinition(String beanName);
}
5. BeanFactory核心实现
5.1 DefaultBeanFactory功能清单
目前的设计架构:

DefaultBeanFactory 需要实现的5大功能:
- 实现Bean定义信息的注册
- 实现getBean方法
- 实现初始化方法的执行
- 实现单例管理
- 实现容器关闭时执行销毁操作

思考:对于单例Bean,可否提前实例化?(预实例化策略)

三、IoC容器增强
基础版IoC容器实现后,我们继续增强其功能。
1. Bean别名机制
Bean除了唯一名称外,还可以有别名。别名特点:
- 可以有多个别名
- 别名也可以有别名
- 别名也是唯一的
实现时需要考虑:
- 数据结构:如何存储名称与别名的映射关系
- 功能点:如何解析别名获取真实Bean名称

具体实现留给读者自行完成。
2. 按Type获取Bean
除了通过Bean名称获取实例,还需要支持按类型获取Bean。
2.1 扩展接口
public interface BeanFactory {
Object getBean(String beanName);
// 新增:按类型获取Bean
<T> T getBean(Class<T> requiredType);
}
2.2 实现思路
朴素实现方式:

遍历所有Bean定义,找到类型匹配的Bean。但这种方式性能较差。
优化方案:提前构建Type与Bean名称的映射关系,用Map缓存:
private Map<Class<?>, Set<String>> typeMap = new ConcurrentHashMap<>(256);
2.3 buildTypeMap方法实现
在DefaultBeanFactory中添加类型映射构建方法:

核心逻辑:
- 遍历所有Bean定义
- 获取Bean的Class类型及其所有父类和接口
- 建立Class → Set的映射关系
- 处理一个Class对应多个Bean的情况(通过@Primary注解)

2.4 完整流程
- 在BeanFactory中添加
getType()方法,封装获取Bean类型的逻辑 - 实现
buildTypeMap()构建类型映射 - 实现
getBean(Class<T>)方法 - 处理一个类型对应多个Bean的情况(通过Primary判断)
四、总结
本文从零开始,一步步实现了Spring IoC容器的核心功能。让我们回顾一下关键知识点:
核心要点
-
IoC本质:控制反转,将对象的创建和管理交给容器
-
核心组件:
BeanFactory:Bean工厂接口,提供获取Bean的方法BeanDefinition:Bean定义,描述如何创建Bean实例BeanDefinitionRegistry:Bean定义注册表,管理Bean定义DefaultBeanFactory:默认实现,整合上述功能
-
关键特性:
- 单例管理:容器级别的单例缓存
- 生命周期:初始化方法和销毁方法
- 别名机制:Bean可以有多个别名
- 按类型获取:支持通过Class类型获取Bean
架构图
最终的IoC容器核心类图:

后续学习建议
- 深入阅读Spring源码,对比本文的简化实现
- 学习BeanPostProcessor机制,理解Bean的后置处理
- 研究循环依赖的解决方式
- 扩展AOP功能,实现完整的Spring核心
如果本文对你有帮助,欢迎点赞、收藏、关注!有问题欢迎评论区留言讨论~
关键词:Spring IoC, 控制反转, Bean工厂, 手写Spring, 源码解析, Java, 框架原理
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)