面试官:Spring 启动过程是什么样的?详细讲讲你自己的理解!

引言:在面试中,对于 Java 开发者来说,掌握 Spring 框架的原理和使用是至关重要的。其中,了解 Spring 的启动流程、循环依赖问题的解决方法以及与设计模式相关的内容是常见的面试题目。

题目

面试官:Spring 启动过程是什么样的?详细讲讲你自己的理解!

推荐解析

启动流程

1)加载配置文件

Spring 启动时会加载应用程序的配置文件,通常是 applicationContext.xml 或者通过 Java Config 配置类。这些配置文件包含了 Spring Bean 的定义、依赖关系、AOP 设置、事务管理器等信息。

2)创建并初始化 Spring 容器

一旦配置文件加载完成,Spring 将会创建并初始化一个 Spring 容器(ApplicationContext)。Spring 容器负责管理应用程序中的所有 Bean,以及它们之间的依赖关系。容器的初始化包括实例化 Bean、注入依赖、应用 AOP 等。

3)扫描组件

Spring 容器会扫描配置文件中指定的包,查找带有特定注解的组件类,如 @Component@Service@Repository@Controller。一旦找到这些组件类,Spring 将会实例化它们并将它们纳入容器管理。

4)实例化 Bean

Spring 容器会根据配置文件中的定义,实例化所有的 Bean。这些 Bean 可能是普通的 POJO 类、数据访问对象(DAO)、服务类等。

5)注入依赖

在实例化 Bean 的过程中,Spring 容器会解析 Bean 之间的依赖关系,并将依赖的 Bean 注入到需要它们的 Bean 中。这个过程可以通过构造函数注入、Setter 方法注入或者字段注入来完成。

6)应用 AOP

如果应用程序中使用了 AOP(面向切面编程),Spring 将会应用切面逻辑,为 Bean 动态生成代理,并将切面逻辑织入到相应的 Bean 中。这个过程包括创建代理对象、将切面逻辑织入到代理对象中等。

7)触发生命周期回调

Spring 容器会在 Bean 实例化、依赖注入完成以及其他初始化工作完成后,触发相应 Bean 的生命周期回调方法,如 InitializingBean 接口的 afterPropertiesSet() 方法、@PostConstruct 注解标注的方法等。

8)完成启动

一旦所有的 Bean 实例化、依赖注入和初始化工作完成,Spring 容器就会完成启动过程,应用程序就可以开始处理请求和响应了。

经典面试题

怎么知道 Spring 的 Bean 加载完成?

使用 ApplicationListener 监听容器启动事件

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 在容器启动完成后执行操作
        System.out.println("Spring容器已启动,所有Bean加载完成");
    }
}

使用 @EventListener 注解监听容器启动事件

import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventListener {
    
    @EventListener
    public void handleContextRefresh(ContextRefreshedEvent event) {
        // 在容器启动完成后执行操作
        System.out.println("Spring容器已启动,所有Bean加载完成");
    }
}
Spring 的 IOC 用到了 哪些设计模式?
  1. 依赖注入(Dependency Injection):在Spring IOC中,通过将对象之间的依赖关系交由IOC容器来处理,实现了松耦合和高度可测试性。
  2. 工厂模式(Factory Pattern):在Spring IOC中,BeanFactory就是一个工厂类,用于创建和管理Bean实例。
  3. 单例模式(Singleton Pattern):在Spring IOC中,默认情况下所有Bean都是单例的,并且可以通过配置控制是否启用单例模式。
  4. 模板方法模式(Template Method Pattern):在Spring AOP中,通过定义抽象切面类和具体实现类来实现切面逻辑复用。
  5. 观察者模式(Observer Pattern):在Spring事件机制中,观察者监听某个事件源发生的事件,并进行相应的处理。
  6. 策略模式(Strategy Pattern):在Spring MVC中,通过定义多个HandlerMapping策略来实现URL到Controller映射。

其他补充

鱼聪明 AI 的回答:

鱼聪明 AI 地址:https://www.yucongming.com/

Spring 解决循环依赖问题的主要方法是通过三级缓存(three-level cache)和“提前暴露”(early exposure)的机制。

三级缓存

Spring 在创建 Bean 的过程中,会维护三级缓存,分别是 singletonObjects、earlySingletonObjects 和 singletonFactories。这三级缓存的作用如下:

  1. singletonObjects: 存放已经完全初始化的单例 Bean 实例。
  2. earlySingletonObjects: 存放已经实例化但未完全初始化的单例 Bean 实例。
  3. singletonFactories: 存放 Bean 工厂对象,用于解决循环依赖问题。

提前暴露

Spring 在创建 Bean 的过程中,会提前暴露尚未完全初始化的 Bean 实例,以便解决循环依赖问题。在处理循环依赖时,Spring 遵循以下步骤:

  1. 当容器需要获取 A 类型的 Bean 实例时,如果发现 A 还未创建,则创建一个 A 类型的 Bean 对象,并将其放入 earlySingletonObjects 缓存中,表示 A 已经实例化但未完全初始化。
  2. 接着创建 A 类型 Bean 的依赖 Bean,如果发现某个依赖 Bean 依赖于 A,则会从 earlySingletonObjects 缓存中提前暴露 A 的代理对象(尚未完全初始化)给依赖 Bean。
  3. 当 A 类型 Bean 的初始化完成后,将其放入 singletonObjects 缓存中,表示 A 已经完全初始化。
  4. 最后,再将 A 的代理对象替换为完全初始化的 A 实例。

这样一来,通过提前暴露尚未完全初始化的 Bean 实例,Spring 能够在循环依赖的情况下确保每个 Bean 都能够得到正确的依赖实例。

示例

假设有两个类 A 和 B,彼此相互依赖:

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
}

public class B {
    private A a;

    public B(A a) {
        this.a = a;
    }
}

在这种情况下,Spring 会通过三级缓存和提前暴露的机制解决循环依赖问题,确保 A 和 B 都能够正确地获取到彼此的实例。

欢迎交流

本文主要讲述 Spring 启动流程,和两个经典面试题,关于 Spring 循环依赖问题,可以去看下三级缓存的源码进行具体分析,在文末还有三个问题,欢迎小伙伴在评论区留言!

1)Spring 中的 Bean 生命周期是怎样的?

2)Spring 中的依赖注入方式有哪些?它们之间有什么区别?

3)在 Spring 中如何实现事务管理?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/677714.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Element-ui使用上传时弹框选择文件类型

实现效果 1&#xff0c;点击上传&#xff0c;上传文件&#xff1b; 2&#xff0c;选择文件&#xff1b; 3&#xff0c;弹框选择文件类型&#xff1b; 4&#xff0c;选择类型后确定上传&#xff1b; 一&#xff0c;上传 跳过&#xff1b; 二&#xff0c;定义弹框下拉框…

这么好看的AI摄影写真,用Stable Diffusion 即可轻松完成,想要什么风格都可以!

大家好&#xff0c;我是向阳。 今天给大家分享一下如何用AI绘画工具Stable Diffusion 制作摄影奇幻写真&#xff0c;本次教程很简单&#xff0c;跟着我&#xff0c;你也能快速上手&#xff01;学会了&#xff0c;就去尝试生成一套自己的AI写真吧 AI工具Stable Diffusion 和 教…

Python 实现反转密码加密

反转密码加密是通过反向输出消息进行加密。如&#xff0c;‘Hi,boy!’通过反转加密就会变成 ‘!yob,iH’。加解密的过程是一样的&#xff0c;解密是需要将密文再次反转过来既可以得到原文内容了。 反转加密是一种比较弱的加密方式&#xff0c;一般我们通过一些密文既可以发现它…

【简单学习一下卷积神经网络】-基于肆十二的高考例子

前言一、白话卷积神经网络总结 前言 【参考】 主要是P2⇨手把手教你用tensorflow2训练自己的数据集 -------2024/5/4 一、白话卷积神经网络 高考前需要大量的做题训练---->相当于数据集。 做题过程中【于标准答案进行比对】产生的错题⇨loss&#xff08;误差&#xff09; 回…

RaspAP:轻松实现树莓派无线 AP

RaspAP 是一个可以将树莓派轻松部署成无线 AP&#xff08;Access Point&#xff09;的软件方案&#xff0c;具有一套响应式的 WebUI 来控制 WiFi&#xff0c;用起来和家用路由器一样方便。RaspAP 可以运行在 Raspbian 上&#xff0c;只需要先给树莓派安装好 Raspbian 系统&…

LeetCode-3067. 在带权树网络中统计可连接服务器对数目【树 深度优先搜索 数组】

LeetCode-3067. 在带权树网络中统计可连接服务器对数目【树 深度优先搜索 数组】 题目描述&#xff1a;解题思路一&#xff1a;dfs&#xff0c;针对当前服务器i有for i, gi in enumerate(g):&#xff0c;不断dfs其的邻居节点for y, wt in gi:&#xff0c;dfs可以计算得到邻居y的…

解决 windows11 文件夹中右键没有出现Git Bash Here的问题?

电脑刚从w10升级到了w11&#xff0c;想要从git拉去项目&#xff0c;但是发现右键菜单下找不到git&#xff0c;如图&#xff1a; 百度了一下&#xff0c;看了看这位大佬 这篇文章 的配置&#xff0c;确实能打开&#xff0c;但右键菜单下还是没有&#xff0c;于是继续搜寻问题的…

Kimichat使用案例008:查找比亚迪、特斯拉等电动车产业链相关股票(用kimichat炒股)

文章目录 一、介绍二、Kimi操作内容三、Kimi输出内容四、kimi操作内容五、Kimi输出内容一、介绍 kimichat可以联网检索,搜索结果更加准确、智能。 二、Kimi操作内容 在kimichat中输入提示词: 找出同时在比亚迪产业链和特斯拉产业链的企业 三、Kimi输出内容 四、kimi操作内容…

成功解决“ModuleNotFoundError: No module named ‘tensorflow_datasets‘”错误的全面指南

成功解决“ModuleNotFoundError: No module named ‘tensorflow_datasets’”错误的全面指南 在Python编程和深度学习项目中&#xff0c;tensorflow_datasets&#xff08;通常简称为tfds&#xff09;是一个非常重要的库&#xff0c;它提供了大量现成的数据集&#xff0c;方便…

日本指数实时API接口

日本 指数 实时API接口 # Restful API https://tsanghi.com/api/fin/index/JPN/realtime?token{token}&ticker{ticker}指定指数代码&#xff0c;获取该指数的实时行情&#xff08;开、高、低、收、量&#xff09;。 更新周期&#xff1a;实时。 请求方式&#xff1a;GET。…

【ARM Cache 与 MMU 系列文章 7.7 – ARMv8/v9 MMU Table 表分配原理及其代码实现 1】

文章目录 MMU Table 表分配原理及其代码实现虚拟地址空间 Region的配置系统物理地址位宽获取 MMU Table 表分配原理及其代码实现 假设当前系统中需要映射多个region&#xff0c;其中第一个要映射的region虚拟地址范围是0x0000_0000 -- 0x8000_0000 一共2G的大小。MMU默认最大支…

探索大模型技术及其前沿应用——TextIn文档解析技术

前言 中国图象图形大会&#xff08;CCIG 2024&#xff09;于近期在西安召开&#xff0c;此次大会将面向开放创新、交叉融合的发展趋势&#xff0c;为图像图形相关领域的专家学者和产业界同仁&#xff0c;搭建一个展示创新成果、展望未来发展&#xff0c;集高度、深度、广度三位…

劳动仲裁避坑指南(收集证据仲裁流程)

前言&#xff1a; 常在河边走&#xff0c;哪能不挨刀。 在大环境不好的滚滚洪流中&#xff0c;老实的IT打工人&#xff0c;一波波的被裁员。随时准备一些材料&#xff0c;特附上准备清单。 参考一些资料&#xff1a;2023年A股上市公司&#xff0c;裁员榜&#xff1a;1、 中国…

el-table动态配置显示表头

在实际工作中&#xff0c;会遇到动态配置e-table表头的情况&#xff0c;如下方法可以实现&#xff1a; // 要展示的列 column: [{prop: name, name: 名称 }, {prop: age, name: 年龄 }, {prop: sex, name: 性别 }, {prop: address, name: 地址 }, {prop: city, name: 城市 }]…

UFS协议—新手快速入门(二)【5-6】

目录 五、UFS协议栈 六、UFS技术演进与详解 1、UFS应用层 设备管理器 任务管理器 2、UFS传输层 3、UFS互联层 UFS协议—新手快速入门&#xff08;一&#xff09;【1-4】 五、UFS协议栈 UFS&#xff08;Universal Flash Storage&#xff09;协议是针对固态存储设备&…

【面试干货】 非关系型数据库(NoSQL)与 关系型数据库(RDBMS)的比较

【面试干货】 非关系型数据库&#xff08;NoSQL&#xff09;与 关系型数据库&#xff08;RDBMS&#xff09;的比较 一、引言二、非关系型数据库&#xff08;NoSQL&#xff09;2.1 优势 三、关系型数据库&#xff08;RDBMS&#xff09;3.1 优势 四、结论 &#x1f496;The Begin…

深圳比创达|EMC与EMI测试整改:确保设备电磁兼容性的关键步骤

在当今电子产品日益普及的时代&#xff0c;电磁兼容性&#xff08;EMC&#xff09;已成为产品设计、制造和测试过程中不可忽视的重要环节。EMC问题不仅影响设备的正常运行&#xff0c;还可能对周围环境和其他设备产生干扰。因此&#xff0c;进行EMC与EMI&#xff08;电磁干扰&a…

【python】修改目标检测的xml标签(VOC)类别名

需求&#xff1a; 在集成多个数据集一同训练时&#xff0c;可能会存在不同数据集针对同一种目标有不同的类名&#xff0c;可以通过python脚本修改数据内的类名映射&#xff0c;实现统一数据集标签名的目的。 代码&#xff1a; # -*- coding: utf-8 -*- # Time : 2023/9/11 1…

EE trade:通缩下什么最保值

通缩&#xff0c;即物价水平总体持续下降的现象&#xff0c;会对经济和投资产生深远影响。在通缩环境下&#xff0c;持有的资产类型和策略需要做出相应调整&#xff0c;以确保资产的保值和增值。以下是几类在通缩环境下通常最保值的资产及其原因&#xff1a; 1. 现金和现金等价…

二十三、 企业可能涉及的数据跨境传输场景有哪些?

&#xff08;一&#xff09;人力资源数据出境场景 1. 公司招聘&#xff08;应聘者个人信息出境&#xff09; 以外企为例&#xff0c;在公司招聘的过程中&#xff0c;可能被认定为涉及数据出境的典型场景如下&#xff1a; a) 境外总部企业官网统一招聘员工&#xff0c;由应聘…