SpringBoot面试题整理(1)
面试整理
前置知识
- ApplicationContextInitializer
- ApplicationListener
- BeanFactory
- BeanDefinition
- BeanFactoryPostProcessor
- Aware
- InitializingBean/DisposableBean
- BeanPostProcessor
面试题
- SpringBoot启动流程
- IOC容器初始化流程
- Bean声明周期
- Bean循环依赖
- SpringMVC执行流程
ApplicationContextInitializer
- IOC容器对象创建完成后执行,可以对上下文环境做一些操作,例如运行环境属性注册等
- 如何使用
- 自定义,实现ApplicationContextInitializer接口
- 在MATA-INF/spring.factories配置文件中配置自定义的类
- initialize方法什么时候执行
- IOC容器对象创建完成后执行,常用语环境属性注册
ApplicationListener
- 如何使用
- 自定义类,实现ApplicationListener接口
- 在META-INF/spring-factories配置文件中配置自定义的类
- 什么时候执行
- IOC容器发布事件后执行,通常用于资源加载,定时任务发布
BeanFactory
- Bean容器的根接口,提供Bean对象的创建、配置、依赖注入等功能



- ApplicationConfigServletServerApplicationContext->DefaultListableBeanFactory
BeanDefinition
- 用于描述Bean,包括Bean的名称,Bean的属性,Bean的行为,实现的接口,添加的注解等,Spring中,Bean在创建之前,都需要封装成对应的BeanDefinition,然后根据BeanFinition进一步创建Bean对象


BeanFactoryPostProcessor
- Bean工厂后置处理器,当BeanFactory准备好了后(Bean初始化前),会调用该接口的postProcessBeanFactory方法,经常用于新增BeanDefinition
| 实现类名 | 作用 |
|---|---|
| ConfigurationClassPostProcessor | 扫描启动类下所在包下的注解 |
| ServletComponentRegisteringPostProcessor | 扫描@WebServler、@WebFilter、@WebListener |
| CachingMetadataReaderFactoryPostProcessor | 配置ConfiguraitonClassPostProcessor |
| ConfigurationWarningsPostProcessor | 配置警告提示 |

Aware
-
感知接口,Spring提供的一种机制,通过实现该接口,重写方法,可以感知Spring应用程序执行过程中的一些变化。Spring会判断出当前的Bean有没有实现Aware接口,如果实现了,会在特定的时机回调接口对应的方法
子接口名 作用 BeanNameAware Bean名称的感知接口 BeanClassLoaderAware Bean类加载器的感知接口 BeanFactoryAware Bean工厂的感知接口 
InitializingBean/DisposableBean
-
初始化接口,当Bean被实例化好后,会回调里面的函数,经常用于做一些加载资源的工作
-
销毁接口,当Bean被销毁执之前,会回调里面的函数,经常用于做一些释放资源的工作

BeanPostProcessor
- Bean的后置处理器,当Bean对象初始化之前以及初始化之后,会回调该接口对应的方法
- postProcessBeforeInitialization:Bean对象初始化之前调用
- postProcessAfterInitialization:Bean对象初始化之后调用
| 实现类名 | 作用 |
|---|---|
| AutowiredAnnotationBeanPostProcessor | 用来完成依赖注入 |
| AbstractAutoProxyCreator | 用来完成代理对象的创建 |
| AbstractAdvisingBeanPostProcessor | 将Aop中的通知作用于特定的Bean上 |

面试题
SpringBoot启动流程
- new SpringApplication()
- 确认web应用的类型
- 加载ApplicationContextInitializer
- 加载ApplicationListener
- 记录主启动类
- run()
- 准备环境对象Environment,用于加载系统属性等等
- 打印Banner
- 实例化容器Context
- 准备容器,为容器设置Environment、BeanFactoryPostProcessor,并加载主类对应的BeanDefinition
- 刷新容器(创建Bean实例)
- 返回容器


总结:
问:请聊聊SpringBoot启动的过程?
总:SpringBoot启动,其本质就是加载各种配置信息,然后初始化IOC容器并返回
分:在其启动的过程中会做这么几件事情:
首先,当我们在启动类执行SpringApplication.run这行代码的时候,在它的方法内部其实会做两件事
1.创建SpringApplication对象
2.执行run方法
其次,在创建StringApplication对象的时候,在它的构造方法内部主要做3件事情
1.确认web应用类型,一般情况下是Servlet类型,这种类型的应用,将来会自动启动一个tomcat
2.从spring.factories配置文件中,加载默认的ApplicationContextInitializer和ApplicationListener
3.记录当前应用的主启动类,将来做包的扫描使用
最后,对象创建好了以后,在调用该对象的run方法,在run方法的内部主要做4个事情
1.准备Environment对象,它里面会封装一些当前应用运行环境的参数,比如环境变量等等
2.实例化容器,这里仅仅是创建ApplicationContext对象
3.容器创建好了以后,会为容器做一些准备工作,比如为容器设置Environment、 BeanFactoryPostProcessor后置处理器,并且加载主类对应的Definition
4.刷新容器,就是我们常说的refresh,在这里会真正的创建Bean实例
总:总结一下我刚才说的,其实SpringBoot启动的时候核心就两步,创建SpringApplication对象以及run方法的调用,在run方法中会真正的实例化容器,并创建容器中需要的Bean实例,最终返回
IOC容器初始化流程
- AbstractApplicationContext.refresh()
-
准备BeanFactory(DefaultListableBeanFactory)
设置ClassLoader
设置Environment
-
扫描要放入容器中的Bean,得到对应的BeanDefinition(只扫描,并不创建)
-
注册BeanPostProcessor
-
处理国际化
-
初始化事件多播器ApplicationEventMulticaster
-
启动Tomcat
-
绑定事件监听器和事件多播器
-
实例化非懒加载的单例Bean
-
扫尾工作,比如清空实例化时占用的缓存等

总结
问:请聊一聊IOC容器初始化的流程?
总:IOC容器的初始化,核心工作时在AbstractApplicationContext.refresh方法中完成的
分:在refresh方法中主要做了这么几件事
1.准备BeanFactory,在这个一块需要给BeanFactory设置很多属性,比如类加载器、Environment等
2.执行BeanFactory后置处理器,这一阶段会扫描要放入到容器中的Bean信息,得到应用的BeanDefinition(注意,这里只扫描不创建)
3.是注册BeanPostProcessor,我们自定义的BeanPostProcessor就是在这个阶段被加载的,将来Bean地域性实例化好后需要用到的时候再创建
4.启动tomcat
5.实例化容器中实例化非懒加载的单例Bean,这里需要说的事,多例Bean和懒加载的Bean不会在这个阶段实例化,将来用到的时候再创建
6.当容器事出花完毕后,再做一些扫尾工作,比如清除缓存等
总:简单总结一下,在IOC容器初始化的过程中,首先得准备并执行BeanFactory后置处理器,其次得注册Bean后置处理器,并启动tomcat,最后需要借助于BeanFactory完成Bean的实例化
Bean循环依赖
- Bean循环依赖是指依赖闭环的问题


总结
问:请聊一聊Bean循环依赖是怎么实现的?
总:Bean的循环依赖指的是A依赖B,B又依赖A这样的依赖闭环问题。在Spring中,通过三个对象存储区来解决循环依赖问题,这三个缓存区被定义到了DefaultSingletonBeanRegistry中,分别是singletonObjects用来存储创建完毕的Bean,earlySingletonObjects用来存储未完成依赖注入的Bean,还有SingletonFactories用来存储创建Bean的ObjectFactory。假如说现在A依赖B,B依赖A,整个创建Bean的过程是这样的:
分:
首先,调用A的构造方法实例化A,当前的A还没有处理依赖注入,暂且把它称为半成品,此时会把半成品A封装到一个ObjectFactory中,并存储到springFactories缓存区
接下来,要处理A的依赖注入了,由于此时还没有B,所以得先实例化一个B,同样的,半成品B也会被封装到ObjectFactory中,并存储到springFactories缓存区
紧接着,要处理B的依赖注入了,此时会找到springFactories中A对应的objectFactorty,调用它的getObject方法得到刚才实例化的半成品A(如果需要代理对象,则会自动创建代理对象),把得到的半成品A注入给B,并同时会把半成品A存入到earlySingletonObjects中,将来如果还有其他的类循环依赖了A,就可以直接从earlySingletonObjects中找到它了,那么此时springFactories中创建A的ObjectFactory也可以删除了
至此,B的依赖注入处理完了后,就可以继续处理A的依赖注入了,把B注入给A,此时A也创建完了,就可以把A的对象存储到singletonObjects中,并同时删除掉earlySingletonObjects中的半成品A
截此为止,A和B对象全部创建完毕,并存储到了singletonObjects中,将来通过容器获取对象,都是从singletonObjects中获取
总:总结起来就是一句话,借助于DefaultSingletonBeanRegistry的三个缓存区可以解决循环依赖问题
SpringMVC执行流程
- Mvc接收到请求开始,到给浏览器做出响应之间的过程



总结面试
问:请聊一聊SpringMVC的执行流程?
总:
使用了SpringMvc后,所有的请求都需要经过DispatcherServlet前端控制器,该类中提供了一个doDispatch方法,有关请求处理和结果响应的所有流程都在该方法中完成
分:
首先,借助于HandlerMapping处理器映射器得到处理器执行链,里面封装了HandlerMethod代表目标Controller的方法,同时还通过一个集合记录了要执行的拦截器
接下来,会根据HandlerMethod获取对应的HandlerAdapter处理器适配器,里面封装了参数解析器以及结果处理器
然后,执行拦截器的perHandler方法
接下来是核心,通过HandlerAdapter处理器适配器执行目标Controller方法,在这个过程中会通过参数解析器和结果处理器分别解析浏览器提交的数据以及处理Controller方法返回的结果
然后,执行拦截器的postHandle方法
最后处理响应,在这个过程中如果有异常抛出,会执行异常的逻辑,这里还会执行全局异常处理器的逻辑,并通过视图解析器viewResolver解析视图,再渲染视图,最后再执行拦截器的afterCompletion
然后,执行拦截器的perHandler方法
接下来是核心,通过HandlerAdapter处理器适配器执行目标Controller方法,在这个过程中会通过参数解析器和结果处理器分别解析浏览器提交的数据以及处理Controller方法返回的结果
然后,执行拦截器的postHandle方法
最后处理响应,在这个过程中如果有异常抛出,会执行异常的逻辑,这里还会执行全局异常处理器的逻辑,并通过视图解析器viewResolver解析视图,再渲染视图,最后再执行拦截器的afterCompletion
相关文章:
SpringBoot面试题整理(1)
面试整理 前置知识 ApplicationContextInitializerApplicationListenerBeanFactoryBeanDefinitionBeanFactoryPostProcessorAwareInitializingBean/DisposableBeanBeanPostProcessor 面试题 SpringBoot启动流程IOC容器初始化流程Bean声明周期Bean循环依赖SpringMVC执行流程…...
LVS原理及实例
目录 LVS原理 LVS概念 lvs集群的类型 lvs-nat 解释 传输过程 lvs-dr 解释 传输过程 特点 lvs-tun LVS(Linux Virtual Server)常见的调度算法 防火墙标记(Firewall Marking)结合轮询调度 实战案例 lvs的nat模式配置 …...
Spring统一功能处理:拦截器、响应与异常的统一管理
目录 一.拦截器 二.统一数据返回格式 三.统一异常处理 一.拦截器 拦截器是Spring框架提供的核⼼功能之⼀,主要⽤来拦截⽤⼾的请求,在指定⽅法前后,根据业务需要执⾏预先设定的代码。 也就是说,允许开发⼈员提前预定义⼀些逻辑…...
深入理解小程序的渲染机制与性能优化策略
一、小程序的渲染机制 小程序的渲染机制主要由两部分组成:渲染层和逻辑层。渲染层负责页面的渲染,逻辑层负责处理业务逻辑和数据处理。两者通过一个安全的、高效的通信机制进行数据传输和事件通知。 渲染层:在渲染层,WXML 模板会…...
Linux:多线程(二.理解pthread_t、线程互斥与同步、基于阻塞队列的生产消费模型)
上次讲解了多线程第一部分:Linux:多线程(一.Linux线程概念、线程控制——创建、等待、退出、分离,封装一下线程) 文章目录 1.理解Linux下线程——理解tid2. Linux线程互斥2.1相关概念2.2引入问题分析问题解决思路 2.3L…...
Pandas中`str`对象解析与应用实例
在数据科学领域,字符串操作是数据清洗和处理中不可或缺的一部分。Pandas的str对象为我们提供了一个强大而灵活的字符串操作方法集。本文将深入探讨str对象的各种应用,并通过代码示例和输出展示如何有效地处理字符串数据。 关键词 Pandas, 字符串操作, …...
C语言典型例题29
《C程序设计教程(第四版)——谭浩强》 习题2.6 设圆半径r1.5,圆柱高h3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。 scanf输入结果,输出计算结果,输出时要有文字说明,取小数点后两位数…...
Docker 常规安装简介
Docker常规安装简介 欢迎关注我的B站:https://space.bilibili.com/379384819 1. 安装mysql 1.1 docker hub上面查找mysql镜像 网址: https://hub.docker.com/_/mysql 1.2 从docker hub上(阿里云加速器)拉取mysql镜像到本地标…...
理解张量拼接(torch.cat)
拼接 维度顺序:对于 3D 张量,通常可以理解为 (深度, 行, 列) 或 (批次, 行, 列)。 选择一个dim进行拼接的时候其他两个维度大小要相等 对于三维张量,理解 torch.cat 的 dim 参数确实变得更加抽象,但原理是相同的。让我们通过一…...
指针基础知识(笔记)
文章目录 1. 概念理解2. 空指针和野指针3. 计算4. 小结5. size_t6. 案例一: 指针查找并返回指定元素索引7. 指针访问多维数组(涉及 int (*ptr)[3]解析)8. 指针数组9. 函数的值传递与地址引用传递① 函数的值传递(pass by value)② 地址传递(pass by reference) 10. 案例二&…...
[Python学习日记-3] 编程前选择一个好用的编程工具
[Python学习日记-3] 编程前选择一个好用的编程工具 简介 PyCharm IDE的安装 PyCharm IDE安装后的一些常规使用 简介 在踏上 Python 编程的精彩旅程之前,选择一款得心应手的编程工具无疑是至关重要的一步。这就如同战士在出征前精心挑选趁手的武器,它将…...
智能化的Facebook未来:AI如何重塑社交网络的面貌?
随着人工智能(AI)技术的飞速发展,社交网络的面貌正在经历深刻的变革。Facebook(现Meta Platforms)作为全球最大的社交媒体平台之一,正积极探索如何利用AI技术来提升用户体验、优化内容管理并推动平台创新。…...
安全启动的原理
安全启动(Secure Boot)是一种用于确保设备只运行经过认证的软件的安全机制。其核心原理和步骤如下: 1. **硬件信任根(Root of Trust, RoT)**: - 安全启动过程始于硬件信任根,通常是设备上的…...
【ML】pre-train model 是什么如何微调它,如何预训练
【ML】pre-train model 是什么如何微调它,如何预训练 0. 预训练模型(Pre-trained Model)0.1 预训练模型的预训练过程0.2 如何微调预训练模型0.3 总结 1. Contextualized word Embedding2. 怎么 让 bert 模型变小3. 如何微调模型 0. 预训练模型…...
leetcode代码练习——Java的数据结构(具体使用)
注:Java中所有的泛型必须是引用类型 如<Integer>而不是<int> java提供的数学方法: 求最大值Math.max(10,15),最小值Math.min(10,15) 看取值范围: int范围:-2^31-2^31-1 double范围:-2^63-2^63-1 long范围:-2^63-2…...
sqlserver导出数据脚本
文章目录 sqlserver导出数据脚本任务-生成脚本 sqlserver导出数据脚本 任务-生成脚本...
html+css 实现hover中间展开背景
前言:哈喽,大家好,今天给大家分享htmlcss 绚丽效果!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目…...
Java 怎么获取支付宝Open ID
在Java中获取支付宝用户的OpenID,通常是通过支付宝的开放平台API来完成的。OpenID是支付宝用于唯一标识一个支付宝用户的字符串,它在OAuth授权流程中被用来获取用户的身份和权限。 下面我将给出一个基于Java使用Spring Boot框架和支付宝开放平台SDK来获…...
Web-server日志分析命令
https://gist.github.com/hvelarde/ceac345c662429447959625e6feb2b47 通过状态码获取请求总数 awk {print $9} /var/log/apache2/access.log | sort | uniq -c | sort –rn按照IP的请求数量排序 awk {print $1} /var/log/apache2/access.log | sort | uniq -c | sort -rn |…...
Typora的markdown笔记使用说明
个人感觉Typora是一款很适合记录编程学习的软件 目录 个人感觉Typora是一款很适合记录编程学习的软件 一、标题 二、段落 1、换行 2、分割线 三、文字显示 1、字体 2、上下标 四、列表 1、无序列表 2、有序列表 3、任务列表 五、区块显示 六、代码显示 1、行内…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
