【Spring】

目录

前言

1.Spring框架中的单例bean是线程安全的吗?

2.什么是AOP?

3.你们项目中有没有使用到AOP?

4.Spring中的事务是如何实现的?

5.Spring中事务失效的场景有哪些?

6.Spring的bean的生命周期。

7.Spring中的循环引用

8.构造方法出现了循环依赖怎么解决?

9.SpringMVC的执行流程知道嘛?

10.Springboot自动配置原理。

11.Spring 的常见注解有哪些?

12.SpringMVC常见的注解有哪些?

13.Springboot常见注解有哪些?

总结


前言

本文主要介绍了Spring面试题相关的面试题目。


1.Spring框架中的单例bean是线程安全的吗?

不是线程安全的,Spring框架中有一个@Scope注解,默认的值就是singleton,单例的。因为一般在spring的bean中都是注入无状态的对象,没有线程安全问题,如果在bean中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例或者加锁来解决。

参考回答:不是线程安全的,当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对该单列状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。比如: 我们通常在项目中使用的Spring bean都是不可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。如果bean有多种状态的话(比如 View Model对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用由“singleton”变更为“prototype”。

2.什么是AOP?

面向切面编程,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合。

参考回答:aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般可以做为公共日志保存,事务处理等。

3.你们项目中有没有使用到AOP?

记录操作日志,缓存,spring实现的事务。核心:使用aop中的环绕通知+切点表达式(找到要记录日志的方法),通过环绕通知的参数获取请求方法的参数(类、方法、注解、请求方式等),获取到这些参数以后,保存到数据库。

4.Spring中的事务是如何实现的?

其本质是通过AOP功能,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

5.Spring中事务失效的场景有哪些?

  1. 异常捕获处理,自己处理了异常,没有抛出。    解决:手动抛出。
  2. 抛出检查异常(Spring 默认只会回滚非检查异常)。    解决:配置rollbackFor属性为Exception。
  3. 非public方法导致的事务失效。    解决:改为public。

参考回答:第一个,如果方法上异常捕获处理,自己处理了异常,没有抛出,就会导致事务失效,所以一般处理了异常以后,别忘了抛出去就行了;第二个,如果方法抛出检查异常,如果报错也会导致事务失效,在 spring事务的注解上,就是@Transactional上配置rollbackFor属性为 Exception,这样别管是什么异常,都会回滚事务;第三,如果方法上不是public修饰的,也会导致事务失效。

6.Spring的bean的生命周期。

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

参考回答:首先会通过一个非常重要的类,叫做BeanDefinition获取bean的定义信息,这里面就封装了bean的所有信息,比如类的全路径、是否是延迟加载、是否是单例等等这些信息在创建bean的时候,第一步是调用构造函数实例化bean;第二步是bean的依赖注入,比如一些set方法注入,像平时开发用的 @Autowire都是这一步完成;第三步是处理Aware接口,如果某一个bean实现了Aware接口就会重写方法执行;第四步是bean的后置处理器BeanPostProcessor,这个是前置处理器;第五步是初始化方法,比如实现了接口InitializingBean或者自定义了方法 init-method标签或@PostContruct;第六步是执行了bean的后置处理器BeanPostProcessor,主要是对bean进行增强,有可能在这里产生代理对象;最后一步是销毁bean。

7.Spring中的循环引用

  • 循环依赖:循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A。
  • 循环依赖在spring中是允许存在,spring框架依据三级缓存已经解决了大部分的循环依赖。
  1. 一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象。
  2. 二级缓存:缓存早期的bean对象(生命周期还没走完)。
  3. 三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象。

具体解决流程:

第一,先实例A对象,同时会创建ObjectFactory对象存入三级缓存singletonFactories;第二,A在初始化的时候需要B对象,这个走B的创建的逻辑;第三,B实例化完成,也会创建ObjectFactory对象存入三级缓存singletonFactories  ;第四,B需要注入A,通过三级缓存中获取ObjectFactory来生成一个A的对象,同时存入二级缓存,这个是有两种情况,一个是可能是A的普通对象,另外一个是A的代理对象,都可以让ObjectFactory来生产对应的对象,这也是三 级缓存的关键; 第五,B通过从通过二级缓存earlySingletonObjects获得到A的对象后可以正常注入,B创建成功,存入一级缓存singletonObjects ;第六,回到A对象初始化,因为B对象已经创建完成,则可以直接注入B,A创建成功存入一次缓存singletonObjects;第七,二级缓存中的临时对象A清除。

8.构造方法出现了循环依赖怎么解决?

A依赖于B,B依赖于A,注入的方式是构造函数。

原因:由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的的依赖注入。

解决方案:使用@Lazy进行懒加载,什么时候需要对象再进行bean对象的创建。

参考回答:由于bean的生命周期中构造函数是第一个执行的,spring框架并不能解决构造函数的的依赖注入,可以使用@Lazy懒加载,什么时候需要对象再进行bean对象的创建。

9.SpringMVC的执行流程知道嘛?

视图版本:

  1. 用户发送出请求到前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
  3. HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)
  5. HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
  6. Controller执行完成返回ModelAndView对象
  7. HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)
  9. ViewReslover解析后返回具体View(视图)
  10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
  11. DispatcherServlet响应用户

前后端开发(接口开发):

  1. 用户发送出请求到前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
  3. HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  4. DispatcherServlet调用HandlerAdapter(处理器适配器)
  5. HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
  6. 方法上添加了@ResponseBody
  7. 通过HttpMessageConverter来返回结果转换为JSON并响应

10.Springboot自动配置原理。

在Spring Boot项目中的引导类上有一个注解@SpringBootApplication,这个注解是对三个注解进行了封装,分别是:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

其中@EnableAutoConfiguration是实现自动化配置的核心注解,该注解通过@Import注解导入对应的配置选择器。
内部就是读取了该项目和该项目引用的Jar包的的classpath路径下META-INF/spring.factories文件中的所配置的类的全类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。

条件判断会有像@ConditionalOnClass这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean放入spring容器中使用。

11.Spring 的常见注解有哪些?

参考回答:第一类:声明bean,有@Component、@Service、@Repository、@Controller ;第二类:依赖注入相关的,有@Autowired、@Qualifier、@Resourse;第三类:设置作用域 @Scope;第四类:spring配置相关的,比如@Configuration,@ComponentScan 和 @Bean;第五类:跟aop相关做增强的注解 @Aspect,@Before,@After, @Around,@Pointcut。

12.SpringMVC常见的注解有哪些?

参考回答:有@RequestMapping:用于映射请求路径; @RequestBody:注解实现接收http请求的json数据,将json转换为java对 象; @RequestParam:指定请求参数的名称; @PathViriable:从请求路径下中获取请求参数(/user/{id}),传递给方法的 形式参数;@ResponseBody:注解实现将controller方法返回对象转化为json 对象响应给客户端;@RequestHeader:获取指定的请求头数据,还有像 @PostMapping、@GetMapping这些。

13.Springboot常见注解有哪些?

参考回答:Spring Boot的核心注解是@SpringBootApplication ,它由几个注解组成,@SpringBootConfiguration: 组合了@Configuration注解,实现配置文件的功 能; @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项; @ComponentScan:Spring组件扫描。


总结

本文主要介绍了Spring相关的面试题目。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

兼容性测试

1 软件兼容性测试 兼容性测试是软件测试的一个关键环节,旨在确保软件应用程序在不同的环境中能够如预期般运行。这包括操作系统、网络环境、浏览器、数据库、设备和其他系统组件的兼容性。进行兼容性测试时,通常会使用虚拟机来模拟不同的环境和条件&…

休斯顿NASA太空机器人进入最后测试阶段,或可模拟人类执行外星任务!

美国宇航局开发研制的太空智能机器人目前正在德州休斯顿的约翰逊航天中心接受最后的运行测试,距离太空智能化时代又要更进一步了! NASA表示,日前在德州休斯顿附近的约翰逊航天中心进行测试的机器人名为Valkyrie,是以北欧神话中的一…

Postgresql 的编译安装与包管理安装, 全发行版 Linux 通用

博客原文 文章目录 实验环境信息编译安装获取安装包环境依赖编译安装安装 contrib 下工具代码 创建用户创建数据目录设置开机自启动启动数据库常用运维操作 apt 安装更新源安装 postgresql开机自启修改配置修改密码 实验环境信息 Ubuntu 20.04Postgre 16.1 编译安装 获取安装…

Leetcode 121 买卖股票的最佳时机

题意理解: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交…

.NET命令行(CLI)常用命令

本文用于记录了.NET软件开发全生命周期各阶段常用的一些CLI命令,用于开发速查。 .NET命令行(CLI)常用命令 项目创建(1)查看本机SDK(2)查看本机可以使用的.NET版本(3)生成…

LeetCode 热题 100 | 链表(下)

目录 1 148. 排序链表 2 23. 合并 K 个升序链表 3 146. LRU 缓存 3.1 解题思路 3.2 详细过程 3.3 完整代码 菜鸟做题第三周,语言是 C 1 148. 排序链表 解题思路: 遍历链表,把每个节点的 val 都存入数组中用 sort 函数对数组进…

159基于matlab的基于密度的噪声应用空间聚类(DBSCAN)算法对点进行聚类

基于matlab的基于密度的噪声应用空间聚类(DBSCAN)算法对点进行聚类,聚类结果效果好,DBSCAN不要求我们指定集群的数量,避免了异常值,并且在任意形状和大小的集群中工作得非常好。它没有质心,聚类簇是通过将相邻的点连接…

Android:内存泄漏检查内存优化

3.17Android优化 手机移动设备的内存是有限的,需要避免内存泄漏,优化内存使用。 1.java中四种引用类型 强引用、软引用、弱引用、虚引用。 强引用:使用类构造方法,创建对象,当内存超出了,也不会释放对象所占内存空间; String str = new String(‘1223’); 切断引用str=…

代码随想录算法训练营第44天 | 完全背包理论基础 518.零钱兑换II 377.组合总和 Ⅳ

完全背包理论基础 完全背包与01背包只相差在物品是无限取用的。因此和01背包相比第二层对背包容量的遍历应该是正序的&#xff0c;而且正因为这个正序&#xff0c;使得在纯完全背包问题中&#xff0c;背包容量和物品的遍历是可以倒过来的。 #include <bits/stdc.h> usi…

【回溯算法】LCR 082. 组合总和 II

LCR 082. 组合总和 II 解题思路 定义了一个 Solution 类。使用了 LinkedList 来存储结果集 res&#xff0c;以及用于回溯过程中追踪当前组合的 track 列表和追踪当前组合的和的 trackNum 变量。combinationSum2 方法是入口方法&#xff0c;用于求解给定 candidates 数组中元素…

785. 快速排序

Problem: 785. 快速排序 文章目录 思路解题方法复杂度Code方法一&#xff08;调用系统类库&#xff09;方法二&#xff08;随机快速排序经典版&#xff09;方法三 &#xff08;利用荷兰国旗问题改写快排&#xff09; 思路 这个问题要求实现快速排序算法&#xff0c;对给定的整数…

网络的基本概念和socket编程

网络的基本概念 1.协议1.1 协议的基本概念1.2 常见的协议 2.分层模型2.1网络七层OSI 7层模型&#xff1a;物数网传会表应(口诀)2.2TCP/IP模型2.3数据通信的过程2.4网络的设计模式2.5以太网帧的格式 3.SOCKET编程3.1网络字节序3.2 相关结构体和函数3.3 代码实现 1.协议 1.1 协议…

前端JavaScript篇之对象继承的方式有哪些?

目录 对象继承的方式有哪些&#xff1f;1. 原型链继承2. 借用构造函数3. 组合继承4. 原型式继承5. 寄生式组合继承 对象继承的方式有哪些&#xff1f; 1. 原型链继承 当使用原型链继承时&#xff0c;子类型的原型对象被设置为父类型的一个实例。这意味着子类型通过其原型可以…

线性表的插入

#define MaxSize 10 //定义最大长度 typeof struct{ int data[MaxSize]; //用静态“数组”存放数据元素 int length; //顺序表的当前长度 }SeqList; //顺序表的类型定义 bool ListInsert(SeqList &L,int i,int e){ if(i<1 || i>L.length1)…

VUE学习——数组变化侦测

官方文档 变更方法&#xff1a; 使用之后&#xff0c;ui可以直接发生改变。改变原数组 替换数组&#xff1a; 使用之后需要接受重新赋值&#xff0c;不然ui不发生改变。不改变原数组

第70讲axios后端请求工具类封装

axios工具类封装&#xff1a; // 引入axios import axios from axios;// 创建axios实例 const httpService axios.create({// url前缀-http:xxx.xxx// baseURL: process.env.BASE_API, // 需自定义baseURL:http://localhost:80/,// 请求超时时间timeout: 3000 // 需自定义 })…

嵌入式系统:挑战与机遇并存的领域

嵌入式系统&#xff1a;挑战与机遇并存的领域嵌入式系统是一个既具有挑战性又充满前景的领域。要成为一名合格的嵌入式系统工程师&#xff0c;需要经过大量的学习和实践。然而&#xff0c;进入这个领域时&#xff0c;刚入行可能会面临许多困境。让我们一起探讨一下嵌入式系统工…

matplotlib的学习

matplotlib绘图两种方式: #面向对象方法 import numpy as np import matplotlib.pyplot as plt x = np.linspace(0, 5, 100) fig, ax = plt.subplots(figsize=(10, 5)) ax.plot(x, x) ax.plot(x, x ** 2) ax.set_xlabel(‘x’) ax.set_ylabel(‘y’) plt.show() #直接使用pyplo…

Python爬虫实战 | 京东平台电商API接口采集京东商品京东工业商品详情数据

item_get-获得JD商品详情API测试 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]cac…

【Maven】依赖、构建管理 继承与聚合 快速学习(3.6.3 )

文章目录 Maven是什么&#xff1f;一、Maven安装和配置本地配置文件设置idea配置本地maven 二、基于IDEA的Maven工程创建2.1 Maven工程GAVP属性2.2 Idea构建Maven JavaEE工程 三、Maven工程项目结构说明四、Maven核心功能依赖和构建管理4.1 依赖管理和配置4.2 依赖传递和冲突4.…