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...

面试题 相关文章推荐
宝信软件JAVA工程师面试经历
Aug 19 面试题
如何设置Java的运行环境
Apr 05 面试题
程序运行正确, 但退出时却"core dump"了,怎么回事
Feb 19 面试题
编写类String的构造函数、析构函数和赋值函数
May 29 面试题
上海中网科技笔试题
Feb 19 面试题
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
Jan 13 面试题
敏捷开发的主要原则都有哪些
Apr 26 面试题
Python面试题:如何用Python来发送邮件
Mar 15 面试题
String s = new String(“xyz”);创建了几个String Object?
Aug 05 面试题
设置器与访问器的定义以及各自特点
Jan 08 面试题
创立科技Java面试题
Nov 29 面试题
与UNIX有关的几个名词
Sep 17 面试题
Java面试题冲刺第十七天--基础篇3
Aug 07 #面试题
Java面试题冲刺第十六天--消息队列
Java面试题冲刺第十五天--设计模式
Promise面试题详解之控制并发
北京捷通华声语音技术有限公司Java软件工程师笔试题
Apr 10 #面试题
顺丰快递Java软件工程师面试题
Jul 31 #面试题
Java软件工程师综合面试题笔试题
Sep 08 #面试题
You might like
PHP+DBM的同学录程序(2)
2006/10/09 PHP
PHP中10个不常见却非常有用的函数
2010/03/21 PHP
解析php中var_dump,var_export,print_r三个函数的区别
2013/06/21 PHP
ThinkPHP的模版中调用session数据的方法
2014/07/01 PHP
php单例模式示例分享
2015/02/12 PHP
使用PHP连接多种数据库的实现代码(mysql,access,sqlserver,Oracle)
2016/12/21 PHP
php实现自定义中奖项数和概率的抽奖函数示例
2017/05/26 PHP
JavaScript中判断数据类型的方法总结
2016/05/24 Javascript
angularjs过滤器--filter与ng-repeat配合有奇效
2017/04/20 Javascript
使用vue-resource进行数据交互的实例
2017/09/02 Javascript
vue中路由验证和相应拦截的使用详解
2017/12/13 Javascript
JS实现运动缓冲效果的封装函数示例
2018/02/18 Javascript
Vue2.0 v-for filter列表过滤功能的实现
2018/09/07 Javascript
微信小程序 this.triggerEvent()的具体使用
2019/12/10 Javascript
Vuex实现简单购物车
2021/01/10 Vue.js
vue 计算属性和侦听器的使用小结
2021/01/25 Vue.js
python实现sublime3的less编译插件示例
2014/04/27 Python
Python中的模块和包概念介绍
2015/04/13 Python
python列表list保留顺序去重的实例
2018/12/14 Python
python实现飞机大战游戏
2020/10/26 Python
python找出一个列表中相同元素的多个索引实例
2019/06/11 Python
Python实现微信中找回好友、群聊用户撤回的消息功能示例
2019/08/23 Python
使用OpenCV circle函数图像上画圆的示例代码
2019/12/27 Python
django创建css文件夹的具体方法
2020/07/31 Python
解决pycharm不能自动保存在远程linux中的问题
2021/02/06 Python
大码女装:Ulla Popken
2019/08/06 全球购物
文秘专业自荐信
2013/10/14 职场文书
制冷与电控专业应届生求职信
2013/11/11 职场文书
中文系学生自荐信范文
2013/11/13 职场文书
2014道德模范事迹材料
2014/02/16 职场文书
教师工作总结范文2014
2014/11/10 职场文书
出国留学自荐信模板
2015/03/06 职场文书
思想道德自我评价2015
2015/03/09 职场文书
卫生保健工作总结2015
2015/05/18 职场文书
golang中字符串MD5生成方式总结
2021/07/04 Golang
从结婚开始的恋爱故事。小说《我的美好婚事》TV动画化决定
2022/04/07 日漫