面试篇:Spring

news2024/11/25 14:45:44

一、Spring框架的单例bean是线程安全的吗?

1、Spring框架中的bean是单例的吗?

spring框架中的bean是单例的,在默认情况下是singleton模式,即单例模式。如果需要更改则可以在@Scope注解设置为prototype为多例模式。

  • singleton:bean在每个Spring IOC容器中只有一个实例。
  • prototype:一个bean的定义可以有多个实例。

2、Spring框架中的单例bean是线程安全的吗?

如上图的代码,在"getById/{id}"请求中,count变量是成员变量,会受到多个用户同时修改,就会出现线程安全问题。但UserService userService不会出现线程安全问题,因为userService是无状态bean,不能被修改。

Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。

3、概括

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

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

4、面试官: Spring框架中的单例bean是线程安全的吗?

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

二、AOP相关面试题

1、什么是AOP,你们项目中有没有使用到AOP ?

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

2、场景的AOP使用场景

  • 记录操作日志
  • 缓存处理
  • Spring中内置的事务处理 

3、记录操作日志思路

这种情况可以使用Spring的AOP思想来解决问题。记录日志需要记录当前用户的各种信息到数据库的日志表中去,因此可以在不改变原代码的情况下,使用AOP封装一个模块来对此操作。

大概思路就是创建一个切面类,找到要添加相应功能的类的地址,然后在切面类中对要添加的功能进行封装,可以使用前置通知,后置通知,异常通知,返回通知和环绕通知对次进行添加。一般而言使用环绕通知,获取要添加功能的类的相应信息,比如添加用户,就可以获取添加用户的用户名,请求方式,访问地址等待来将它们添加到数据库的日志表中。

4、Spring事务是如何实现的?

编程式事务

  • 通过TransactionTemplate或TransactionManager手动管理事务,因为是手动,所以实际开发中很少使用。

声明式事务(主要)

  • 声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

如上代码,比如要保存一个用户,其中的Object proceed=joinPoint.proceed();方法就是执行保存用户的代码,在代码之前会开启事务,然后在保存之后是提交事务。如果出现异常会在catch代码块执行回滚事务,这是Spring的事务的原理。

如果需要开启事务,就可以使用 @Transactional注解添加到方法上进行开启。

5、概括

什么是AOP?

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

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

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

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

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

三、事务失效的场景

1、Spring中事务失效的场景有哪些

  • 异常捕获处理
  • 抛出检查异常
  • 非public方法

2、异常捕获处理实例

如上图代码,这是正常转帐的情况

  • 这是执行前的数据

  • 这是代码执行后的数据

如上图,进行模拟异常,那么就会事务回滚

  • 这是执行结果:事务会回滚

如上图代码,这是将try-catch包裹异常的代码

这是执行后的数据:事务没有被回滚

原因:

  • 事务通知只有捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉异常,事务通知无法知悉。

这是Spring的事务底层,AOP层无法捕获到异常就不会进行回滚,因为业务层已经将异常捕获了。

解决方法:

在catch块添加throw new RuntimeException(e)抛出

2、抛出检查异常

如上图,代码抛出了 FileNotFoundException异常,这个是检查异常

运行前结果:

运行后结果:事务没有回滚

原因:

  • Spring 默认只会回滚非检查异常

解决:

  • 配置rollbackFor属性
    • @Transactional(rollbackFor=Exception.class)

3、非public方法导致的事务失效

如上代码,访问权限修饰为default,不是public

运行前数据:

运行后数据:事务失效

原因:

  • Spring为方法创建代理、添加事务通知、前提条件都是该方法是 public的

解决方法:

  • 改为 public方法

 4、概括

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

  • 异常捕获处理,自己处理了异常,没有抛出,解决: 手动抛出
  • 抛出检查异常,配置rollbackFor属性为Exception
  • 非public方法导致的事务失效,改为public

四、Bean的生命周期

1、BeanDefinition

有三种面向资源的bean定义信息读取方式,常用的方式:

  • XML方式配置
    • 会将xml配置的<bean>的信息封装成一个BeanDefinition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多的属性用来描述Bean。
  • 面向注解
    • @component
    • @import
    • @bean

 这是BeanDefinition的类的方法

其中比较重要的有:

  • beanClassName: bean 的类名
  • initMethodName:初始化方法名称
  • properryValues: bean 的属性值
  • scope:作用域
  • lazylnit:延迟初始化

2、Bean生命周期 

Bean生命周期主要分为三个大阶段分别为:

  • 生产
  • 使用
  • 销毁

3、生产阶段

首先通过loadBeanDefinitions()方法,用xml、注解等方法将定义的Bean类全部都找出来,并且放到beanDefinitionMap集合中。

通过遍历beanDefinitionMap集合,然后使用creatBean()方法创建一个个Bean对象,创建Bean分为构造对象、填充属性、初始化实例、注册销毁四个步骤。

首先,对于构造对象,通过createBeanInstance()方法进行对象的构造,先用反射机制从beanDefinitionMap中的BeanClass拿到这个类的构造方法。如果有多个构造方法,那么就会造成可读性低,理解和维护困难。对于获取构造方法有响应的规则:

  • 如果Bean只有一个构造方法,那么就使用该构造方法。
  • 如果Bean有多个构造方法,那么就会优先选择有@Autowired注解的构造方法,如果多个构造方法都有@Autowired,那么就会报错。
  • 如果构造方法没有@Autowired注解,那么会优先使用无参数的构造方法,如果多个构造方法都有参数,那么就会报错。

在确定构造方法之后,就需要准备构造方法的参数了,首先在Bean的单例池中根据参数的Class类进行查找 ,如果这个类有多个实例,则会根据参数名进行匹配。如果没有找到,就会认为构造信息不完整之间报错。在参数准备好以后就可以通过反射进行Bean的构造了,即实例化。如果是无参构造,则无需参数之间构造。

接下来是进行属性填充,通过调用populateBean()方法为Bean内部的所需的属性进行复制填充,通常就是@Autowired注解这些变量,通过三级缓存机制进行填充,三级缓存就是依赖注入。

然后是初始化实例。初始化第一步是初始化容器相关信息,通过invokeAwareMethods方法为实现个各种Aware接口的Bean设置如beanName、beanFactory等容器信息。然后通过invokeInitMethod方法执行Bean的初始化方法,通过实现initializingBean接口而实现的afterPropertiesSet()方法。方法名afterPropertiesSet就代表"Bean填充属性后"执行。最后再执行Bean中自定义的initMethod()方法。

在执行初始化方法之前和之后还需要对Bean后置处理器BeanPostProcessors进行处理。在Spring内部使用了很多后置处理器,比较典型的是当一个类被增强了使用到了AOP,那么这个类通常使用后置处理器来增强的。

4、使用阶段

因此到了BeanPostProcessors这一步之后,基本Bean实例已经被创建好了,并且可以使用。

5、销毁阶段 

对于销毁,通过实现DisposableBean接口执行destory方法进行销毁。

6、概括

Spring的bean的生命周期

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

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

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

相关文章

ECharts---X轴文字显示不全

原因&#xff1a; X轴标签文字过多导致显示不全解决方法&#xff1a;(一)xAxis 中添加 xAxis.axisLabel 属性 axisLabel是用来设置x轴的刻度以及一些参数的设置&#xff1a; (1)interval设置的是间隔数&#xff0c;把x轴分成10个间隔&#xff0c;根据x轴的数据自动划分份数值…

【计算机专业漫谈】【计算机系统基础学习笔记】W1-计算机系统概述

利用空档期时间学习一下计算机系统基础&#xff0c;以前对这些知识只停留在应试层面&#xff0c;今天终于能详细理解一下了。参考课程为南京大学袁春风老师的计算机系统基础MOOC&#xff0c;参考书籍也是袁老师的教材&#xff0c;这是我的听课自查资料整理后的笔记&#xff0c;…

【Java笔试强训 14】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、选择题 二、编程题 &#x1f525;计算日期…

web小游戏开发:华容道(一)

web小游戏开发:华容道(一) 华容道htmlcss素材原图素材验证游戏关卡华容道 老顾儿时的记忆啊,也是一个经典的益智游戏。 游戏规则就不用再介绍了吧,就是让曹操移动到曹营就算胜利。 CSDN 文盲老顾的博客,https://blog.csdn.net/superrwfei html 经过上次的扫雷,大家应…

Prometheus 监控初体验

最近由于要对Splunk 实现Prometheus 监控,下面先实践一下: 0: 先看架构图: 1: 安装: docker run -d -p 9090:9090 -v ~/docker/prometheus/:/etc/prometheus/ prom/prometheus 执行上面的 命令,发现prometheus docker 启动不起来,(原因是Mac 里的文件权限,或者是path

《嵌入式系统》知识总结4:STM32时钟源

此图说明了STM32的时钟走向&#xff0c;从图的左边开始&#xff0c;从时钟源一步步分配到外设时钟。 时钟源分类 从时钟频率来说&#xff0c;分为高速时钟和低速时钟&#xff0c;高速时钟是供给芯片主体的主时钟&#xff0c;而低速时钟只是供 给芯片中的RTC&#xff08;实时时…

Django请求生命周期

前言 django是一个web框架&#xff0c;在这之前的文章中&#xff0c;我们推导了python web框架的实现过程&#xff0c;也了解了客户端浏览器输入网址回车后发生了啥事&#xff0c;为了更加理解django的工作流程&#xff0c;本文将介绍客户端浏览器访问django后端在django框架中…

R语言多元数据统计分析在生态环境中的实践

生态环境领域研究中常常面对众多的不同类型的数据或变量&#xff0c;当要同时分析多个因变量&#xff08;y&#xff09;时需要用到多元统计分析&#xff08;multivariate statistical analysis&#xff09;。多元统计分析内容丰富&#xff0c;应用广泛&#xff0c;是非常重要和…

如何使用OpenVPN搭建局域安全网

前言: 由于在使用SpringCloud的时候把注册中心部署到内网中的一个服务器器上,由于这个服务器和我当前使用的网络的网关在同一个局域网内内,但是我电脑不在.主要现象就是我的电脑能ping通服务器,但是服务器不能ping通我的电脑 正文: 服务器端安装方式一: 去这个仓库下载一个open…

【人脸检测】——YOLO5Face: Why Reinventing a Face Detector论文浅读

人脸检测&#xff0c; yolov5 主要讨论的问题&#xff1a; 用通用的目标检测模型做人脸检测&#xff0c;而不一定需要一些专业设计的结构 摘要 最近几年在使用卷积神经网络进行人脸检测方面取得了巨大的进展。尽管许多人脸检测器使用专门用于检测人脸的设计&#xff0c;但我们…

【CTF WriteUp】2023数字中国创新大赛网络数据安全赛道决赛WP(2)

2023数字中国创新大赛网络数据安全赛道决赛WP(2) 数据分析题目 菜的要死&#xff0c;各种不会&#xff0c;答案也不全&#xff0c;凑合吧 数据分析-bankmail 流量为邮件通信流量 将其中邮件部分导出&#xff0c;保存为eml文件并打开&#xff0c;看到Alice给Bob的第一封邮件…

收藏的一些好用的网站

一、PPT模板 网址&#xff1a;https://pptmon.com/ PPTMON - Free PowerPoint Templates and Google Slides Themes 是一个提供 PowerPoint 模板和图标素材下载的网站。该网站上有大量的 PowerPoint 模板&#xff0c;可供用户根据自己的需要进行选择和下载。此外&#xff0c;该…

二叉树OJ题目合集(单值、对称、平衡、构建加遍历)

目录 前言&#xff1a; 一&#xff1a;单值二叉树 二&#xff1a;二叉树遍历 核心点 (1)前序 (2)中序 (3)后序 三&#xff1a;判断两颗树是否相同 四&#xff1a;判断二叉树是否对称 五&#xff1a;判断一颗树是否为另一颗树的子树 六&#xff1a;平衡二叉树 七&…

创建的django项目生成后,没有默认的数据库生成

目录 1、尚未执行迁移 1.1 首先&#xff0c;在setting.py文件中配置数据库链接 1.2 确保在Terminal运行已经执行了如下命令来创建数据库表格。 1.3 在数据库刷新就有了 2、已经使用了自定义的数据库 3、尚未配置默认数据库 1、尚未执行迁移 1.1 首先&#xff0c;在setting.…

介绍一款优秀的网址导航,可以部署到自己公司内部:hexo-theme-webstack

GitHub - HCLonely/hexo-theme-webstack: A hexo theme based on webstack. | 一个基于webstack的hexo主题。 中文文档 A Hexo theme based on WebStackPage. Installation hexo > 4.0 git clone https://github.com/HCLonely/hexo-theme-webstack themes/webstack hexo …

C++中的stack容器

文章目录 stack的介绍stack的使用 stack的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作特性的环境中&#xff0c;只能在容器的一端进行插入删除&#xff1b;stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特性类封装作为其底层的容器&#xf…

101-Linux_I/O复用方法之select

文章目录 1.select系统调用的作用2.select系统调用的原型3.集合fdset4.使用select实现TCP服务器(1)服务器端代码:(2)客户端代码(3)运行结果截图 1.select系统调用的作用 在一段指定时间内&#xff0c;监听用户感兴趣的文件描述符的可读、可写和异常等事件 2.select系统调用的…

Typora Markdown 中 LaTeX 公式居左、对齐的方法

我们知道公式块里的公式默认是居中的&#xff0c;我们想让公式居左&#xff08;顶着左页面&#xff09;可以使用如下格式的 flalign 数学环境&#xff1a; 不多说&#xff0c;先看示例 示例 \begin{flalign} &\iint_D\frac{\sin y}{y}{\rm d}\sigma\\ &\int_0^1{\rm…

【redis】redis分布式锁(二)可重入锁+设计模式

【redis】redis分布式锁&#xff08;二&#xff09;可重入锁 文章目录 【redis】redis分布式锁&#xff08;二&#xff09;可重入锁前言一、可重入锁&#xff08;又名递归锁&#xff09;1、说明&#xff1a;2、分开解释&#xff1a;3、可重入锁的种类隐式锁&#xff08;即synch…

Nautilus Chain 测试网第二阶段,推出忠诚度计划及广泛空投

随着更多的公链底层面向市场&#xff0c;通过参与早期测试在主网上线后获得激励成为了行业的一个热点话题&#xff0c;在Apots、Arbitrum One、Optimism等陆续发放了测试空投后&#xff0c;以Layer3为主要特性的Nautilus Chain也在前不久明确表示将会有空投&#xff0c;引发行业…