Spring框架中的IoC(控制反转)

什么是IoC

百度百科:

控制反转 (Inversion of Control,缩写为IoC ),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入 (Dependency Injection,简称DI),还有一种方式叫"依赖查找"(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

简单来说,IoC是一种设计思想,它的目的是为了解耦。它的目的是为简化我们在开发过程中自我创建、管理对象的过程。

存在以下常见场景:

  • 存在一个模块需要被多个服务使用。

  • MVC架构中一个服务层可能依赖多个数据访问层。

  • 资源复用,例如:数据库连接池,线程池。

上述这些场景中本质上都是对于资源的重复创建使用,对于这种形式可能会出现下图中的情况:

对象间的依赖关系因系统复杂度提升变得越来越复杂,可能会出现多重依赖等问题。

为了解决解决该问题,我们引入IoC控制反转这种设计思想。在Spring框架中,IoC通过依赖注入(Depedency Injection,DI)的方式实现。

通过引入IoC我们的资源管理将变成下图所示的形式:

我们将对象的控制权交给IoC容器,通过容器控制对象的生命周期。


DI(依赖注入)

通过 DI(依赖注入) 实现 IoC 控制反转,通过将对象的依赖关系交由外部容器管理,解决代码耦合问题。核心思想是:对象不需要主动创建或者去查找依赖,而是直接接受容器注入的依赖即可。

依赖注入 的三种实现方式

  • Setter注入:通过Setter方法注入依赖(XML配置或@Autowired)注解。

  • 构造器注入:通过构造函数注入。

  • 字段注入:通过反射注入字段(@Autowird)。

DI 的实现原理

  1. 扫描 BeanDefinition:容器启动时扫描所有 Bean 的定义(XML、注解、Java 配置)。

  2. 创建 Bean 实例:通过反射或工厂方法实例化 Bean。

  3. 注入依赖:根据依赖类型或名称查找匹配的 Bean,递归完成所有依赖的注入。

  4. 初始化 Bean:调用 @PostConstruct 方法或实现 InitializingBean 接口。

三级缓存 机制

通过引入三级缓存机制解决循环依赖问题。

循环依赖指的是:A需要依赖B,B需要依赖A,出现这种互相依赖的情况。

缓存级别 存储内容 作用
一级缓存 完全初始化后的单例 Bean 直接提供可用 Bean
二级缓存 早期暴露的 Bean(未完成属性填充) 解决循环依赖
三级缓存 Bean 工厂(用于生成早期对象) 延迟创建代理对象(如 AOP 场景)

流程:

  1. 创建 A 实例(未填充属性)→ 放入三级缓存。

  2. 填充 A 的属性时发现依赖 B → 创建 B 实例。

  3. 填充 B 的属性时发现依赖 A → 从三级缓存获取 A 的工厂,生成早期对象并放入二级缓存。

  4. B 完成初始化 → 放入一级缓存。

  5. A 继续填充 B 的依赖 → 完成初始化并放入一级缓存。


Spring IoC 的工作流程

1、 容器初始化

  • 加载配置(XML/注解),生成 BeanDefinition。

  • 注册 BeanPostProcessor(扩展点,如 AOP 代理)。

  • 预实例化单例 Bean(非懒加载)。

2、Bean 生命周期

  • 实例化:反射或工厂方法创建对象。

  • 属性填充:注入依赖(DI)。

  • 初始化:执行 @PostConstruct、InitializingBean 等方法。

  • 销毁:调用 @PreDestroy 或 DisposableBean 方法。

0. BeanDefinition

通过BeanDefinition获取Bean的定义信息。

1. 构造函数

通过构造函数实例化Bean。

2. 依赖注入

进行Bean的依赖注入。

3. Aware接口

处理Aware接口:

  • BeanNameAware:获取Bean的名称。

  • BeanFactoryAware:获取Bean工厂。

  • ApplicationContextAware:获取容器上下文对象。

4. BeanPostProcessor#before

Bean前置处理器。

5. 初始化方法
6. BeanPostProcessor#after

Bean后置处理器,可以在内部通过AOP进行动态代理,增强Bean。

7. 销毁Bean

3、扩展机制

  • BeanPostProcessor:在 Bean 初始化前后插入逻辑(如 AOP)。

  • BeanFactoryPostProcessor:修改 BeanDefinition(如占位符替换)。

相关推荐
self-discipline6341 小时前
【Java】Java核心知识点与相应面试技巧(七)——类与对象(二)
java·开发语言·面试
wei3872452321 小时前
java笔记02
java·开发语言·笔记
zjj5871 小时前
Docker使用ubuntu
java·docker·eureka
士别三日&&当刮目相看1 小时前
JAVA学习*简单的代理模式
java·学习·代理模式
ShareBeHappy_Qin2 小时前
设计模式——设计模式理念
java·设计模式
yuluo_YX4 小时前
使用 Spring AI Aliabab Module RAG 构建 Web Search 应用
前端·人工智能·spring
程序猿大波4 小时前
基于Java,SpringBoot,Vue,HTML高校社团信息管理系统设计
java·vue.js·spring boot
小李同学_LHY5 小时前
微服务架构中的精妙设计:环境和工程搭建
java·spring·微服务·springcloud
慕容魏5 小时前
面经分享,中科创达(安卓开发,二面挂)
java·开发语言
不辉放弃5 小时前
Java/Scala是什么
java·scala