《面试1v1》SpringBean生命周期

news2024/11/25 10:46:36

🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪
🍅 技术交流:定期更新Java硬核干货,不定期送书活动
🍅 王哥多年工作总结:Java学习路线总结, 点击 突击面试
🍅 数十万人的面试选择: 面试说人话系列《面试1v1》

在这里插入图片描述

我是 javapub,一名 Markdown 程序员从👨‍💻,八股文种子选手。


《面试1v1》 连载中…


面试官: 小伙子,听说你对 Spring Bean 生命周期比较熟悉,我们聊聊吧。Spring Bean 都有哪些生命周期阶段?

候选人: Spring Bean 的生命周期可以分为 5 个阶段:

  1. 实例化(Instantiation):Spring 使用 BeanDefinition 中的信息实例化 Bean。
  2. 属性赋值(Dependency injection):Spring 将 BeanDefinition 中配置的属性值注入到 Bean 中。
  3. 初始化前阶段(Post-Construct):如果 Bean 实现了 InitializingBean 接口,会调用 afterPropertiesSet() 方法。
  4. 初始化阶段(Initialization):如果在 BeanDefinition 中配置了 init-method,会调用该方法。
  5. 销毁阶段(Destruction):如果 Bean 实现了 DisposableBean 接口,会调用 destroy() 方法。如果配置了 destroy-method,会调用该方法。

面试官: 聪明!初始化方法有哪些?在源码层面,Spring 是如何调用这些方法的?

候选人: Spring Bean 提供了 3 种初始化方法:

  1. @PostConstruct:这是 JSR-250 注解,Spring 会在 Bean 初始化后自动调用被此注解标注的方法。
  2. InitializingBean 接口:这个接口只有一个方法 afterPropertiesSet(),Spring 会在 Bean 初始化后调用该方法。
  3. 自定义 init-method:在 BeanDefinition 中配置 init-method 属性,指向 Bean 中的某个方法名,Spring 会在 Bean 初始化后调用这个方法。

在源码层面,这些方法的调用是在 AbstractAutowireCapableBeanFactoryinitializeBean 方法中实现的:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // ...
        
    // 1. 处理 PostConstruct 注解
    if (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet")) {
        // 2. 实现了 InitializingBean 接口的 Bean 会调用 afterPropertiesSet() 方法
        if (bean instanceof InitializingBean) {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    // 3. 调用自定义的 init-method 
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) && 
            !(bean instanceof InitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
                Method initMethod = bean.getClass().getMethod(initMethodName);
                initMethod.invoke(bean);
        }
    }
}

面试官: 不错,你对 Spring Bean 的初始化过程很清楚!那销毁方法哪些?原理又是什么?

候选人: Spring Bean 提供了 2 种销毁方法:

  1. DisposableBean 接口:实现这个接口的 Bean 会调用 destroy() 方法。
  2. 自定义 destroy-method:在 BeanDefinition 中配置 destroy-method 属性,指向 Bean 中的某个方法名,Spring 会在 Bean 销毁前调用这个方法。

在源码层面,这些方法的调用是在 AbstractAutowireCapableBeanFactorydestroyBean 方法中实现的:

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    // 1. 实现了 DisposableBean 接口的 Bean 会调用 destroy() 方法
    if (bean != null) { 
        bean.destroy();
    }

    // 2. 调用自定义的 destroy-method
    String destroyMethodName = getDestroyMethodName(beanName);
    if (destroyMethodName != null) {
        Method destroyMethod = null;
        try {
            // 获取 destroy-method 方法对象
            destroyMethod = bean.getClass().getMethod(destroyMethodName); 
        } catch (NoSuchMethodException ex) {
            throw new BeanDefinitionStoreException(...);
        }
        
        // 调用方法
        try {
            if (destroyMethod != null) {
                destroyMethod.invoke(bean);
            }
        } catch (...) {
            throw new BeanCreationException(...); 
        }
    } 
    
}

面试官: 棒!最后,Spring Bean 的作用域都有哪些?如何控制 Bean 的生命周期?

候选人: Spring Bean 的作用域有 5 种:

  1. singleton:单例,整个 Spring 容器中只有一个 Bean 实例。
  2. prototype:原型,每次获取 Bean 都会创建一个新的实例。
  3. request:每个 HTTP 请求都会创建一个 Bean 实例。
  4. session:每个 HTTP 会话都会创建一个 Bean 实例。
  5. global-session:每个全局 HTTP 会话都会创建一个 Bean 实例。

我们可以通过 scope 属性控制 Bean 的作用域,从而影响其生命周期:

<bean id="..." class="..." scope="prototype"/>

此外,我们还可以自定义 Bean 的初始化和销毁方法,在 Bean 作用域开始和结束时触发:

<bean id="..." class="..." scope="prototype" 
    init-method="start" destroy-method="end">
</bean>

这样我们就可以在 start() 方法中执行初始化逻辑,在 end() 方法中执行清理工作,从而精确控制 Bean 的生命周期。

面试官: 很全面,佩服佩服!如果再给你一个机会,你觉得还可以在哪些方面加深对 Spring Bean 生命周期的理解?

候选人: 这里有几个方面可以进一步加深对 Spring Bean 生命周期的理解:

  1. BeanPostProcessor:这个接口可以监听 Bean 的初始化前后,提供了扩展点可以在 Bean 初始化前后进行一些处理。这也是 Spring AOP 的底层原理之一。
  2. 了解 BeanFactoryPostProcessor:这个接口可以监听 BeanDefinition 的加载,可以在 Bean 实例化前修改 BeanDefinition 的属性。
  3. 理解 Bean 的加载时机:在 Spring 容器启动时,默认会立即加载 singleton 作用域的 Bean,而其他作用域的 Bean 会延迟加载, singleton 作用域的 Bean 也支持延迟加载。这就要涉及到Spring 的 lazy-init 属性设置。
  4. 了解 Bean 为什么要有不同的作用域:每个作用域适合的场景是什么,选择不同作用域会对 Bean 的生命周期产生怎样的影响。
  5. 了解 Bean 之间的依赖关系对生命周期的影响:比如 A Bean 的初始化依赖 B Bean,那么 A Bean 的初始化也会延迟到 B Bean 初始化完毕后。这涉及到 Spring 的 depends-on 属性配置。
  6. 了解自定义初始化和销毁方法的具体应用场景:什么情况下需要自定义这些方法,能在方法中完成什么样的逻辑处理。
  7. 探索 BeanPostProcessor 和 BeanFactoryPostProcessor 的具体应用:比如 Spring AOP、Spring 事件发布者等机制的实现。
    综上,要全面理解 Spring Bean 的生命周期,除了知道每个阶段的调用外,还需要对很多这个过程涉及到的其他知识点进行深入学习和理解,这需要不断实践和总结。但只要把这些要点都串联起来,对 Spring Bean 的生命周期控制就会很得心应手了。

面试官: 非常棒,这些点精彩极了!你的回答已经很全面和深入,对 Spring Bean 生命周期有清晰理解,这些又是常见的面试重点,我相信面试一定会取得很好的表现,加油!我们就聊到这里,很高兴与你的交流,谢谢!

最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!


《面试1v1》 连载中…


🎁目录合集:

Gitee:https://gitee.com/rodert/JavaPub

GitHub:https://github.com/Rodert/JavaPub

http://javapub.net.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/668031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python:使用Scikit-image对遥感影像进行边缘检测(edges)

作者:CSDN @ _养乐多_ 本文将介绍使用Scikit-image库中用于边缘检测特征提取的一些方法及其代码。方法包括 Canny边缘检测(canny),Sobel边缘检测(sobel),Scharr边缘检测(scharr), Roberts边缘检测(roberts),Prewitt边缘检测(prewitt),Farid边缘检测(farid),…

HJ48 从单向链表中删除指定值的节点

描述 输入一个单向链表和一个节点的值&#xff0c;从单向链表中删除等于该值的节点&#xff0c;删除后如果链表中无节点则返回空指针。 链表的值不能重复。 构造过程&#xff0c;例如输入一行数据为: 6 2 1 2 3 2 5 1 4 5 7 2 2 则第一个参数6表示输入总共6个节点&am…

Day24 实战篇 ——Jmeter通过JDBC测试实战

Day24 实战篇 ——Jmeter通过JDBC测试实战 文章目录 Day24 实战篇 ——Jmeter通过JDBC测试实战1、**业务级脚本开发**2、**接口级脚本开发**3、**JDBC脚本开发**4、**JMS Point-to-Poibt脚本开发**5、**Jmeter轻量级接口自动化测试框架**(了解就行)1、业务级脚本开发 登录脚…

《2023 年 React 生态》

大家好&#xff0c;我是 Chocolate。 前不久看到一篇不错的内容&#xff0c;来自于 The React Ecosystem in 2023&#xff0c;也结合自己今年使用的 React 生态总结一下。 本文并非视频演讲稿&#xff0c;和视频内容还是有一点点区别&#xff0c;视频内容相对来说会更加详细一…

ffmpeg(一) ffmpeg+QT开发环境搭建

1、开发库的选择 &#xff08;1&#xff09;音视频开发库 每个主流平台基本都有自己的音视频开发库&#xff08;API&#xff09;&#xff0c;用以处理音视频数据&#xff0c;比如&#xff1a; iOS&#xff1a;AVFoundation、AudioUnit 等 Android&#xff1a;MediaPlayer、Me…

Flink 学习九 Flink 程序分布式运行部署

Flink 学习九 Flink 程序分布式运行部署 1.Job 执行计划 层级说明备注StreamGraph用户代码生成的最初的图程序的运行流程图JobGraph将多个符合条件的节点多个符合条件的节点合并,减少序列化和反序列化ExecutionGraphJobGraph 的并行化调度层的核心数据结构PhysicalGraphJobMa…

【计算机组成原理】信息编码与数据表示

目录 一、进位计数制 二、信息编码 三、定点数的表示 四、校验码 五、浮点数的表示 一、进位计数制 整数部分&#xff1a; 二进制、八进制、十六进制 ---> 十进制&#xff1a;加权求和二进制 ---> 八进制&#xff1a;每三位分为一组&#xff0c;转为八进制…

CloFormer实战:使用CloFormer实现图像分类任务(一)

文章目录 摘要安装包安装efficientnet_pytorch安装timm安装 grad-cam 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文翻译&#xff1a;https://blog.csdn.net/m0_47867638/article/details/131161083 官方源码&#xff1a;https://github.com/qhfan/CloF…

faceswap安装教程图文详解

Faceswap是一种人脸识别技术&#xff0c;可以将一个人的面部特征与另一个人的面部特征进行交换&#xff0c;从而创建出一个看起来像是两个人融合在一起的图像或视频。这项技术可以用于各种目的&#xff0c;包括艺术创作、电影制作、虚拟现实、安全监控等领域。Faceswap的实现方…

UE特效案例 —— 寒冰武器

一&#xff0c;环境配置 创建默认地形Landscape&#xff0c;如给地形上材质需确定比例&#xff1b;添加环境主光源DirectionalLight&#xff0c;设置相应的强度和颜色&#xff1b;PostProcessVolume设置曝光&#xff0c;设置Min/Max Brightness为1&#xff1b; 与关闭Game Sett…

怎样开始用selenium进行自动化测试?

如果您刚开始使用 Selenium 进行自动化测试&#xff0c;以下是建议的步骤。 1、安装 Selenium 首先&#xff0c;您需要安装 Selenium。Selenium 支持多种编程语言&#xff0c;如 Python、Java、C# 等。可以通过 pip 命令在 Python 中安装 Selenium&#xff1a; pip install …

CloFormer实战:使用CloFormer实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整算法设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试热力图可视化展示…

秀米编辑器(xiumi)+百度编辑器(Ueditor) 集成 :解决集成问题,秀米编辑器导出到百度编辑器格式问题,图片保存到自己的服务器(阿里云OSS)

1.集成前提条件&#xff1a; 1. 需要集成百度编辑器到环境中 2.https环境下才可以导出数据到百度编辑器&#xff0c;如果不是https环境&#xff0c;会出现错误 然后我们开始讲解如何集成&#xff1a; 2.引入资源&#xff1a; //百度编辑器需要修改的文件&#xff08;配置与原始…

测试入门第一步------编写接口测试用例

自动化始终只是辅助测试工作的一个手段&#xff0c;对于测试人员而言&#xff0c;测试基础和测试用例的设计才是核心。如果测试用例的覆盖率或者质量不高&#xff0c;那将这部分用例实现为自动化用例的意义也就不大了。 那么&#xff0c;接口测试用例应该怎么编写呢&#xff1…

Spring boot集成RabbitMq

Spring boot集成RabbitMq 一、搭建RabbitMq1.1 参考1.2 配置erlong的环境变量1.3 RabbitMQ对应的在注册表中的位置 二、使用教程2.1 打开服务端2.2 注意的问题2.3 Queue的包 三、git命令3.1 git remote3.2 git remote add origin "xxxx"3.3 git push -u origin maste…

使用esp32+micropython+microdot搭建web(http+websocket)服务器(超详细)第一部分

使用esp32micropythonmicrodot搭建web(httpwebsocket)服务器&#xff08;超详细&#xff09;第一部分 microdot文档速查 什么是Microdot?Microdot是一个可以在micropython中搭建物联网web服务器的框架micropyton文档api速查 Quick reference for the ESP32 先来个小demo先体…

数据仓库——原理+实战(一)

一、数据仓库概述 1. 数据仓库诞生原因 &#xff08;1&#xff09;历史数据积存&#xff08;存放在线上业务数据库中&#xff0c;当数据积压到一定程度会导致性能下降&#xff0c;所以需要将实用频率低的冷数据转移到数据仓库中&#xff09; &#xff08;2&#xff09;企业数…

【C++11】线程库

文章目录 1. get_idthis_thread 2. 锁1. 为什么要使用锁&#xff1f;2. 锁的使用并行 与 串行递归锁 recursive_mutextimed_mutexlock_guard 与 unique_lock 3. atomic4. 条件变量线程等待线程唤醒条件变量的应用问题1&#xff1a;如何保证 v1先运行&#xff0c;v2阻塞&#xf…

python的tqdm一些操作

主要参数 iterable: 可迭代的对象, 在手动更新时不需要进行设置 desc: str, 左边进度条的描述性文字 total: 总的项目数 leave: bool, 执行完成后是否保留进度条 file: 输出指向位置, 默认是终端, 一般不需要设置 ncols: 调整进度条宽度, 默认是根据环境自动调节长度, 如果设置…

VUE 2X 事件处理 ⑤

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs E v e n t j s Eventjs Eventjs总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ ⡖⠒⠒⠒⠤⢄⠀⠀⠀…