Java面试题冲刺第十八天--Spring框架3


Posted in 面试题 onAugust 07, 2021

面试题1:Bean 的加载过程是怎样的?

我们知道, Spring 的工作流主要包括以下两个环节:

  • 解析,读 xml 配置,扫描类文件,从配置或者注解中获取 Bean 的定义信息,注册一些扩展功能。
  • 加载,通过解析完的定义信息获取 Bean 实例。

下面是跟踪了 getBean的调用链创建的流程图,为了能够很好地理解 Bean 加载流程,省略一些异常、日志和分支处理和一些特殊条件的判断。

Java面试题冲刺第十八天--Spring框架3

从上面的流程图中,可以看到一个 Bean 加载主要会经历这么几个阶段(标绿内容):

  • 获取 BeanName,对传入的 name 进行解析,转化为可以从 Map 中获取到 BeanDefinition 的 bean name。
  • 合并 Bean 定义,对父类的定义进行合并和覆盖,如果父类还有父类,会进行递归合并,以获取完整的 Bean 定义信息。
  • 实例化,使用构造或者工厂方法创建 Bean 实例。
  • 属性填充,寻找并且注入依赖,依赖的 Bean 还会递归调用 getBean 方法获取。
  • 初始化,调用自定义的初始化方法。
  • 获取最终的 Bean,如果是 FactoryBean 需要调用 getObject 方法,如果需要类型转换调用 TypeConverter 进行转化。

以上便是Spring对bean解析注册的全过程,总结一下大致步骤:

  • 加载XML文件,封装成Resource对象;
  • 调用Reader对象方法读取XML文件内容,并将相关属性放到BeanDefinition实例;
  • 将BeanDefinition对象放到BeanFactory对象,用于调用;

追问1:什么是循环依赖?

举个例子,这里有三个类 A、B、C,然后 A 关联 B,B 关联 C,C 又关联 A,这就形成了一个循环依赖。如果是方法调用是不算循环依赖的,循环依赖必须要持有引用。

Java面试题冲刺第十八天--Spring框架3

循环依赖发生的场景:

  • 构造器循环依赖:依赖的对象是通过构造器传入的,发生在实例化 Bean 的时候。
  • 设值循环依赖:依赖的对象是通过 setter 方法传入的,对象已经实例化,发生属性填充和依赖注入的时候。
  • 如果是构造器循环依赖,本质上是无法解决的。比如我们准调用 A 的构造器,发现依赖 B,于是去调用 B 的构造器进行实例化,发现又依赖 C,于是调用 C 的构造器去初始化,结果依赖 A,整个形成一个死结,导致 A 无法创建。
  • 如果是设值循环依赖,Spring 框架只支持单例下的设值循环依赖。Spring 通过对还在创建过程中的单例,缓存并提前暴露该单例,使得其他实例可以引用该依赖。

追问2:循环依赖得解决思路是什么样的?

Spring解决循环依赖,主要的思路就是依据三级缓存(解链)。

在实例化A时调用doGetBean,发现A依赖的B的实例,此时调用doGetBean去实例B,实例化的B的时候发现又依赖A,如果不解决这个循环依赖的话此时的doGetBean将会无限循环下去,导致内存溢出,程序奔溃。

如果Spring引用一个早期对象,并且把这个"早期引用"并将其注入到容器中,让B先完成实例化,此时A就获取B的引用,完成实例化。

一级缓存:singletonObjects,存放完全实例化属性赋值完成的Bean,直接可以使用。
二级缓存:earlySingletonObjects,存放早期Bean的引用,尚未属性装配的Bean
三级缓存:singletonFactories,三级缓存,存放实例化完成的Bean工厂。

面试题2:@Resource和@Autowired有什么区别?

  •  @Autowired 根据类型注入
  • @Resource 默认根据名字注入,其次按照类型搜索
  • @Autowired @Qualifie("userService") 两个结合起来可以根据名字和类型注入,等同于@Resource

1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。

2.@Autowired默认按类型装配(byType),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用(@Autowired () @Qualifier ( "xxx" )功能同@Resource),如下:

@Autowired
@Qualifier ( "userDao" )
private UserDao userDao;

3.@Resource默认按照名称进行装配(byName),名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。如果name属性一旦指定,就只会按照名称进行装配。

@Resource (name= "baseDao" )
private BaseDao baseDao;

总结如下:

  • @Autowired默认按byType自动装配,而@Resource默认byName自动装配。
  • @Autowired只包含一个参数:required,表示是否开启自动注入,默认是true。而@Resource包含七个参数,其中最重要的两个参数是:name 和 type。
  • @Autowired如果要使用byName,需要使用@Qualifier一起配合。而@Resource如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配。
  • @Autowired能够用在:构造器、方法、参数、成员变量和注解上,而@Resource能用在:类、成员变量和方法上。
  • @Autowired是spring定义的注解,而@Resource是JSR-250定义的注解。

面试题3:Spring 的事务传播行为有哪些,都有什么作用?

简单来讲,就是当系统中存在两个事务方法时(我们暂称为方法A和方法B),如果方法B在方法A中被调用,那么将采用什么样的事务形式,就叫做事务的传播特性

比如,A方法调用了B方法(B方法必须使用事务注解),那么B事务可以是一个在A中嵌套的事务,或者B事务不使用事务,又或是使用与A事务相同的事务,这些均可以通过指定事务传播特性来实现。

传播行为 意义
propagation.REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则会启动一个新的事务
propagation.SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
propagation.MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
propagation.REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
propagation.NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
propagation.NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
propagation.NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与propagation.REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注三水点靠木的更多内容!


Tags in this post...

面试题 相关文章推荐
abstract class和interface有什么区别?
Jan 03 面试题
在Java开发中如何选择使用哪种集合类
Aug 09 面试题
2019年Java面试必问之经典试题
Sep 12 面试题
C++:局部变量能否和全局变量重名
Mar 03 面试题
2019年c语言经典面试题目
Aug 17 面试题
不用游标的SQL语句有哪些
Sep 07 面试题
触发器(trigger)的功能都有哪些?写出一个触发器的例子
Sep 17 面试题
渗透攻击的测试步骤
Jun 07 面试题
几个Linux面试题笔试题
Dec 01 面试题
Linux上比较文件的命令都有哪些
Feb 24 面试题
山海经纬软件测试笔试题和面试题
Apr 02 面试题
JSF界面控制层技术
Jun 17 面试题
Java面试题冲刺第十七天--基础篇3
Aug 07 #面试题
Java面试题冲刺第十六天--消息队列
Java面试题冲刺第十五天--设计模式
Promise面试题详解之控制并发
北京捷通华声语音技术有限公司Java软件工程师笔试题
Apr 10 #面试题
顺丰快递Java软件工程师面试题
Jul 31 #面试题
Java软件工程师综合面试题笔试题
Sep 08 #面试题
You might like
用PHP和ACCESS写聊天室(二)
2006/10/09 PHP
php小经验:解析preg_match与preg_match_all 函数
2013/06/29 PHP
Symfony页面的基本创建实例详解
2015/01/26 PHP
PHP与Perl之间知识点区别整理
2019/03/19 PHP
使用swoole 定时器变更超时未支付订单状态的解决方案
2019/07/24 PHP
PHP队列场景以及实现代码实例详解
2021/02/26 PHP
js删除所有的cookie的代码
2010/11/25 Javascript
jquery.tmpl JQuery模板插件
2011/10/10 Javascript
js将iframe中控件的值传到主页面控件中的实现方法
2013/03/11 Javascript
TypeScript Type Innference(类型判断)
2016/03/10 Javascript
jqGrid用法汇总(全经典)
2016/06/28 Javascript
JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用
2016/09/19 Javascript
神级程序员JavaScript300行代码搞定汉字转拼音
2017/05/20 Javascript
js数组实现权重概率分配
2017/09/12 Javascript
浅谈手写node可读流之流动模式
2018/06/01 Javascript
vue+echarts实现动态绘制图表及异步加载数据的方法
2018/10/17 Javascript
vue图片加载失败时用默认图片替换的方法
2019/08/29 Javascript
Python标准库与第三方库详解
2014/07/22 Python
10款最好的Web开发的 Python 框架
2015/03/18 Python
在Python下进行UDP网络编程的教程
2015/04/29 Python
详谈Python高阶函数与函数装饰器(推荐)
2017/09/30 Python
Python爬虫设置代理IP(图文)
2018/12/23 Python
python安装virtualenv虚拟环境步骤图文详解
2019/09/18 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
用纯css3实现的图片放大镜特效效果非常不错
2014/09/02 HTML / CSS
小橄榄树:Le Petit Olivier
2018/04/23 全球购物
北美领先的智能产品购物网站:Wellbots
2018/06/11 全球购物
俄罗斯茶和咖啡网上商店:Tea.ru
2021/01/26 全球购物
解释下列WebService名词:WSDL、SOAP、UDDI
2012/06/22 面试题
化学相关工作求职信
2013/10/02 职场文书
专业毕业生个性的自我评价
2013/10/03 职场文书
《乡下孩子》教学反思
2014/04/17 职场文书
加强作风建设演讲稿
2014/10/24 职场文书
六一领导慰问欢迎词
2015/01/26 职场文书
担保书怎么写 ?
2019/04/22 职场文书
python manim实现排序算法动画示例
2022/08/14 Python