八股训练营第 39 天 | Bean 的作用域?Bean 的生命周期?Spring 循环依赖是怎么解决的?Spring 中用到了那些设计模式?

Bean 的作用域?

Spring IoC 容器的对象称之为 Bean。Bean 的作用域就是对象在应用程序中的生命周期和可见范围,通常有以下几种类型:

  1. 单例:是默认的作用域。如果一个 Bean 的作用域为 Singleton,那么 IoC 容器中只会存在一个共享的 Bean 实例。当对 Bean 进行请求时,如果 ID 与该 Bean 定义相匹配,那么会返回同一个 Bean 实例。
  2. 原型:如果一个 Bean 的作用域为 Prototype,那么一个 Bean 会对应多个实例对象。每次对该 Bean 的请求都会创建一个新的 Bean 实例。
  3. 请求:一个 HTTP 请求对应一个 Bean 实例。每个 HTTP 请求都会创建一个新的 Bean 实例。且该 Bean 仅在请求期间有效。
  4. 会话:一个 HTTP 会话对应一个 Bean 实例。Bean 的生命周期与会话的生命周期相同。
  1. 应用程序:对于定义在 ServletContext中的 Bean,整个 Web 应用程序共享一个 Bean 实例。
  2. Websocket:WebSocket生命周期内,每个 WebSocket 会话拥有一个 Bean 实例。

Bean的生命周期?

Bean 的生命周期,就是 Bean 从创建到销毁的整个过程,包含以下几个步骤:

  1. 实例化 Bean:Spring 容器通过构造器或者工厂方法创建 Bean 实例。
  2. 设置属性:容器注入 Bean 的属性。这些属性可能是其他 Bean 的引用,也可以是一些简单的配置值。
  3. 检查 Aware 接口并设置相关依赖:如果 Bean 实现了 BeanNameAware 或 BeanFactoryAware 接口,容器会调用相应的 setBeanName 或 setBeanFactory 方法。
  4. BeanPostProcessor:在 Bean 的属性设置完毕之后,容器会调用所有注册了 BeanPostProcessor 的 postBeanBeforeInitialization 方法。
  5. 初始化 Bean:如果 Bean 实现了 InitializingBean 接口,容器会调用 afterPropertiesSet 方法;如果 Bean 定义了 init-method,那么容器也会调用这个方法。
  6. BeanPostProcessor 的二次调用:容器会再次调用所有注册了 BeanPostProcessor 的 postBeanAfterInitialization 方法。这是在初始化 Bean 之后调用的。
  7. 使用 Bean:此时 Bean 已经设置完毕,可以被应用程序所使用。
  8. 处理 DisposableBean 和 destroy-method:当容器关闭时,如果 Bean 实现了 DisposableBean 接口,则容器会调用相应的 destroy 方法;如果 Bean 定义了 destroy-method,容器也会调用这个方法。
  9. Bean 销毁:最后,Bean 被 Spring 容器销毁,结束了它的生命周期。

Spring 循环依赖是怎么解决的?

  1. 什么是循环依赖

    循环依赖是指两个或者两个以上的 Bean 互相持有对方,最终形成闭环。比如 Bean A 依赖于 Bean B,Bean B 又依赖于 Bean A。

  2. 如何解决

  • 字段注入或 Setter 注入:使用三级缓存来解决循环依赖。
    • 首先,Spring 容器会实例化一个 Bean(这个 Bean 是已通过构造器创建,但属性尚未填充),然后注册一个 singletonFactory 到三级缓存,这个工厂会在需要时返回该 Bean 的早期引用。
    • 当为该 Bean 填充属性时,如果属性依赖其他 Bean,而其他 Bean 又依赖当前 Bean,就会尝试从缓存中获取当前 Bean。优先从一级缓存获取完全初始化的 Bean。如果未找到,就尝试从二级缓存获取该 Bean 的早期引用。如果也未找到,就调用三级缓存中的工厂,生成早期引用并放入二级缓存。
    • 当 Bean 的属性填充和初始化全部完成后,就会把完全初始化的 Bean 放入一级缓存中,并清理掉在二级、三级缓存中的临时引用。
  • 构造器注入:Spring 容器无法解决构造器注入造成的循环依赖。但是可以使用 @Lazy 懒加载方法,延迟 Bean 的加载。知道它被实际使用时才创建。

① 一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的 Bean 对象

② 二级缓存:缓存早期的 Bean 对象(生命周期还没走完)

③ 三级缓存:缓存的是 ObjectFactory,表示对象工厂,用来创建某个对象的

Spring 中用到了那些设计模式?

  1. 工厂设计模式:Spring 使用工厂设计模式,通过 BeanFactory 和 ApplicationContext 创建 Bean 对象。
  2. 代理设计模式:Spring AOP 就是代理功能实现。
  3. 单例设计模式:Spring 中的 Bean 默认是单例的。
  4. 模板方法模式:Spring 中的 jdbcTemplate、hiberateTemplate 等以 Template 结尾的操作数据库的类,它们就采用了模板模式。
  5. 包装器设计模式:我们的项目会连接多个数据库,不同的客户每次访问会根据需要访问不同的数据库,这种模式可以让我们根据客户的需求动态切换不同的数据源。
  6. 观察者模式:Spring 中的事件驱动模型就是观察者模式很经典的一个应用。
  7. 适配器模式:Spring AOP 的增强和通知使用到了适配器模式。Spring MVC 也使用适配器模式来适配 Controller。
相关推荐
洲星河ZXH10 分钟前
Java,泛型
java·开发语言·windows
海南java第二人13 分钟前
SpringBoot循环依赖全解:从根源到解决方案的深度剖析
java·spring
CopyProfessor13 分钟前
Java Agent 入门项目模板(含代码 + 配置 + 说明)
java·开发语言
duansamve16 分钟前
VSCode中如何搭建JAVA+MAVEN开发环境?
java·vscode·maven
Elias不吃糖18 分钟前
Java Collection 体系与使用场景整理
java·学习笔记·map·collection
一颗青果20 分钟前
c++的异常机制
java·jvm·c++
小码过河.20 分钟前
设计模式——命令模式
设计模式·命令模式
小豪GO!21 分钟前
操作系统-八股
java
爱吃山竹的大肚肚22 分钟前
达梦(DM)数据库中设置表空间
java·数据库·sql·mysql·spring·spring cloud·oracle
Geek攻城猫31 分钟前
Java 实现大文件上传与断点续传:原理、实践与优化
java