当前位置: 首页 > news >正文

spring6-bean的生命周期与循环依赖

bean的生命周期

粗略划分5步

  1. 实例化bean

调用的是无参数的构造方法

  1. bean属性赋值

执行set注入

  1. 初始化bean

调用bean的init()方法,需要自己写,自己配

  1. 使用bean

  2. 销毁bean

调用bean的destroy(),需要自己写,自己配

注意:自定义的init()和destroy()需要在配置文件配置

<!--    init-method指定初始化方法,destroy-method指定销毁方法-->
<!--    这两个方法需要在bean类中定义--><bean id="user" class="com.ali.bean.User" init-method="initBean" destroy-method="destroyBean"></bean>

进一步七步

在以上的5步中,第三步是初始化bean。其实可以在初始化之前和初始化之后添加代码。此时,需要加入“Bean后处理器”。

编写一个类实现BeanPostProcessor类,并重写before和after方法

  1. 实例化bean

调用的是无参数的构造方法

  1. bean属性赋值

执行set注入

  1. 执行“Bean后处理器”的before方法
  2. 初始化bean

调用bean的init()方法,需要自己写,自己配

  1. 执行“Bean后处理器”的after方法

  2. 使用bean

  3. 销毁bean

// 日志类bean后处理器
public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("BeanPostProcessor befor方法");return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("BeanPostProcessor after方法");return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}
<!--  配置bean后处理器这个bean后处理器会在bean实例化后和初始化前后执行相应的方法例如可以在bean初始化前后打印日志需要实现BeanPostProcessor接口这样spring容器在创建其他bean时会自动调用这个后处理器的相应方法例如上面的springBean在实例化和初始化时就会调用LogBeanPostProcessor中的方法这样就可以在控制台看到日志输出这个bean后处理器必须配置在spring配置文件中,才能被spring容器识别和调用这个bean后处理器将作用于当前配置文件中的所有bean--><bean class="com.ali.bean.LogBeanPostProcessor" />

精细化分为10步

  1. 实例化bean

调用的是无参数的构造方法

  1. bean属性赋值

执行set注入

  1. 检查bean是否实现Aware相关接口(BeanNameAware, BeanClassLoaderAware, BeanFactoryAware),如果实现了,则调用这些接口相关的方法。

  2. 执行“Bean后处理器”的before方法

  3. 检查bean是否实现InitializingBean接口,并调用接口方法

  4. 初始化bean

调用bean的init()方法,需要自己写,自己配

  1. 执行“Bean后处理器”的after方法

  2. 使用bean

  3. 检查bean是否实现了DisposableBean接口,并调用接口方法

  4. 销毁bean

调用bean的destroy(),需要自己写,自己配

spring容器只对singleton的bean进行完整的生命周期管理。

如果是prototype作用域的bean,spring容器只负责初始化完毕,等客户端程序一旦获取到该bean后,spring容器就不再管理该对象的声明周期了。

自己new的对象如何让spring容器管理

使用DefaultListableBeanFactory类注入自己创建的对象。

public static void main(String[] args) {User user = new User();System.out.println(user);// 将以上new的对象交给spring容器管理DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();beanFactory.registerSingleton("userBean", user);// 从spring容器中获取Object userBean = beanFactory.getBean("userBean");System.out.println(userBean);
}

bean的循环依赖问题

bean的循环依赖:A对象中有B属性。B对象中有A属性。这种你依赖我,我依赖你的情况就是循环依赖。

singleton+setter模式

<!--    singleton+setter方式解决循环依赖-->
<!--     通过setter方法注入依赖,可以解决循环依赖问题 -->
<!--     spring容器在创建bean时会先实例化bean对象,然后通过setter方法注入依赖-->
<!--     这样即使存在循环依赖,spring也能正确创建和注入bean--><bean id="husbandBean" class="com.ali.bean.Husband" ><property name="name" value="Jack"/><property name="wife" ref="wifeBean"/></bean><bean id="wifeBean" class="com.ali.bean.Wife" ><property name="name" value="Rose"/><property name="husband" ref="husbandBean"/></bean>
在这种模式(singleton+setter)下主要分为2个阶段来解决:1. 在spring容器加载的时候,实例化bean。只要其中任意一个bean实例化之后,马上进行“曝光”【不等属性赋值就曝光】2. bean“曝光”后再进行赋值

prototype+setter模式

<!--    在prototype+setter方式下无法解决循环依赖问题,会出现异常因为prototype作用域下,spring容器不会缓存bean实例,每次获取都会创建一个新的实例这样当husbandBean实例化时,wifeBean还没有被创建,导致无法注入wifeBean反之亦然,最终会导致循环依赖失败,抛出异常所以prototype作用域下不支持循环依赖但是:当2个bean的scope不同时(其中任意一个是singleton)是可以的例如下面的配置中,husbandBean是singleton作用域,wifeBean是prototype作用域这样在创建husbandBean时,wifeBean会被创建并注入但是每次获取wifeBean时,都会创建一个新的实例这样就避免了循环依赖的问题因为singleton只会创建一次,而prototype每次获取都会创建新的实例所以这种组合方式是可行的--><bean id="husbandBean" class="com.ali.bean.Husband" scope="singleton"><property name="name" value="Jack"/><property name="wife" ref="wifeBean"/></bean><bean id="wifeBean" class="com.ali.bean.Wife"  scope="prototype"><property name="name" value="Rose"/><property name="husband" ref="husbandBean"/></bean>
http://www.jsqmd.com/news/339773/

相关文章:

  • 当计算机专业站在十字路口:近屿智能看见了什么?
  • ViT图像分类-中文-日常物品GPU算力优化教程:4090D高效部署方案
  • TDengine TSDB 3.4.0.0 上线:虚拟表、流计算性能显著提升,安全能力全面进阶
  • Qwen3-Reranker-0.6B实战教程:Python API调用+批量文档重排代码实例
  • 大数据分析:Spark与Hadoop的对比与结合
  • CCMusic Dashboard效果展示:AI识别出‘雷鬼’音乐中反拍节奏在时频域的稀疏能量分布
  • Chord基于Qwen2.5-VL的视觉定位参数详解:max_new_tokens与精度平衡
  • 解读大数据领域HDFS的元数据管理
  • Qwen3-ASR-0.6B实战:如何用Gradio搭建语音识别Web界面
  • 开源大模型部署新趋势:Qwen2.5镜像免配置实操手册
  • ClearerVoice-Studio模型热切换:Web界面动态加载FRCRN/MossFormer2实操
  • 阿里每日100W次登录请求场景下的JVM参数优化配置详解
  • 从RNN到LSTM:循环神经网络的进化之路
  • 雀巢赋能创新:徐福记投建智能软糖车间,筑牢春节市场保障
  • div水平垂直居中
  • 《揭秘!AI应用架构师如何实现AI系统集成的卓越最佳实践》
  • 小白也能轻松玩转:yz-女生-角色扮演模型的5个实用技巧
  • 文库、网盘业务重组,百度剑指AI to C话语权
  • SeqGPT-560M零样本应用:电商评论自动分类实战
  • StringRedisTemplate简单操作redis
  • 从BLIP到Deepbooru:揭秘AI图像标注背后的语言学博弈
  • MetaTube效能提升指南:解决媒体库管理难题的7个实战方案
  • AI读脸术JavaScript调用:前端直接集成可能性分析
  • 【网络攻防】ARP 欺骗深度解析:双向欺骗 + arpspoof,轻松达成 100% 断网操作!
  • Qwen3-4B-Instruct企业应用:技术文档自动生成与代码辅助开发
  • HG-ha/MTools一文详解:开源桌面AI套件在中小企业内容生产中的落地实践
  • MusePublic艺术创作引擎保姆级教程:从安装到生成首张高清人像
  • Spark代码规范指南:写出高性能Spark应用的最佳实践
  • LongCat-Image-Editn镜像免配置原理:预置Gradio+torch+transformers全栈依赖
  • Pi0具身智能v1网络通信:TCP/IP协议栈优化实践