Spring必问-bean生命周期和循环依赖

chatgpt回答

Spring Bean 的生命周期可分为以下阶段:

  1. 实例化:Spring容器根据配置文件或者注解等方式创建一个 Bean 实例,它是一个普通的 Java 对象。
  2. 属性赋值:Spring 容器通过 setter 方法或者构造器为 Bean 实例的属性赋值。
  3. BeanPostProcessor 前置处理:Spring 容器调用实现了 BeanPostProcessor 接口的类的 postProcessBeforeInitialization 方法,该方法在 Bean 实例化之后、初始化之前被调用,用于对 Bean 实例进行加工处理。
  4. 初始化:Spring 容器调用 Bean 实例的初始化方法,可以在 Bean 上使用 @PostConstruct 注解或者实现 InitializingBean 接口来指定初始化方法。
  5. BeanPostProcessor 后置处理:Spring 容器调用实现了 BeanPostProcessor 接口的类的 postProcessAfterInitialization 方法,该方法在 Bean 实例化之后、初始化之后被调用,用于对 Bean 实例进行加工处理。
  6. 使用:Spring 容器将 Bean 实例注入到其他 Bean 中或者在 BeanFactory 中管理,应用程序可以通过 ApplicationContext 获取 Bean 实例。
  7. 销毁:Spring 容器调用 Bean 实例的销毁方法,可以在 Bean 上使用 @PreDestroy 注解或者实现 DisposableBean 接口来指定销毁方法。

Spring 通过三级缓存解决循环依赖问题。当创建 Bean 实例时,Spring 会检查当前创建的 Bean 是否有依赖其他 Bean,如果有依赖,则会尝试从缓存中获取依赖的 Bean,如果缓存中没有,则会创建依赖的 Bean。

如果依赖的 Bean 也依赖当前 Bean,就会产生循环依赖。为了解决这个问题,Spring 采用了三级缓存:

  1. singletonObjects:缓存已经创建好的单例 Bean 实例。
  2. earlySingletonObjects:缓存正在创建中的 Bean 实例,还未进行属性注入。
  3. singletonFactories:缓存 Bean 工厂对象,用于解决循环依赖。

当 Spring 创建 Bean 实例时,会先将正在创建的 Bean 实例放入 earlySingletonObjects 缓存中,然后再创建依赖的 Bean 实例,如果依赖的 Bean 也依赖当前 Bean,就会从 singletonFactories 缓存中获取 Bean 工厂对象,通过工厂方法创建一个代理对象,再进行属性注入和初始化。

最后,再将创建好的 Bean 实例放入 singletonObjects 缓存中,并从 earlySingletonObjects 缓存中移除。这样就能够解决循环依赖问题。

#你觉得今年春招回暖了吗#
全部评论
感谢大佬分享
1 回复 分享
发布于 2023-03-16 19:03 四川
马了学习一下
点赞 回复 分享
发布于 2023-03-16 18:18 山东
简单概括: 实例化:配置⽂件找定义,利用反射建实例。 属性赋值:有值则用set()设置,再看有无Awar,如有则调相关set()。 初始化: 如果有以下配置,则将执行对应method。 若载BeanPostProcessor(),执⾏ postProcessBeforeInitialization() 。 如有实现InitializingBean ,行 afterPropertiesSet() 配置⽂件有定义,相关 init-method 属性的,则将执⾏指定⽅法。 如有加载BeanPostProcessor 对象,执⾏ postProcessAfterInitialization() ⽅法 ————这里就可以使用这个bean了———— 销毁: 如果实现DisposableBean 接⼝,执⾏ destroy() ⽅法。 配置⽂件有定义,相关 destroy-method 属性的,执⾏指定的⽅法。 作者:朝书暮省 链接:https://www.jianshu.com/p/fd8dc1e0d30e 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
点赞 回复 分享
发布于 2023-03-17 13:45 日本
Bean 的实例化通常由容器负责,在容器启动时,根据配置文件或注解信息,容器会创建一个或多个 Bean 实例。 实例化 Bean 的过程通常可以分为以下两种方式: 使用构造方法实例化:容器根据配置文件或注解信息,调用 Bean 对应的构造方法创建一个新的实例。这个过程通常涉及到依赖注入和参数解析等操作,以确保实例被正确地创建和初始化。 使用工厂方法实例化:容器根据配置文件或注解信息,调用 Bean 工厂中的工厂方法创建一个新的实例。这个过程通常涉及到依赖注入、参数解析和一些额外的初始化操作,以确保实例被正确地创建和初始化。 在 Spring 框架中,Bean 的实例化过程通常由 BeanFactory 和 ApplicationContext 接口负责管理和控制,它们提供了各种方法和回调函数用于实现 Bean 的实例化。例如,BeanFactory 提供了 getBean() 方法,用于从容器中获取指定名称的 Bean 实例;ApplicationContext 则提供了更多的方法和事件类型,用于处理更加复杂的实例化需求。
点赞 回复 分享
发布于 2023-03-17 13:46 日本

相关推荐

2024-12-12 16:52
中山大学 Java
面试总共分为 。一面为技术面 ,侧重于八股基础 ;二面为技术面 ,侧重于项目细节和场景题考验 ;三面为技术面 ,侧重于八股基础 ;四面为HR面 。一面:面试内容:1.垃圾回收器,cms2.垃圾回收机制3.Redis,单线程模型结构,阻塞,Zset,哨兵模式,大 Key 问题会影响内存性能吗4.MQ 使用场景5.Spring 循环依赖,有没有遇到过,怎么定位,怎么解决6.Maven 传递依赖,有什么具体的问题7.Spring MVC手撕代码:反转链表面试体验:一面对项目不做深挖,主要考查八股,除了以上问题以外数据库问的也多,但都是比较常见的点,如mvcc、索引、事务等问题。二面:面试内容:1.项目难点2.拦截器用的是Spring还是Servlet3.SpringAOP拦截器什么情况下会失效4.JDK和CGLIB区别5.ThreadLocal具体什么情况下取加密字段6.如果字段被拦截了怎么办,怎么保证安全性,网关层面做了加密,那如果让你来加密,你会怎么做7.场景图:如果要设计一个定时器,用什么数据结构8.算法:字符串转Integer,遇到超出范围的数据怎么办,数据越界怎么办 面试体验:压力最大的一面,对应的面试官所在的组应该就是最终的组。二面基本不问寻常八股,都是从项目的角度延伸开来问问题,我的项目的亮点是拦截器方案的改进,所以就针对这部分做深入挖掘。场景题没有标准答案,答数组、堆等都可以,但会针对这种数据结构里面的缺陷和某种场景反问,让你一步一步打补丁修正答案,最后提出了时间轮的数据结构概念。三面:面试内容:1. Transactional注解什么时候会失效?基于原理2. binlog 什么用途3. jvm,分为哪几个区域,哪个区域会发生内存溢出4. hashmap 源码看过吗,扩容原理,扩容过程5. 什么情况下,走不到索引上6. 怎么定位线程死锁,怎么解决7. 线程池,常见参数,工作队列的大小怎么定,线程数怎么定面试体验:三面像交叉面,没有深入问之前的问题,还是以检验基础八股为主,时间较短,没有手撕。四面:面试内容:1. 自我介绍2. 职业规划3. 为什么偏向于选择支付方向4.  目前手头有哪些offer,签约了吗面试体验:常规HR面,没有开摄像头。
查看26道真题和解析
点赞 评论 收藏
分享
评论
2
80
分享
牛客网
牛客企业服务