当前位置: 首页 > news >正文

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 功能
ApplicationContextBeanFactory 的子接口,提供更多企业级功能(如 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 生命周期步骤

  1. 加载 BeanDefinition
    • 从 XML、注解或 Java Config 中解析出 Bean 的元数据。
  2. 实例化 Bean
    • 调用构造函数创建 Bean 对象(此时还未赋值属性)
  3. 填充属性(依赖注入)
    • 根据配置自动装配依赖(@Autowired、set 方法等)
  4. 设置 BeanName、BeanFactory、ApplicationContext 等
    • 实现 BeanNameAware, BeanFactoryAware 接口的方法回调
  5. 调用 BeanPostProcessor.beforeInitialization()
  6. 调用初始化方法
    • @PostConstruct
    • InitializingBean.afterPropertiesSet()
    • 自定义 init-method
  7. 调用 BeanPostProcessor.afterInitialization()
  8. 使用 Bean
  9. 销毁 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 通过 BeanFactoryApplicationContext 来管理 Bean 的创建、依赖注入、初始化、销毁等全过程。通过 BeanPostProcessorInitializingBeanDisposableBean 等接口或注解实现扩展。

Q2: Spring 是如何解决循环依赖的?

Spring 使用三级缓存机制,在创建 Bean 的过程中提前暴露一个工厂对象,避免重复创建导致死循环。但仅支持单例 Bean,并且不能处理构造函数注入的循环依赖。

Q3: Spring 是如何实现依赖注入的?

Spring 通过反射机制,读取 @Autowired@Resource 等注解,找到对应的依赖对象并注入。底层使用 Field.set()Method.invoke() 实现。


✅ 总结

特性Spring IoC 实现
控制反转将对象创建交给容器管理
依赖注入支持字段、构造器、Setter 注入
Bean 生命周期完整的初始化、销毁流程
循环依赖使用三级缓存机制解决单例 Bean 循环依赖
扩展机制提供多种扩展点(BeanFactoryPostProcessor、BeanPostProcessor)
http://www.xdnf.cn/news/323803.html

相关文章:

  • Linux NVIDIA 显卡驱动安装指南(适用于 RHEL/CentOS)
  • 低代码 x AI,解锁数智化应用的创新引擎
  • Spark-Core(RDD行动算子)
  • C++回调函数学习
  • C++回顾 Day5
  • VRM Add-on for Blender 学习笔记
  • 如何测试 esp-webrtc-solution_solutions_doorbell_demo 例程?
  • C++ 继承
  • 文章记单词 | 第68篇(六级)
  • Synthetic Data Kit:LLM微调的语料提炼方案
  • iPhone 和 Android 在日期格式方面的区别
  • 前端日常 · 移动端网页调试
  • c++混淆工具Hikari-LLVM15-llvm-18.1.8rel编译安装
  • Android 蓝牙开发调试总结
  • 多模态学习(一)——从 Image-Text Pair 到 Instruction-Following 格式
  • Java学习手册:数据库事务相关知识
  • 护照阅读器简介
  • 算法导论第7章思考题
  • 16.Three.js 中的 RectAreaLight 全面详解 + Vue 3 实战案例
  • 动态规划之01背包——三道题助你理解01背包
  • 深入浅出之FPN (Feature Pyramid Networks for Object Detection)
  • vue3 element-plus 输入框回车跳转页面问题处理
  • 拒绝服务攻击(DoS/DDoS/DRDoS)详解:洪水猛兽的防御之道
  • 嵌入式学习--江协51单片机day2
  • 基于英特尔 RealSense D455 结构光相机实现裂缝尺寸以及深度测量
  • STM32基础教程——硬件SPI
  • OpenMVS 的编译与运行
  • 2025年链游行业DDoS与CC攻击防御全解析:高带宽时代的攻防博弈
  • 算法-时间复杂度和空间复杂度
  • 【Python 函数】