写点什么

Java 岗大厂面试百日冲刺 - 日积月累,每日三题【Day26

  • 2022 年 4 月 18 日
  • 本文字数:1681 字

    阅读完需:约 6 分钟

本栏目 Java 开发岗高频面试题主要出自以下各技术栈:Java基础知识集合容器并发编程JVMSpring全家桶MyBatis等ORMapping框架MySQL数据库Redis缓存RabbitMQ消息队列Linux操作技巧等。


[](()面试题 1:Bean 的加载过程是怎样的?


===================================================================================


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


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

  • 加载,通过解析完的定义信息获取 Bean 实例。


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





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


  1. 获取 BeanName,对传入的 name 进行解析,转化为可以从 Map 中获取到 BeanDefinition 的 bean name。

  2. 合并 Bean 定义,对父类的定义进行合并和覆盖,如果父类还有父类,会进行递归合并,以获取完整的 Bean 定义信息。

  3. 实例化,使用构造或者工厂方法创建 Bean 实例。

  4. 属性填充,寻找并且注入依赖,依赖的 Bean 还会递归调用 getBean 方法获取。

  5. 初始化,调用自定义的初始化方法。

  6. 获取最终的 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 工厂。




! Java 开源项目【ali1024.coding.net/public/P7/Java/git】 [在这里插入图片描述](()


课间休息,来秀一下新加入的一名家庭成员,小哈!来的第二天睡觉就如此妖娆了么~




《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源


[](()面试题 2:@Resource 和 @Autowired 有什么区别?


==============================================================================================


  • @Autowired 根据类型注入

  • @Resource 默认根据名字注入,其次按照类型搜索

  • @Autowired @Qualifie("userService") 两个结合起来可以根据名字和类型注入,等同于 @Resource


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

读者福利

分享一份自己整理好的 Java 面试手册,还有一些面试题 pdf


不要停下自己学习的脚步




用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day26_Java_爱好编程进阶_InfoQ写作平台