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

探索InitializingBean:Spring框架中的隐藏宝藏

​🌈 个人主页:danci_
🔥 系列专栏:《设计模式》《MYSQL》
💪🏻 制定明确可量化的目标,坚持默默的做事。


✨欢迎加入探索MYSQL索引数据结构之旅✨

    👋 Spring框架的浩瀚海洋中,InitializingBean如同一颗闪闪发光的珍珠,等待被你发现。这一隐藏的宝藏,能够让你的Spring应用在初始化时更灵活、可控。本篇文章将带你深入探索InitializingBean的奥秘,揭示其在Spring生命周期中的重要作用,让你的开发之路更加顺畅高效。准备好开启这段奇妙的探索之旅了吗?让我们一起揭开InitializingBean的神秘面纱吧!


目录

一、环境

二、示例

2.1、说明

三、执行过程

3.1 源码解析


一、环境

  • jdk: 1.8
  • spring-boot: 2.7.1

二、示例

@Component
public class TestInit implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("调用TestInit.afterPropertiesSet方法");}
}

运行结果:

2.1、说明

  • springboot提供InitializingBean接口,用户可以实现之来自定义初始化操作
  • 实现InitializingBean接口重写afterPropertiesSet方法并注册到spring容器中,创建实例后即可触发执行自定义初始化操作

三、执行过程

       一直很好奇和想弄清楚什么时候调扩展点afterPropertiesSet()方法呢?用什么方式调用?

为满足好奇,启动一个简单springboot项目跟踪源码执行过程如下:

   

3.1 源码解析

1. Springboot项目启动入口SpringApplication.run

public ConfigurableApplicationContext run(String... args) {// 记录启动开始时间long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 准备ApplicationContextConfigurableApplicationContext context = null;configureHeadlessProperty();// 从spring.factories 中获取监听器SpringApplicationRunListeners listeners = getRunListeners(args);// 发布事件listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 环境参数ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置设置进系统参数configureIgnoreBeanInfo(environment);// 输出bannerBanner printedBanner = printBanner(environment);// 创建applicationContext IOC容器context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);// 准备上下文IOC容器,设置了一系列的属性值prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 308行,启动spring容器refreshContext(context);// 刷新后的处理afterRefresh(context, applicationArguments);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}// 发布事件listeners.started(context, timeTakenToStartup);// 调用 runner,实现了 ApplicationRunner或CommandLineRunner 的接口callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}

这里关注调refreshContext(context)来启动容器

 2. SpringApplication.refreshContext启动容器

protected void refresh(ConfigurableApplicationContext applicationContext) {// 734行applicationContext.refresh();}

然后调AbstractApplicationContext.refresh()来启动Spring容器

3. AbstractApplicationContext.refresh()启动Spring容器

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 启动容器前准备。启动时间、状态和环境等prepareRefresh();// 告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备在上下文中使用bean工厂prepareBeanFactory(beanFactory);try {// 允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 调用在上下文中注册为bean的工厂处理器invokeBeanFactoryPostProcessors(beanFactory);// 注册拦截bean创建的bean处理器。registerBeanPostProcessors(beanFactory);beanPostProcess.end();// 为此上下文初始化消息源。initMessageSource();// 初始化事件广播器initApplicationEventMulticaster();// 初始化特定上下文子类中的其他特殊bean。onRefresh();// 注册事件监听器registerListeners();// 583行,实例化所有剩余的(非lazy-init)单例finishBeanFactoryInitialization(beanFactory);// 完成启动操作finishRefresh();}catch (BeansException ex) {...}finally {resetCommonCaches();contextRefresh.end();}}
}

列出了Spring容器启动的整个过程。本例关注InitializingBean扩展点,其它内容不详细解读。 实例化所有剩余的(非lazy-init)单例 finishBeanFactoryInitialization(beanFactory);

4. AbstractApplicationContext.finishBeanFactoryInitialization(...)初始化(非lazy-init)单例

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {...// 918行,实例化所有剩余的(非lazy-init)单例。beanFactory.preInstantiateSingletons();
}

调bean工厂类的preInstantiateSingletons方法来实例化bean

5. ConfigurableListableBeanFactory.preInstantiateSingletons()实例化bean

@Override
public void preInstantiateSingletons() throws BeansException {...// 955行,获取beangetBean(beanName);...
}

这里由调父父类AbstractBeanFactory.getBean来获取bean

6.AbstractBeanFactory.getBean(beanName)获取bean

public Object getBean(String name) throws BeansException {// 208行return doGetBean(name, null, null, false);
}

然后调本类doGetBean(...)方法获取bean

7. AbstractBeanFactory.doGetBean获取bean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {...// 332行,创建bean实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {...}});...}...}return adaptBeanInstance(name, beanInstance, requiredType);
}

然后调子类的createBean来创建实例

8.AbstractAutowireCapableBeanFactory.createBean(...)创建实例

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {...// 542行doCreateBean(beanName, mbdToUse, args);...
}

调本类doCreateBean

9.AbstractAutowireCapableBeanFactory.doCreateBean(...)执行创建bean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {...// 实例化 Bean// 解决循环依赖问题, 是否允许循环依赖 等...// 属性装配, 即自动注入populateBean(beanName, mbd, instanceWrapper);// 620行,应用工厂回调以及初始化方法和bean后处理程序。// 例如init-method、InitializingBean 接口、BeanPostProcessor 接口exposedObject = initializeBean(beanName, exposedObject, mbd);...
}

10. AbstractAutowireCapableBeanFactory.initializeBean处理初始化完成处理

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {...// 方法回调invokeInitMethods(beanName, wrappedBean, mbd);...
}

11. AbstractAutowireCapableBeanFactory.invokeInitMethods实例的方法回调处理

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);// 判断为InitializingBean的实现类,且重写afterPropertiesSet方法,则调afterPropertiesSet方法if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {...((InitializingBean) bean).afterPropertiesSet();...}...
}

到此,探索InitializingBean已完。

ps: 以上是研读源码加上翻阅许多文献理解的总结,如有错误或不足的地方,欢迎指出,欢迎留言交流。我会继续努力学习和分享更多有干货的内容。

相关文章:

探索InitializingBean:Spring框架中的隐藏宝藏

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索MYSQL索引数据结构之旅✨ &#x1f44b; Spring框架的浩瀚海洋中&#x…...

JVM专题之垃圾收集算法

标记清除算法 第一步:标记 (找出内存中需要回收的对象,并且把它们标记出来) 第二步:清除 (清除掉被标记需要回收的对象,释放出对应的内存空间) 缺点: 标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需 要分配较大对象时,无法找到…...

2024年6月后2周重要的大语言模型论文总结:LLM进展、微调、推理和对齐

本文总结了2024年6月后两周发表的一些最重要的大语言模型论文。这些论文涵盖了塑造下一代语言模型的各种主题&#xff0c;从模型优化和缩放到推理、基准测试和增强性能。 LLM进展与基准 1、 BigCodeBench: Benchmarking Code Generation with Diverse Function Calls and Com…...

大数据面试题之数仓(1)

目录 介绍下数据仓库 数仓的基本原理 数仓架构 数据仓库分层(层级划分)&#xff0c;每层做什么?分层的好处? 数据分层是根据什么? 数仓分层的原则与思路 知道数仓建模常用模型吗?区别、优缺点? 星型模型和雪花模型的区别?应用场景?优劣对比 数仓建模有哪些方式…...

[机器学习]-4 Transformer介绍和ChatGPT本质

Transformer Transformer是由Vaswani等人在2017年提出的一种深度学习模型架构&#xff0c;最初用于自然语言处理&#xff08;NLP&#xff09;任务&#xff0c;特别是机器翻译。Transformer通过自注意机制和完全基于注意力的架构&#xff0c;核心思想是通过注意力来捕捉输入序列…...

基于深度学习的电力分配

基于深度学习的电力分配是一项利用深度学习算法优化电力系统中的电力资源分配、负荷预测、故障检测和系统管理的技术。该技术旨在提高电力系统的运行效率、稳定性和可靠性。以下是关于这一领域的系统介绍&#xff1a; 1. 任务和目标 电力分配的主要任务是优化电力系统中的电力…...

飞书 API 2-4:如何使用 API 将数据写入数据表

一、引入 上一篇创建好数据表之后&#xff0c;接下来就是写入数据和对数据的处理。 本文主要探讨数据的插入、更新和删除操作。所有的操作都是基于上一篇&#xff08;飞书 API 2-4&#xff09;创建的数据表进行操作。上面最终的数据表只有 2 个字段&#xff1a;序号和邮箱。序…...

系统设计题-日活月活统计

一、题目描述 根据访问日志统计接口的日活和月活。日志格式为 yyyy-mm-dd|clientIP|url|result 其中yyyy-mm-dd代表年月日&#xff0c;一个日志文件中时间跨度保证都在同一个月内&#xff0c;但不保证每行是按照日期顺序。 clientIP为合法的点分十进制ipv4地址(1.1.1.1和1.01.…...

在CentOS7云服务器下搭建MySQL网络服务详细教程

目录 0.说明 1.卸载不要的环境 1.1查看当前环境存在的服务mysql或者mariadb 1.2卸载不要的环境 1.2.1先关闭相关的服务 1.2.2查询曾经下载的安装包 1.2.3卸载安装包 1.2.4检查是否卸载干净 2.配置MySQLyum源 2.1获取mysql关外yum源 2.2 查看当前系统结合系统配置yum…...

【数据结构与算法】快速排序霍尔版

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​...

无人机5公里WiFi低延迟图传模组,抗干扰、长距离、低延迟,飞睿智能无线通信新标杆

在科技日新月异的今天&#xff0c;我们见证了无数通信技术的飞跃。从开始的电报、电话&#xff0c;到如今的4G、5G网络&#xff0c;再到WiFi的广泛应用&#xff0c;每一次技术的革新都极大地改变了人们的生活方式。飞睿智能5公里WiFi低延迟图传模组&#xff0c;它以其独特的优势…...

Kappa架构

1.Kappa架构介绍 Kappa架构由Jay Kreps提出&#xff0c;不同于Lambda同时计算和批计算并合并视图&#xff0c;Kappa只会通过流计算一条的数据链路计算并产生视图。Kappa同样采用了重新处理事件的原则&#xff0c;对于历史数据分析类的需求&#xff0c;Kappa要求数据的长期存储能…...

护网在即,助力安服仔漏洞扫描~

整合了个漏扫系统&#xff0c;安服仔必备~ 使用场景 网前布防&#xff0c;漏洞扫描&#xff0c;资产梳理 使用方法&#xff1a; 启动虚拟机后运行命令&#xff1a; ./StartSystemScript.sh 输入密码attack 启动完成后浏览器打开网站&#xff1a; http://IP:5000 相关账户…...

3C电子制造行业MES系统,提高企业生产效率

随着科技的不断进步&#xff0c;3C电子制造行业正迎来传统工厂向数字化工厂转型的阶段。在这场变革中&#xff0c;MES系统发挥着重要的作用&#xff0c;成为了企业变革的“智慧大脑”&#xff0c;引领着生产流程的优化和升级。 那么&#xff0c;MES系统究竟有哪些功能&#xf…...

C++ 多态和虚函数

参考C&#xff1a;多态 详解_c多态-CSDN博客 C多态——虚函数_c的a* a new b()是什么意思-CSDN博客 一.多态的概念 多态是在不同继承关系的类对象&#xff0c;去调用同一函数&#xff0c;产生了不同的行为。比如 Student 继承了 Person。 Person 对象买票全价&#xff0c;…...

七月记录上半

7.5 运行mysql脚本 mysql -u root -p 数据库名 < 脚本名 7.6 使用screen在服务器后台长期运行一个程序&#xff1a; screen -S 窗口名&#xff1a;创建窗口 执行程序脚本 ctrlad&#xff1a;退出窗口 screen -ls &#xff1a;查看所有窗口 screen -r 窗口号 &#…...

Wing FTP Server

文章目录 1.Wing FTP Server简介1.1主要特点1.2使用教程 2.高级用法2.1Lua脚本,案例1 1.Wing FTP Server简介 Wing FTP Server&#xff0c;是一个专业的跨平台FTP服务器端&#xff0c;它拥有不错的速度、可靠性和一个友好的配置界面。它除了能提供FTP的基本服务功能以外&#…...

【Linux进阶】文件系统6——理解文件操作

目录 1.文件的读取 1.1.目录 1.2.文件 1.3.目录树读取 1.4.文件系统大小与磁盘读取性能 2.增添文件 2.1.数据的不一致&#xff08;Inconsistent&#xff09;状态 2.2.日志式文件系统&#xff08;Journaling filesystem&#xff09; 3.Linux文件系统的运行 4、文件的删…...

Python编译器的选择

了解如何使用一个集成开发环境&#xff08;IDE&#xff09;对于 Python 编程是非常重要的。IDE 提供了代码编辑、运行、调试、版本控制等多种功能&#xff0c;可以极大地提升开发效率。以下是一些流行的 Python IDE 和代码编辑器的介绍&#xff0c;以及如何开始使用它们&#x…...

Java | Leetcode Java题解之第217题存在重复元素

题目&#xff1a; 题解&#xff1a; class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> set new HashSet<Integer>();for (int x : nums) {if (!set.add(x)) {return true;}}return false;} }...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如&#xff0c;已知表达式3*52&#xff0c;依照子表达式的求值顺序&#xff0c;有两种可能的结果&#xff0c;如图9-3所示。 如果乘法先执行&#xff0c;结果是17。如果5…...