关于java:Java面试题冲刺第十八天Spring框架3

5次阅读

共计 3172 个字符,预计需要花费 8 分钟才能阅读完成。

面试题 1:Bean 的加载过程是怎么的?
咱们晓得,Spring 的工作流次要包含以下两个环节:

解析,读 xml 配置,扫描类文件,从配置或者注解中获取 Bean 的定义信息,注册一些扩大性能。
加载,通过解析完的定义信息获取 Bean 实例。
上面是跟踪了 getBean 的调用链创立的流程图,为了可能很好地了解 Bean 加载流程,省略一些异样、日志和分支解决和一些非凡条件的判断。

从下面的流程图中,能够看到一个 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,这就造成了一个循环依赖。如果是办法调用是不算循环依赖的,循环依赖必须要持有援用。

循环依赖产生的场景:

结构器循环依赖:依赖的对象是通过结构器传入的,产生在实例化 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 一样。留神各厂商对这种流传行为的反对是有所差别的。能够参考资源管理器的文档来确认它们是否反对嵌套事务

正文完
 0