IOC简介

IOC的背景 

传统模式下,当一个对象需要调用另一个对象的方法或者获取其属性值时,就形成了功能依赖。这种依赖关系会导致对象之间的耦合。在一个较为复杂的系统中,,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系。

IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦。

当我们去掉IOC容器之后我们可以看到,这时候,A、B、C、D这4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。

IOC 

IOC就是控制反转,通俗的说就是我们不用自己创建实例对象,这些都交给Spring的bean工厂帮我们创建管理。这也是Spring的核心思想,通过面向接口编程的方式来是实现对业务组件的动态依赖。这就意味着IOC是Spring针对解决程序耦合而存在的。

DI

依赖注入(Dependency Injection)是IOC容器的核心概念之一。它指的是将一个对象的依赖关系注入到另一个对象中,而不是由对象自己创建或查找依赖。通过依赖注入,IOC容器负责解决对象之间的依赖关系,将依赖的对象自动注入到需要的地方。比如说@Autowired。

通常,依赖注入可以通过三种方式完成,即:

  • 构造函数注入
  • setter 注入
  • 接口注入

IOC容器

Bean

Bean 是指由 Spring 容器管理的对象。Bean 是应用程序的组件或对象,可以是任何普通的 Java 对象(POJO),也可以是通过特定的注解或配置定义的特殊对象。

Bean的作用域

  • Singleton(单例):在 Spring IoC 容器中,每个 Singleton Bean 只有一个实例,它在整个应用程序的生命周期内都是有效的。默认情况下,所有没有指定作用域的 Bean 都是单例的。
  • Prototype(原型):Prototype Bean 每次被请求时都会创建一个新的实例。每个请求都会得到一个独立的 Bean 实例。
  • Request(请求):Request Bean 在 Web 应用程序中使用,它表示每个 HTTP 请求都会创建一个新的实例。Request Bean 的生命周期仅限于当前 HTTP 请求的处理过程中。
  • Session(会话):Session Bean 也是在 Web 应用程序中使用的,它表示每个用户会话(Session)都会创建一个新的实例。
  • Global-session(全局会话):Global-session Bean 类似于标准的 HTTP Session 作用域,但仅在基于 Portlet 的 Web 应用程序中有意义。

Bean的存储

Spring 容器使用数据结构Map来存储和管理 Bean 对象。

BeanFactory

BeanFactory(bean工厂) 是一个抽象接口,定义了获取和管理 Bean 的基本方法。

DefaultListableBeanFactory:这是 BeanFactory 接口的主要实现类,也是 Spring 容器的默认实现。它可以从配置文件或注解中读取 Bean 的定义,并负责创建、初始化和管理 Bean 对象。

当 Spring 应用程序启动时,会创建一个 BeanFactory 实例来管理应用程序中的 Bean。这通常发生在应用程序的入口点,例如在 Spring Boot 的启动类中。 

Bean的生命周期

  • 实例化阶段:在实例化阶段,Spring 容器根据配置信息或注解创建 Bean 的实例。这通常是通过调用类的构造函数来完成的。
  • 属性注入阶段:在实例化完成后,Spring 容器将相关的属性值注入到 Bean 实例中。这可以通过构造函数注入、Setter 方法注入或字段注入来实现。
  • 初始化阶段:在属性注入完成后,Spring 容器会调用 Bean 的初始化方法来执行自定义的初始化逻辑。
  • 使用阶段:初始化完成后,Bean 可以被应用程序使用。
  • 销毁阶段:当应用程序关闭或 Spring 容器关闭时,容器会调用 Bean 的销毁方法来执行清理操作。可以使用 @PreDestroy 注解或实现 DisposableBean 接口的 destroy() 方法来定义销毁逻辑。

循环依赖与解决

构造器的循环依赖:

当两个Bean之间存在构造器的循环依赖时,Spring无法处理该情况,并会抛出BeanCurrentlyInCreationException异常。这是因为在构造器注入时,需要同时实例化所有的依赖关系,但由于循环依赖,无法解决依赖关系。

单例模式下的setter循环依赖:

在单例模式下,当两个Bean之间存在setter方法的循环依赖时,Spring使用"三级缓存"来处理该问题。"三级缓存"是指在Bean实例化的过程中,Spring使用三个不同的缓存区域来存储Bean的创建状态,以解决循环依赖。

通过使用"三级缓存",Spring能够解决setter方法循环依赖问题。

  • 第一级缓存:用于存储正在创建的Bean的引用,如果发现循环依赖,则返回缓存中的Bean引用。
  • 第二级缓存:用于存储已经创建完成但尚未初始化的Bean。
  • 第三级缓存:用于存储已经初始化完成的Bean。

非单例循环依赖:

对于非单例的Bean,Spring无法处理循环依赖。因为在非单例模式下,每次获取Bean都会创建一个新的实例,不同于单例模式下只创建一次。这种情况下,Spring无法确定何时创建哪个Bean实例,因此无法解决循环依赖。

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值