spring ioc实现原理
Spring 的 IoC(Inversion of Control,控制反转) 是 Spring 框架的核心思想之一,它的本质是将对象的创建、管理、依赖关系的维护交给 Spring 容器来完成,而不是由开发者手动去 new 或管理。
🧠 一、IoC 实现原理概览
✅ 控制反转(IoC)是什么?
- 传统方式:对象之间相互
new
,耦合度高。 - IoC 方式:对象的创建和依赖关系由容器来管理,程序只负责声明“需要什么”,而“怎么创建”由容器决定。
✅ 依赖注入(DI)与 IoC 的关系?
- DI 是实现 IoC 的一种方式。
- Spring 使用 DI 来实现 IoC,即通过配置(XML 或注解)来描述对象之间的依赖关系,容器在运行时自动装配这些依赖。
📦 二、IoC 容器核心组件
Spring IoC 容器主要包括以下核心接口和类:
类名 | 作用 |
---|---|
BeanFactory | 最基础的容器接口,提供基本的 IOC 功能 |
ApplicationContext | BeanFactory 的子接口,提供更多企业级功能(如 AOP、国际化等) |
BeanDefinition | 描述一个 Bean 的元信息(如类名、作用域、是否懒加载等) |
BeanPostProcessor | 在 Bean 初始化前后进行拦截处理 |
BeanFactoryPostProcessor | 在容器加载完 BeanDefinition 后修改其配置 |
🔁 三、IoC 容器启动流程(以 ApplicationContext
为例)
Spring 启动过程中最重要的方法是 refresh()
,它定义了整个容器的初始化流程。
public void refresh() throws BeansException, IllegalStateException {prepareRefresh();ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory); // 修改 BeanDefinitionregisterBeanPostProcessors(beanFactory); // 注册后置处理器initMessageSource(); // 初始化消息资源initApplicationEventMulticaster(); // 初始化事件广播器onRefresh(); // 子类扩展点registerListeners(); // 注册监听器finishBeanFactoryInitialization(beanFactory); // 实例化单例 BeanfinishRefresh(); // 刷新完成
}
其中最重要的一步是
finishBeanFactoryInitialization(beanFactory)
,它会触发所有非懒加载的单例 Bean 的实例化。
⚙️ 四、Bean 的生命周期详解
Spring 中每个 Bean 都会经历从定义到销毁的一系列阶段,以下是主要流程:
🔄 Bean 生命周期步骤
- 加载 BeanDefinition
- 从 XML、注解或 Java Config 中解析出 Bean 的元数据。
- 实例化 Bean
- 调用构造函数创建 Bean 对象(此时还未赋值属性)
- 填充属性(依赖注入)
- 根据配置自动装配依赖(@Autowired、set 方法等)
- 设置 BeanName、BeanFactory、ApplicationContext 等
- 实现
BeanNameAware
,BeanFactoryAware
接口的方法回调
- 实现
- 调用
BeanPostProcessor.beforeInitialization()
- 调用初始化方法
@PostConstruct
InitializingBean.afterPropertiesSet()
- 自定义
init-method
- 调用
BeanPostProcessor.afterInitialization()
- 使用 Bean
- 销毁 Bean
@PreDestroy
DisposableBean.destroy()
- 自定义
destroy-method
🧱 五、IoC 实现的关键技术点
1. BeanDefinition 的注册
- Spring 容器在启动时会扫描类路径下的类或 XML 配置文件,生成
BeanDefinition
并注册到BeanFactory
中。
2. 依赖注入(DI)机制
- Spring 通过反射机制调用 setter 方法或构造函数注入依赖。
- 支持按类型、按名称注入。
- 常见注解:
@Autowired
@Resource
@Inject
3. 三级缓存解决循环依赖
- Spring 解决的是 单例 Bean 的构造方法之外的循环依赖问题。
- 三级缓存结构如下:
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 一级缓存 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存
- 当发现循环依赖时,Spring 会提前暴露一个工厂对象放入三级缓存中,后续获取该 Bean 时再通过工厂创建代理对象。
4. BeanFactoryPostProcessor 和 BeanPostProcessor
BeanFactoryPostProcessor
:可以修改BeanDefinition
BeanPostProcessor
:可以在 Bean 实例化前后对其进行增强处理(例如 AOP)
📌 六、代码示例分析
示例 1:简单 Bean 加载流程
@Component
class A {@AutowiredB b;
}@Component
class B {@AutowiredA a;
}public class MainApp {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);A a = context.getBean(A.class);a.b.doSomething();}
}
在这个例子中,A 和 B 相互依赖,Spring 使用三级缓存机制解决了这个循环依赖问题。
📚 七、推荐源码阅读路径
📁 核心类路径(spring-beans、spring-context 模块):
AbstractApplicationContext.refresh()
—— 容器启动入口DefaultListableBeanFactory
—— 默认的 BeanFactory 实现AbstractBeanFactory.getBean()
—— 获取 Bean 的主逻辑AbstractAutowireCapableBeanFactory.createBean()
—— 创建 Bean 的核心方法doCreateBean()
—— 实例化 + 属性注入 + 初始化getSingleton()
—— 三级缓存相关逻辑populateBean()
—— 属性填充(依赖注入)initializeBean()
—— 初始化阶段(包括 Aware、BeanPostProcessor)
❓八、常见面试题(结合源码)
Q1: Spring 是如何管理 Bean 的生命周期的?
Spring 通过
BeanFactory
和ApplicationContext
来管理 Bean 的创建、依赖注入、初始化、销毁等全过程。通过BeanPostProcessor
、InitializingBean
、DisposableBean
等接口或注解实现扩展。
Q2: Spring 是如何解决循环依赖的?
Spring 使用三级缓存机制,在创建 Bean 的过程中提前暴露一个工厂对象,避免重复创建导致死循环。但仅支持单例 Bean,并且不能处理构造函数注入的循环依赖。
Q3: Spring 是如何实现依赖注入的?
Spring 通过反射机制,读取
@Autowired
、@Resource
等注解,找到对应的依赖对象并注入。底层使用Field.set()
或Method.invoke()
实现。
✅ 总结
特性 | Spring IoC 实现 |
---|---|
控制反转 | 将对象创建交给容器管理 |
依赖注入 | 支持字段、构造器、Setter 注入 |
Bean 生命周期 | 完整的初始化、销毁流程 |
循环依赖 | 使用三级缓存机制解决单例 Bean 循环依赖 |
扩展机制 | 提供多种扩展点(BeanFactoryPostProcessor、BeanPostProcessor) |