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(如占位符替换)。

相关推荐
橘猫云计算机设计1 小时前
基于Springboot的自习室预约系统的设计与实现(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·毕业设计
秋书一叶2 小时前
SpringBoot项目打包为window安装包
java·spring boot·后端
碎梦归途2 小时前
23种设计模式-结构型模式之外观模式(Java版本)
java·开发语言·jvm·设计模式·intellij-idea·外观模式
极客先躯2 小时前
高级java每日一道面试题-2025年4月13日-微服务篇[Nacos篇]-Nacos如何处理网络分区情况下的服务可用性问题?
java·服务器·网络·微服务·nacos·高级面试
pwzs2 小时前
Spring MVC 执行流程全解析:从请求到响应的七步走
java·后端·spring·spring mvc
我该如何取个名字3 小时前
Mac配置Java的环境变量
java·开发语言·macos
kkkkatoq3 小时前
Java中的锁
java·开发语言
界面开发小八哥3 小时前
「Java EE开发指南」用MyEclipse开发EJB 3无状态会话Bean(二)
java·ide·java-ee·eclipse·myeclipse
LCY1333 小时前
spring security +kotlin 实现oauth2.0 认证
java·spring·kotlin
soulermax3 小时前
数字ic后端设计从入门到精通2(含fusion compiler, tcl教学)
java·linux·服务器