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、行内…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...

结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...