Java后端面试:框架篇高频面试(Spring、SpringMVC、SpringBoot、MyBatis)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Java后端面试:MySQL面试篇(底层事务、SQL调优)
📚订阅专栏:Java后端面试
希望文章对你们有所帮助

框架篇高频面试(Spring、SpringMVC、SpringBoot、MyBatis)

  • Spring
    • 单例bean是线程安全的吗?
    • AOP相关面试题
    • Spring事务失效的场景
    • bean的生命周期
    • bean的循环依赖(循环引用)
  • SpringMVC-执行流程
    • 视图阶段(JSP)
    • 前后端分离阶段
  • SpringBoot-自动装配原理
  • Spring框架常见注解(Spring、SpringMVC、SpringBoot)
  • MyBatis
    • 执行流程
    • 延迟加载使用及原理
    • 一级、二级缓存

Spring

单例bean是线程安全的吗?

通过@Scope注解可以设置bean是单例的还是多例的,默认是单例的。
而单例bean线程不安全

Spring的bean中都是注入无状态的对象,也就是说无法修改,不会有线程安全问题。
但是如果在bean中定义了可修改的成员变量,是要考虑线程安全问题的,当然可以使用多例模式或者加锁来解决。

AOP相关面试题

AOP很重要,在Spring也算是一个难点吧,但是像IOC、AOP这种Spring核心,不会的话说不过去,这里就简单说说。

1、何为AOP?
AOP称为面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被称为切面(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。

2、常见的AOP使用场景?

1、记录操作日志(自行学习@Aspect、切点、环绕通知)
2、缓存处理
3、Spring中内置的事务处理

3、Spring中的事务是如何实现的?(一定要提到AOP!)

Spring支持编程式事务管理和声明式事务管理两种方式,主要使用的是声明式事务
声明式事务管理是建立在AOP上的。本质是通过AOP功能,对方法的前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行目标方法之后执行情况提交或者回滚事务。(@Transactional注解就是这样的,其底层的实现(开启事务、提交/回滚事务)就是AOP追加的)

Spring事务失效的场景

这种问题能够体现出我们对Spring框架的深入理解,以及复杂业务的编码经验。

有三种非常常见的事务失效的情况:

1、异常捕获处理

对于转账的业务,我们会给整个业务增加@Transactional注解,如果中途发生了异常我们就会回滚。
但是如果这个业务方法中使用了try…catch,中途发生异常以后,@Transactional将会失效。
原因:事务通知只有捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉异常,事务通知将会无法知悉
解决方法:在catch块中添加throw new RuntimeException(E),将异常给抛出,不要处理。

2、抛出检查异常

依旧是转账业务,这次不用try…catch,而是在方法体使用throws来抛出检查异常(类似FileNotFoundException这种非运行异常),这种情况也会导致事务失效。
原因:Spring默认只会回滚非检查异常
解决方法:配置rollbackFor属性:@Transactional(rollbackFor=Exception.class),这样事务回滚就不只是针对运行时异常了。

3、非public方法

如果没有用public修饰方法,就会导致事务失效。
原因:Spring为方法创建代理、添加事务通知,前提条件都是该方法是public的
解决:改为public方法

bean的生命周期

这个在业务开发过程中重要吗?可能真的不太重要,这就是个纯八股。但是面试官还是挺喜欢问的,可能是掌握生命周期能显得你更了解框架,方便调试和解决问题。

1、通过BeanDefinition获取bean的定义信息
2、调用构造函数实例化bean
3、bean的依赖注入
4、处理Aware接口
5、Bean的后置处理器BeanPostProcessor-前置
6、初始化方法
7、Bean的后置处理器BeanPostProcessor-后置
8、销毁bean

bean的循环依赖(循环引用)

如果是两个bean,成员变量分别用对方来注入,这就是循环依赖。
这种方式是会出现死循环的,对于A,先实例化bean,再初始化,初始化的过程中需要设置b属性,而b是B类型的对象,可是容器中不存在B对象,就会去实例化B的bean对象,再去初始化,初始化的时候需要设置a属性,a是A类型的对象,但是容器中也不存在A对象,最后造成了死循环。

Spring框架已经帮助我们解决了大部分的循环依赖问题,通过的是三级缓存:

一级缓存:单力池,缓存已经经历了完整声明周期,即已经初始化完成的bean对象
二级缓存:缓存早期的bean对象(生命周期还没走完)
三级缓存:缓存的是对象工厂ObjectFactory,用来创建某个对象的

整体流程非常的复杂,大家可以自行去看相关资料来理解,写起来很麻烦,但要记住一级缓存+二级缓存可以解决大部分的循环依赖问题,但是解决不了存在代理对象时的问题,而一级+二级+三级可以解决代理对象的循环依赖问题,过程需要理解。

这些都是发生在初始化的时候,而如果我们在声明周期的构造方法换发出现了循环依赖,也就是注入的方式是用构造函数。解决是使用@Lazy进行懒加载,什么时候需要对象了再进行bean对象的创建就好了。

SpringMVC-执行流程

如果要问到SpringMVC,那么执行流程可以说是非常重要的。
但是其实开发分为了两个阶段,一个是视图阶段(老旧的JSP等),另外一个是前后端分离阶段(接口开发,异步),现在我们都是用的前后端分离的开发,但是视图阶段的开发也是面试可能会问到的,很繁琐,得记住。

视图阶段(JSP)

在这里插入图片描述
1、对于一个浏览器发起的请求,视图阶段的执行流程如下:

1、浏览器发起请求给前端控制器DispatcherServlet
2、查询handler:前端控制器根据前端请求,去处理器映射器HandlerMapping中查询对应的执行方法
3、返回处理器执行链:因为对于一个请求,除了要找到这个路径对应的类名.方法名,还需要判断它是否会被拦截器拦截,因此处理器映射器不是直接返回方法给前端控制器,而是返回一个处理器执行链(处理器执行链可以暂且理解成方法handler+拦截器
4、请求执行handler:处理器执行链不会被拦截,那么前端控制器就要开始执行方法handler,这个执行需要向处理器适配器去请求,而不是直接到处理器中(适配器模式),用适配器有两个好处:
(1)可以处理请求的参数
(2)处理返回值
5、处理器适配器向处理器请求
6、处理器将响应返回给处理器适配器,这个响应就是ModelAndView
7、处理器适配器再将ModelAndView返回给前端控制器
8、前端控制器返回视图解析器ViewResolver,这个视图解析器的作用是将逻辑视图解析为真正的视图View
9、视图解析器将真正的视图View返回给前端控制器
10、前端控制器将视图渲染

2、SpringMVC执行过程中重要的四个组件

1、前端控制器DispatcherServlet(调度中心,处理所有的请求)
2、处理器映射器HandlerMapping(通过路径,查询方法handler,返回处理器执行链)
3、处理器适配器HandlerAdaptor(执行handler、处理handler中的参数)
4、视图解析器ViewResolver(将逻辑视图ModelAndView解析为真正的视图View)

前后端分离阶段

现在的开发不太一样,没有ModelAndView了,而是返回的Json数据,流程将会简化为:
在这里插入图片描述
这时候处理器Handler的执行是变化了:

1、处理器Handler的方法上添加@ResponseBody注解
2、底层会通过一个转化器HttpMessageConverter将返回结果转化为JSON格式响应给前端

SpringBoot-自动装配原理

这是SpringBoot最高频的面试题了,也是框架的最核心思想。

我们的SpringBoot启动类中一定会有一个注解:@SpringBootApplication,这个注解底层包含了三个部分:

@SpringBootConfiguration:与@Configuration相同,用来声明当前是个配置类
@ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包
@EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解

其中,@EnableAutoConfiguration是实现自动化配置的核心注解,该注解底层通过@Import来导入对应的配置选择器。

其内部就是读取该项目和该项目引用的jar包的classpath路径下META-INF/spring.factories文件中的所配置的类的全类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。
这个条件判断会有@ConditionalOnClass这样的注解,判断是否有对应的class文件(字节码文件),若有则加载该类,把这个配置类中所有的Bean都放入Spring容器中使用。

Spring框架常见注解(Spring、SpringMVC、SpringBoot)

Spring的注解主要是用来进行bean的实例化以及依赖注入的,SpringMVC的注解主要是用来处理请求和响应的,而SpringBoot的注解尽量说一下跟自动装配有关系的,被问到不要混淆着讲。
1、Spring注解:

注解说明
@Componennt、@Controller、@Service、@Repository使用在类上,用于实例化bean
@Autowired在字段上根据类型依赖注入
@Qualifier结合@Autowired一起使用,用于根据名称进行依赖注入
@Scope标注Bean的作用返回(单例or多例)
@Configuration指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定Spring在初始化容器时要扫描的包
@Bean用在方法上,标注该方法的返回值会存到Spring容器中
@Import该注解导入的类会被Spring加载到IOC容器中
@Aspect、@Before、@After、@Around、@Pointcut用于AOP(切面、前置通知、后置通知、环绕通知、切入点表达式)

2、SpringMVC注解:

注解说明
@RequestMapping(也有衍生的PostMapping、GetMapping等)用于映射请求路径,定义在类上或方法上,用在类上则该类中的所有方法都是以该地址作为父路径的
@RequestBody接受http请求的json数据,将json转化为java对象
@ResponseBody将controller方法返回的对象转化为json对象响应给客户端
@RequestParam指定请求参数的名称(和数据库字段名不一致时使用)
@PathViriable从请求路径下获取请求参数/user/{id},传递给方法的形式参数(Restful风格)
@RequestHeader获取指定的请求头数据
@RestController@Controller+@ResponseBody

3、SpringBoot注解:

注解说明
@SpringBootConfiguration配置文件
@EnableAutoConfiguration打开自动配置
@ComponentScanSpring组件扫描

MyBatis

执行流程

1、读取MyBatis配置文件mybatis-config.xml,加载运行环境(数据库相关信息)和mapper映射文件
2、构造会话工厂SqlSessionFactory,会话工厂是全局唯一的
3、会话工厂创建SqlSession对象(包含了执行SQL语句的所有方法),每次操作都会创建出一个会话
4、Executor执行器是真正操作数据库的接口,同时负责了查询缓存的维护
5、Executor接口的执行方法中有一个MappedStatement类型的参数,封装了映射信息
6、输入参数的映射(将java类型转化为数据库处理的类型)
7、输出结果映射(将数据库操作的结果映射成java类型)

延迟加载使用及原理

1、延迟加载是需要用到数据的时候才会加载,不需要的时候就不会加载。
2、MyBatis是支持延迟加载的,但是默认是没有开启的。可以局部开启或者全局开启。
3、延迟加载的底层原理:

(1)使用CGLIB创建目标对象的代理对象
(2)当调用方法的时候,进入拦截器invoke方法,发现目标方法是null值,执行SQL查询
(3)获取数据后,调用set方法设置属性值,再继续查询目标方法,就有值了

一级、二级缓存

一级缓存:基于HashMap本地缓存,其存储作用域为SqlSession,当SqlSession进行flush或close之后,该Session中的Cache就被清空(默认开启)
二级缓存:基于namespace和mapper的作用域起作用的,不依赖于SqlSession,默认也是基于HashMap存储,需要单独开启(通过核心配置文件)

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

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

相关文章

HQYJ 3-18 整理

1.OSI七层体系结构:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层 TCP/IP四层结构:网络接口层、网际层、传输层、应用层 五层结构:物理层、数据链路层、网络层、传输层、应用层 2.一帧数据的说明:大小为64-1518…

解决访问站外图片403(referrer)问题

问题 我们在使用站外图片的时候,访问图片403,但是浏览器直接访问图片链接可以打开,这是为什么呢? 原因 http请求体的header中有一个referrer字段,用来表示发起http请求的源地址信息,这个referrer信息是可…

WPS制作甘特图

“ 甘特图(Gantt chart)又称为横道图、条状图(Bar chart),通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。” 设置基础样式 设置行高 设置宽度 准备基础数据 计算持续时间 …

解决Android Studio Flamingo创建项目时出现的问题

问题1 使用Android Studio Flamingo创建项目时,IDE默认下载Gradle 8.0,但是下载速度特别慢,或者直接下载失败 解决办法-手动安装Gradle 第一步:使用浏览器下载gradle-8.0-bin.zip 下载地址:https://services.gradle…

Flutter-Android studio常用快捷键总结

前言 因为之前一直用Xcode,对Android studio的快捷键还不是很熟悉,这次有空来总结一下。 一、快捷键 1、Ctrl option O 删除未使用的 import 这个快捷键其实也不需要,可以在设置里面设置flutter自动格式化代码,或者使用CMD …

Servlet两种配置

通过xml配置 <servlet><servlet-name>MyServlet</servlet-name><servlet-class>MyServlet</servlet-class> </servlet> <servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/MyServlet</ur…

智慧城市中的智慧生活:便捷、舒适与高效

目录 一、智慧城市中的智慧生活概述 二、智慧生活带来的便捷性 1、智慧交通的便捷出行 2、智慧购物的轻松体验 3、智慧政务的一站式服务 三、智慧生活带来的舒适性 1、智慧环境的绿色宜居 2、智慧医疗的健康保障 3、智慧教育的均衡发展 四、智慧生活带来的高效性 1、…

Flask中的Blueprints:模块化和组织大型Web应用【第142篇—Web应用】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Flask中的Blueprints&#xff1a;模块化和组织大型Web应用 在构建大型Web应用时&#xff0…

机器人可反向驱动能力与力控架构

反向驱动性是电机传动系统的机械特性&#xff0c;它描述了运动是否可以轻松反转 。特别是&#xff0c;反向驱动能力取决于两个因素&#xff1a;传动运动效率和整体执行器机械阻抗。反向运动中传动装置的低运动效率意味着所施加的外力的大部分被运动反作用力抵消。然而&#xff…

海外问卷调查:代理IP使用方法

在进行问卷调查时&#xff0c;为了避免被限制访问或被封禁IP&#xff0c;使用代理IP已经成为了必要的选择。 其中&#xff0c;口子查和渠道查也不例外。 使用代理IP可以隐藏本机IP地址&#xff0c;模拟不同的IP地址&#xff0c;从而规避被封禁的风险。但是&#xff0c;对于很…

layuiAdmin-通用型后台模板框架【广泛用于各类管理平台】

1. 主页 1.1 控制台 2. 组件 3. 页面 3.1 个人主页 3.2 通讯录 3.3 客户列表 3.4 商品列表 3.5 留言板 3.6 搜索结果 3.7 注册 3.8 登入 3.9 忘记密码 4. 应用 4.1 内容系统 4.1.1 文章列表 4.1.2 分类管理 4.1.3 评论管理 4.2 社区系统 4.2.1 帖子列表 4.2.2 回…

【FPGA/IC】什么是模块化设计?

什么是模块化设计 FPGA/IC设计中根据模块层次的不同有两种基本的设计方法&#xff1a; 自下而上方法对设计进行逐次划分的过程是从基本单元出发的&#xff0c;设计树最末枝上的单元是已经设计好的基本单元&#xff0c;或者其他项目开发好的单元或者IP。该方法先对底层的功能块…

数据结构:图的拓扑排序与关键路径

目录 一、拓扑排序 1.1、算法的基本步骤 1.2、算法实现 1.4、习题思考 1.5、DFS生成逆拓扑序 一、拓扑排序 AOV网:在 有向图中&#xff0c; 顶点表示活动&#xff08;或任务&#xff09;&#xff0c; 有向边表示活动&#xff08;或任务&#xff09;间的先后关系&#xff0…

在基于全志V851se的TinyVision上手动构建 Linux 6.1 + Debian 12 镜像

构建 SyterKit 作为 Bootloader SyterKit 是一个纯裸机框架&#xff0c;用于 TinyVision 或者其他 v851se/v851s/v851s3/v853 等芯片的开发板&#xff0c;SyterKit 使用 CMake 作为构建系统构建&#xff0c;支持多种应用与多种外设驱动。同时 SyterKit 也具有启动引导的功能&a…

Kotlin: 协程的四种启动模式(CoroutineStart)

点击查看CoroutineStart英文文档 创建协程的三种方式 runBlocking 运行一个协程并且会阻塞当前线程&#xff0c;直到它完成。launch 启动一个新的协程&#xff0c;不会阻塞当前线程&#xff0c;并且返回一个Job&#xff0c;可以取消。async async和await是两个函数&#xff0c…

【UE 插件】UE4 虚幻引擎 插件开发(带源码插件打包、无源码插件打包) 有这一篇文章就够了!!!

目录 0 引言1 快速入门1.1 新建插件的前提1.2 创建插件步骤1.3 打包插件 2 无源代码的插件制作3 插件详细介绍3.1 插件的使用方法3.1 UE 预置插件模版3.1.1 空白3.1.2 纯内容3.1.3 编辑器独立窗口3.1.4 编辑器工具栏按钮3.1.5 编辑器模式3.1.6 第三方库3.1.7 蓝图库 3.2 插件中…

【视频异常检测】Delving into CLIP latent space for Video Anomaly Recognition 论文阅读

Delving into CLIP latent space for Video Anomaly Recognition 论文阅读 ABSTRACT1. Introduction2. Related Works3. Proposed approach3.1. Selector model3.2. Temporal Model3.3. Predictions Aggregation3.4. Training 4. Experiments4.1. Experiment Setup4.2. Evaluat…

Re62:读论文 GPT-2 Language Models are Unsupervised Multitask Learners

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名&#xff1a;Language Models are Unsupervised Multitask Learners 论文下载地址&#xff1a;https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learner…

jar读取目录配置、打包jar后无法获取目录下的配置

jar读取目录配置、打包jar后无法获取目录下的配置 jar读取目录配置、打包jar后无法获取目录下的配置。java打成jar包后获取不到配置文件路径。解决项目打成jar包上线无法读取配置文件。打包jar后无法读取resource下的配置文件 场景 需要读取 src/main/resources/mapper下的所…

计算机网络:TCP篇

计网tcp部分面试总结 tcp报文格式&#xff1a; 序列号&#xff1a;通过SYN传给接收端&#xff0c;当SYN为1&#xff0c;表示请求建立连接&#xff0c;且设置序列号初值&#xff0c;后面没法送一次数据&#xff0c;就累加数据大小&#xff0c;保证包有序。 确认应答号&#x…