SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton

在继续深入探讨 SmartInitializingSingleton接口之前,让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE(Java Enterprise Edition)全栈(full-stack)轻量级应用程序框架,用于开发企业级应用程序。它提供了广泛的基础设施支持和丰富的特性,以简化企业级应用程序的开发。

1. Spring Framework 概述

Spring Framework 的核心特性包括:

1.1 控制反转(Inversion of Control,IoC)

Spring 使用控制反转(IoC)原则来管理对象之间的依赖关系。在传统的 Java 开发中,对象的创建和依赖关系通常由程序员自己管理,而在 Spring 中,容器负责创建对象并将它们装配起来。这种方式将对象之间的依赖关系从代码中解耦,提高了代码的灵活性和可维护性。

1.2 依赖注入(Dependency Injection,DI)

依赖注入是控制反转的一种实现方式,它通过将对象的依赖关系注入到对象本身,来实现对象之间的解耦。Spring 使用依赖注入来管理对象之间的依赖关系,通过配置文件或者注解来描述对象之间的关系,然后由 Spring 容器负责将依赖关系注入到对象中。

1.3 切面编程(Aspect-Oriented Programming,AOP)

切面编程是一种用于将横切关注点(cross-cutting concerns)从应用程序的核心逻辑中分离出来的编程范式。在 Spring 中,通过 AOP 可以实现诸如日志记录、性能监控、事务管理等与业务逻辑无关的功能,从而提高代码的模块化和可重用性。

1.4 面向接口编程(Interface-Based Programming)

Spring 鼓励使用面向接口编程的方式来开发应用程序,这样可以提高代码的灵活性和可扩展性。Spring 的许多特性都是基于接口实现的,如依赖注入、AOP 等,这使得开发者可以很容易地实现自己的定制功能。

1.5 配置简化

Spring 提供了多种配置方式,包括基于 XML 的配置、基于注解的配置和基于 Java 的配置,使得开发者可以根据自己的习惯和项目的需求选择合适的配置方式,并且可以灵活地切换配置方式而不影响应用程序的正常运行。

1.6 模块化设计

Spring Framework 被设计为一组相互独立、松耦合的模块,每个模块都提供特定的功能,如核心容器、数据访问/集成、Web 开发、AOP 支持等。开发者可以根据自己的需求选择需要的模块,而不必引入整个框架。

2. SmartInitializingSingleton 接口介绍

现在让我们转向本文的重点:SmartInitializingSingleton 接口。在 Spring Framework 中,SmartInitializingSingleton 是一个特殊的接口,用于在 Spring 容器中所有单例 Bean 初始化完成后执行一些自定义的初始化逻辑。它允许开发者在所有单例 Bean 都已经准备就绪后执行一些特定的操作,这对于需要在应用程序启动时进行一些额外的初始化工作的场景非常有用。

2.1 SmartInitializingSingleton 接口定义

javaCopy codepublic interface SmartInitializingSingleton {void afterSingletonsInstantiated();
}

SmartInitializingSingleton 接口非常简单,只有一个方法:afterSingletonsInstantiated()。在 Spring 容器中所有的单例 Bean 都初始化完成之后,Spring 容器会回调实现了 SmartInitializingSingleton 接口的类的 afterSingletonsInstantiated() 方法,从而触发相应的初始化逻辑。

2.2 使用示例

让我们通过一个简单的示例来说明如何使用 SmartInitializingSingleton 接口。假设我们有一个需要在所有单例 Bean 初始化完成后执行初始化逻辑的场景,我们可以定义一个实现了 SmartInitializingSingleton 接口的类,然后在其中实现 afterSingletonsInstantiated() 方法来执行相应的初始化逻辑。

javaCopy code@Component
public class MyInitializer implements SmartInitializingSingleton {private static final Logger logger = LoggerFactory.getLogger(MyInitializer.class);@Overridepublic void afterSingletonsInstantiated() {// 执行初始化逻辑logger.info("All singleton beans have been instantiated.");// 可以在这里执行一些初始化操作,如加载配置文件、初始化缓存等}
}

在上面的示例中,我们定义了一个名为 MyInitializer 的类,它实现了SmartInitializingSingleton 接口,并重写了 afterSingletonsInstantiated() 方法。在这个方法中,我们可以执行任何需要在所有单例 Bean 初始化完成后执行的初始化逻辑。

3.案例

3.1 初始化缓存信息

在项目开发中,用户经常会浏览各种商品,如服装、家居用品、电子设备等。为了提高用户体验和系统性能,平台决定引入缓存机制来存储商品信息,以减少对数据库的频繁访问。在系统启动时,需要初始化商品信息的缓存(从数据库中进行查询),以便在用户请求时快速响应。为了实现这一目标,我们将使用 Spring 框架的 SmartInitializingSingleton 接口来在所有单例 Bean 初始化完成后执行初始化缓存的操作。

3.1.2 创建商品实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 商品id唯一*/private String goodId;/*** 商品名称*/private String goodName;/*** 商品价格*/private BigDecimal price;public String toString(Product product){StringBuffer sb = new StringBuffer();sb.append("商品id:").append(product.getGoodId()).append("商品名称:").append(product.getGoodName()).append("商品价格:").append(product.getPrice());return sb.toString();}
}

3.1.3 编写商品缓存类

/**** 商品缓存类型* @author 13723* @version 1.0* 2024/2/24 12:49*/
@Component
public class ProductCache implements SmartInitializingSingleton {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 商品缓存Map*/private static final Map<String,Product> goodMap = new HashMap<>();/*** 添加商品到缓存* @param product*/public void addGood(Product product){// 添加商品到缓存goodMap.put(product.getGoodId(),product);}/*** 根据商品id获取商品*/public Product getGoods(String goodId){Product product = goodMap.get(goodId);if (product == null){logger.error("未查询到商品!");}return product;}public void initializingGoods(){// 初始化商品信息Product product1 = new Product("1", "手机", new BigDecimal("111.23"));Product product2 = new Product("2", "笔记本", new BigDecimal("1121.23"));Product product3 = new Product("3", "相机", new BigDecimal("3331.23"));Product product4 = new Product("4", "游戏机", new BigDecimal("12111.23"));addGood(product1);addGood(product2);addGood(product3);addGood(product4);logger.error("=========== 初始化商品信息完成 ===========");}/*** 在项目启动时,所有的单例bean都实例化完成后,会调用该方法*/@Overridepublic void afterSingletonsInstantiated() {// 初始化商品信息initializingGoods();}
}

3.1.4 编写测试类

@Test
@DisplayName("测试SmartInitializingSingleton Bean加载")
public void testSmartInitializingSingleton(){// 测试SmartInitializingSingleton Bean加载logger.error("商品信息未:{}",productCache.getGoods("1"));logger.error("商品信息未:{}",productCache.getGoods("2"));logger.error("商品信息未:{}",productCache.getGoods("3"));
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. SmartInitializingSingleton 的使用场景

SmartInitializingSingleton 接口提供了一种灵活的机制来处理在 Spring 容器启动时需要执行的初始化逻辑。它适用于许多场景,包括但不限于:

4.1 加载配置信息

在应用程序启动时,可能需要加载一些配置信息,如数据库连接信息、系统参数等。SmartInitializingSingleton 接口可以用来执行这些初始化操作,确保在所有单例 Bean 初始化完成之后再加载配置信息。

4.2 初始化缓存

在应用程序启动时,可以使用 SmartInitializingSingleton 接口来初始化缓存,以提高系统的性能和响应速度。通过在所有单例 Bean 初始化完成后执行初始化缓存的操作,可以确保缓存数据已经准备就绪,从而避免了在系统运行时动态加载数据造成的性能损耗。

4.3. 执行定时任务

在某些情况下,可能需要在应用程序启动时执行一些定时任务,如数据同步、数据清理等。SmartInitializingSingleton 接口可以用来执行这些定时任务,以确保它们在所有单例 Bean 初始化完成之后立即执行。

总结

在本文中,我们介绍了 Spring Framework 的核心特性和背景,并深入探讨了 SmartInitializingSingleton 接口。通过实现 SmartInitializingSingleton 接口,开发者可以在 Spring 容器中所有单例 Bean 初始化完成后执行一些自定义的初始化逻辑,从而提高应用程序的灵活性和可维护性。我们还介绍了 SmartInitializingSingleton 接口的使用示例和常见的使用场景,希望能够帮助开发者更好地理解和应用这一特性。

总的来说,SmartInitializingSingleton 接口为 Spring 应用程序提供了一个强大而灵活的初始化机制,可以满足各种复杂应用程序的初始化需求,是 Spring Framework 中的一个重要组成部分。开发者可以根据自己的实际需求,合理地使用 SmartInitializingSingleton 接口来优化应用程序的初始化过程,提高系统的性能和可靠性。

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

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

相关文章

力扣 724. 寻找数组的中心下标

思路&#xff1a; 创建两个变量sum和sum1&#xff0c;sum代表左边元素的和&#xff0c;sum1代表右边元素的和 然后假设从数组下标0开始&#xff0c;一直到最后一个作为中心下标 如果sumsum1&#xff0c;返回此时的中心下标 如果所有下标循环完了&#xff0c;发现没有return…

Apipost 数据模型功能API数据重复利用起来

在Apipost数据模型中用户可以预先创建多个数据模型&#xff0c;并在API设计过程中重复利用这些模型来构建API 创建数据模型 在左侧导航点击「数据模型」-「新建数据模型」在右侧工作台配置数据模型参数 引入数据模型 在API设计预定义响应期望下点击引用数据模型&#xff0c;…

操作系统——处理机调度

文章目录 进程调度0.概念1.调度分类高级调度低级调度中级调度七状态模型调度对比 2.进程调度进程调度的时机进程调度的方式进程的切换方式调度器/调度程序闲逛进程 3. 调度算法的评价指标CPU利用率系统吞吐量周转时间等待时间响应时间 4. 调度算法先来先服务(FCFS)短作业优先(S…

【软件测试】--功能测试1

一、测试介绍 什么是软件&#xff1f; 控制计算机硬件工作的工具。 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 软件测试的目的&#xff1f; 减少软件缺陷&#xff0c;保证软件质量。 测试主流技能 1、功能测试 2、自动化测试 3、接口测试 4、性能测试 ​…

MySQL-事务,properties文件解析,连接池

1.事务机制管理 1.1 Transaction事务机制管理 默认情况下是执行一条sql语句就保存一次&#xff0c;那么比如我们需要三条数据同时成功或同时失败就需要开启事务机制了。开启事务机制后执行过程中发生问题就会回滚到操作之前&#xff0c;相当于没有执行操作。 1.2 事务的特征 事…

【初始RabbitMQ】延迟队列的实现

延迟队列概念 延迟队列中的元素是希望在指定时间到了之后或之前取出和处理消息&#xff0c;并且队列内部是有序的。简单来说&#xff0c;延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列使用场景 延迟队列经常使用的场景有以下几点&#xff1a; 订单在十分…

Anaconda下安装torch-geometric

主要流程参考&#xff1a;https://blog.csdn.net/weixin_45671036/article/details/130617637 https://blog.csdn.net/weixin_43756314/article/details/130225038?ops_request_misc&request_id&biz_id102&utm_term%E5%80%9F%E5%8A%A9anaconda%20%E5%AE%89%E8%A3%…

配置vscode,使其可以运行C++11特性的代码(如vector)

配置vscode&#xff0c;使其可以运行C11特性的代码 封面引用自配置教程的B站视频&#xff0c;非常详细的视频&#xff0c;感谢视频作者的贡献。 文章目录 配置vscode&#xff0c;使其可以运行C11特性的代码Step 1: 基础配置Step 2: 调整Code Runner的配置Step 3: 更改tasks.jso…

一文7个步骤教你搭建测试web测试项目实战环境

​今天小编&#xff0c;给大家总结下web 测试实战的相关内容&#xff0c;一起来学习下吧&#xff01; web项目实战可按顺序依次为&#xff1a;【搭建测试环境】、【需求评审】、【编写测试计划】、【分析测试点.编写测试用例】、【用例评审】、【执行用例提bug】、【测试报告】…

undo日志详解

一、undo日志介绍 上一节详细的说了redo日志&#xff0c;redo日志的功能就是把增删改操作都记录着&#xff0c;如果断电导致内存中的脏页丢失&#xff0c;可以根据磁盘中的redo日志文件进行恢复。redo日志被设计出来是为了保证数据库的持久性&#xff0c;undo日志设计出来是为…

AI 绘画:人工智能绘画之美

人工智能&#xff08;AI&#xff09;是当今科技领域的热门话题&#xff0c;它不仅可以帮助我们解决各种复杂的问题&#xff0c;还可以创造出令人惊叹的艺术作品。AI 绘画是一种利用 AI 技术生成图像的方法&#xff0c;它可以模仿不同的风格、主题和技巧&#xff0c;甚至可以创造…

Qt Linux下调用OpenGL的glu.h报错:error: GL/glu.h: No such file or directory

Qt Linux下调用OpenGL的glu.h报错&#xff1a;error: GL/glu.h: No such file or directory 引言一、问题描述二、解决方案三、解决过程记录3.1 定位问题3.2 尝试使用yum命令安装3.3 从网上下载到本地进行安装 引言 在Windows上正常运行的OpenGL程序&#xff0c;到Linux下突然…

cuda学习笔记(2)

一 专业名词 1 分支断定 2 一致性和同一性 3 常见名词汇总 4 加速比 二 GPU架构构述 GPU就是将cpu的数据存储单元去掉&#xff0c;也就是保留执行单元&#xff0c;GPU就是多个执行单元 1 GPU设计思路&#xff0c;指令流共享&#xff0c;同时执行&#xff0c;数据切分成小块 …

MySQL的21个SQL经验

1. 写完SQL先explain查看执行计划(SQL性能优化) 日常开发写SQL的时候,尽量养成这个好习惯呀:写完SQL后,用explain分析一下,尤其注意走不走索引。 explain select userid,name,age from user where userid =10086 or age =18;2、操作delete或者update语句,加个limit(S…

Android 面试问题 2024 版(其三)

Android 面试问题 2024 版&#xff08;其三&#xff09; 十一、版本控制十二、Play 商店和应用程序部署十三、无障碍十四、第三方库和 API十五、解决问题的能力十六、基于 JD 的非常高级别的问题 十一、版本控制 什么是版本控制&#xff0c;为什么它在软件开发中很重要&#x…

爬某网站延禧宫率第一集视频

import requests import re from tqdm import tqdm # 网址链接&#xff1a;https://v.ijujitv.cc/play/24291-1-1.html url https://v6.1080pzy.co/20220801/urxniJCN/hls/index.m3u8 headers {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Appl…

BUUCTF crypto做题记录(9)新手向

一、rsa2 得到题目代码如下&#xff1a; N 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241962525705950046253400188884658262496534706438791515071885860897552736656899566915731297225817250639873643376310103992170…

Linux调用可执行程序:system()函数和execl函数

system()函数&#xff1a; system()函数是一个在C/C编程语言中的库函数&#xff0c;用于在操作系统中执行命令。 函数声明如下&#xff1a; int system(const char *command);该函数接受一个指向以空字符结尾的字符串的指针作为参数&#xff0c;该字符串包含要执行的命令。函…

吴恩达deeplearning.ai:sigmoid函数的替代方案以及激活函数的选择

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 引入——改进下需求预测模型ReLU函数(整流线性单元 rectified linear unit&#xff09;线性激活函数(linear activation function)激活函数的选择实现方式为什么需要激活函数 到现在…

【MATLAB】 LMD信号分解+FFT傅里叶频谱变换组合算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 展示出图效果 1 LMD分解算法 LMD (Local Mean Decomposition) 分解算法是一种信号分解算法&#xff0c;它可以将一个信号分解成多个局部平滑的成分&#xff0c;并且可以将高频噪声和低频信号有效地分离出来。LMD 分解算…