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

谈谈单例模式中通过Htools包的SpringUtil.getBean获取Bean的好处

目录

优势

解决依赖注入失效问题:

典型应用场景:

好处

1. 实例化时序问题

2. 延迟获取解决空指针

3. 设计模式与 Spring 的权衡

代码对比:错误 vs 正确

错误示例(空指针):

正确实现(延迟获取):

总结

优势

在单例模式中通过SpringUtil.getBean获取Bean有以下几个关键优势:

解决依赖注入失效问题:

    • AsyncManager是饿汉式单例,实例化时机早于Spring容器初始化
    • 使用@Autowired等注入方式会导致NullPointerException
    • getBean()延迟获取保证了Spring容器完成初始化后才获取Bean

1. 保持单例控制权:

  • 该类自己维护单例实例(非Spring管理)
  • 避免与Spring容器管理的单例产生冲突
  • 可以自主控制初始化和销毁时机

2. 获取复杂依赖的灵活性:

  • 当需要动态获取不同profile配置的Bean时更灵活
  • 特别适用于需要根据条件获取不同实现类的场景

3. 避免循环依赖陷阱:

  • 传统注入方式在复杂依赖链中可能引发循环依赖问题
  • 按需主动获取的方式打破了这种潜在的循环依赖链

4. 与工具类整合更自然:

  • 结合Hutool等工具库的使用风格
  • 保持代码简洁性,避免大量注解污染

典型应用场景:

  1. 框架基础组件
  2. 需要严格生命周期控制的类
  3. 早于Spring容器初始化的核心组件
  4. 需要避免被Spring代理的场合

这种模式在中间件开发、基础框架开发中较为常见,体现了对Spring容器的主动控制,而非被动依赖。

好处

1. 实例化时序问题

  • 根本矛盾AsyncManager饿汉式单例,其静态实例 INSTANCE 在类加载时(通常是应用启动早期)立即初始化。而此时 Spring 容器可能尚未完成 Bean 的初始化
  • 传统注入的陷阱:如果用 @Autowired 注入 ScheduledExecutorService
@Autowired
private ScheduledExecutorService executor; // 此时Spring容器未就绪,注入会失败!

由于单例的初始化早于 Spring 容器的初始化,executor 会保持 null,后续使用时必然抛出 NullPointerException


2. 延迟获取解决空指针

  • 按需获取:通过 SpringUtil.getBean("scheduledExecutorService") 延迟加载 Bean:
    • 第一次调用 execute() 方法时才会实际获取 Bean
    • 此时 Spring 容器已经初始化完成,可以安全获取到 Bean
  • 避免静态代码块陷阱:即使你在静态代码块中调用 SpringUtil.getBean(),仍然可能因容器未就绪而失败,而延迟加载彻底规避了时序问题。

3. 设计模式与 Spring 的权衡

  • 单例控制权AsyncManager 是一个自主管理的单例(非 Spring 托管),因此:
    • 它不参与 Spring 的生命周期管理
    • 不能直接享受 Spring 的依赖注入特性
    • 需要主动从容器中获取依赖,而非被动注入
  • 框架整合技巧:通过 SpringUtil 工具类(Hutool 提供)打破单例模式与 Spring 容器的耦合,是常见的企业级解决方案。

代码对比:错误 vs 正确

错误示例(空指针):
public class AsyncManager {private static final AsyncManager INSTANCE = new AsyncManager();@Autowired // 注入时机不对!private ScheduledExecutorService executor;public void execute(TimerTask task) {executor.schedule(task, 10, TimeUnit.MILLISECONDS); // executor 为 null!}
}
正确实现(延迟获取):
public class AsyncManager {private static final AsyncManager INSTANCE = new AsyncManager();// 延迟获取 Beanprivate final ScheduledExecutorService executor = SpringUtil.getBean("scheduledExecutorService"); public void execute(TimerTask task) {executor.schedule(task, 10, TimeUnit.MILLISECONDS); // 安全执行}
}

总结

  • 核心目标:确保在 Spring 容器初始化完成后再获取 Bean,避免 NullPointerException
  • 设计权衡:牺牲一定的 "纯粹性"(依赖注入的理想模式),换取代码的健壮性和框架整合的灵活性
  • 适用场景:自主管理的单例类、工具类、需要早期初始化的组件等

这种模式在需要严格掌控初始化时序的场景中非常实用,是解决框架整合时序问题的经典方案。

相关文章:

谈谈单例模式中通过Htools包的SpringUtil.getBean获取Bean的好处

目录 优势 解决依赖注入失效问题: 典型应用场景: 好处 1. 实例化时序问题 2. 延迟获取解决空指针 3. 设计模式与 Spring 的权衡 代码对比:错误 vs 正确 错误示例(空指针): 正确实现(延…...

本地部署大语言模型-DeepSeek

DeepSeek 是国内顶尖 AI 团队「深度求索」开发的多模态大模型,具备数学推理、代码生成等深度能力,堪称"AI界的六边形战士"。 Hostease AMD 9950X/96G/3.84T NVMe/1G/5IP/RTX4090 GPU服务器提供多种计费模式。 DeepSeek-R1-32B配置 配置项 规…...

adb的安装

1、概念 (1)adb(android debug bridge)安卓调试桥,用于完成电脑和手机之间的通信控制。 (2)xcode来完成对于ios设备的操控,前提是有个mac电脑。 2、adb的安装 (1&…...

Python 如何实现 Markdown 记账记录转 Excel 存储

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...

随机播放音乐 伪随机

import java.util.*;/*** https://cloud.tencent.com.cn/developer/news/1045747* 伪随机播放音乐*/ public class MusicPlayer {private List<String> allSongs; // 所有歌曲列表private List<String> playedSongs; // 已经播放过的歌曲列表private Map<String…...

latex 环境配置

编译器可选 miktex和 tex live ① miktex 下载地址 Portable 版本用的也是 Installer版的安装程序 basic-miktex-24.1-x64.exe&#xff0c;但是需要修改文件名为 miktex-portable.exe ├──texmfs │ ├─config │ ├─data │ └─install │ └─miktex/…...

fortify安全扫描Access Control: Database问题解决

概述 Access Control: Database说白了就是权限控制。在访问数据库(sql和nosql)需要加入当前用户的权限控制。不然会被fortify扫描出来&#xff0c;认为客户端可能不挟持和假冒&#xff0c;从而导致数据被泄露。 但是这个并不是任何时候都需要的&#xff0c;有的接口本来…...

Java 设计模式:软件开发的精髓与艺

目录 一、设计模式的起源二、设计模式的分类1. 创建型模式2. 结构型模式3. 行为型模式三、设计模式的实践1. 单例模式2. 工厂模式3. 策略模式四、设计模式的优势五、设计模式的局限性六、总结在软件开发的浩瀚星空中,设计模式犹如一颗颗璀璨的星辰,照亮了开发者前行的道路。它…...

初学者如何用 Python 写第一个爬虫?

?? 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长。 ?? …...

Cocos Creator3.8.6拖拽物体的几种方式

文章目录 前言一、第一种通过UILocation二、第二种通过UIDelta实现总结 前言 在游戏开发中&#xff0c;拖拽物体是一个非常常见的交互功能&#xff0c;无论是用于UI元素的拖动&#xff0c;还是场景中物体的移动&#xff0c;拖拽操作都能极大地提升用户体验。Cocos Creator 3.8…...

分布式Session

我用「餐厅点餐代码实战」帮你彻底搞懂分布式Session&#xff0c;看完不仅能应对面试&#xff0c;还能直接应用到实际开发。先记住这个核心矛盾&#xff1a;多服务员如何记住同一顾客的喜好&#xff1f; 一、从生活场景理解Session的本质 传统单机场景&#xff08;小餐馆&…...

Kotlin 运算符重载

在Kotlin中&#xff0c;常用的运算符重载函数名如下&#xff1a; 1.算术操作符&#xff1a; 加法&#xff1a;plus 减法&#xff1a;minus 乘法&#xff1a;times 除法&#xff1a;div 取模&#xff1a;rem 或 mod 整数除法&#xff1a;floorDiv 求幂&#xff1a;pow 自增&…...

OpenHarmony4.1-轻量与小型系统ubuntu开发环境

因OpenHarmony官网提供包含轻量、小型与标准系统的全量代码非常宠大&#xff0c;解包后大概需要70G以上硬盘空间&#xff0c;如要编译标准系统则需要140G以上空间。 如硬盘空间有限与只使用轻量/小型OpenHarmony系统&#xff0c;则可以下载并直接使用本人裁剪源码过的ubuntu硬盘…...

AVR 单片机硬件供电处理

摘自AVR 单片机应用笔记&#xff1a;AN2519 - AVR Microcontroller Hardware Design Considerations。 2. 供电 供电设计是任何硬件设计的关键一环&#xff0c;直接影响到系统的性能。在设计供电时&#xff0c;有两个重要的方面需要考虑&#xff1a;ESD 防护和噪声干扰。这些内…...

LeetCode 27 移除元素

LeetCode 27 - 移除元素&#xff08;Remove Element&#xff09;是一个简单但经典的双指针问题&#xff0c;主要考察数组操作的基本功。虽然问题容易&#xff0c;但掌握多种解法以及衍生的变体问题对解决更复杂的操作数组问题有帮助。 题目描述 输入&#xff1a;整数数组 nums…...

对“预训练”的理解

预训练有什么用 传统的机器学习是偏数学的&#xff0c;对数据的量不做过多要求&#xff0c;而深度学习的项目通常是有大量的数据可供使用。 在平常的任务或者项目中&#xff0c;我们可能并没有大量数据&#xff0c;只有少量数据&#xff0c;在这时我们就可以通过“借用”有大…...

论文阅读:CAN GENERATIVE LARGE LANGUAGE MODELS PERFORM ASR ERROR CORRECTION?

CAN GENERATIVE LARGE LANGUAGE MODELS PERFORM ASR ERROR CORRECTION? 生成式大语言模型能否进行自动语音识别&#xff08;ASR&#xff09;纠错&#xff1f; https://arxiv.org/pdf/2307.04172 文章目录 速览常规总结通俗版 摘要&#xff08;Abstract&#xff09;2. 引言&a…...

Stable Diffusion(SD)系列模型及关联算法深度解析

一、‌基础模型架构演进‌ SD v1.5‌ ‌核心架构‌&#xff1a;基于Latent Diffusion Model&#xff08;LDM&#xff09;&#xff0c;通过VAE将图像压缩至潜空间进行扩散训练&#xff0c;支持512x512分辨率生成&#xff0c;兼容二次元与写实风格混合创作‌12。 ‌训练数据‌&…...

FPGA开发,使用Deepseek V3还是R1(3):系统级与RTL级

以下都是Deepseek生成的答案 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;1&#xff09;&#xff1a;应用场景 FPGA开发&#xff0c;使用Deepseek V3还是R1&#xff08;2&#xff09;&#xff1a;V3和R1的区别 FPGA开发&#xff0c;使用Deepseek V3还是R1&#x…...

logback日志输出配置范例

logback日志输出配置范例 在wutool中&#xff0c;提供了logback日志输出配置范例&#xff0c;实现日志文件大小限制、滚动覆盖策略、定时清理等功能。 关于wutool wutool是一个java代码片段收集库&#xff0c;针对特定场景提供轻量解决方案&#xff0c;只要按需选择代码片段…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目

应用场景&#xff1a; 1、常规某个机器被钓鱼后门攻击后&#xff0c;我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后&#xff0c;我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...

c++算法学习3——深度优先搜索

一、深度优先搜索的核心概念 DFS算法是一种通过递归或栈实现的"一条路走到底"的搜索策略&#xff0c;其核心思想是&#xff1a; 深度优先&#xff1a;从起点出发&#xff0c;选择一个方向探索到底&#xff0c;直到无路可走 回溯机制&#xff1a;遇到死路时返回最近…...

后端解决跨域问题的三种方案:注解配置 vs 全局配置 vs 过滤器配置(附完整代码详解)

文章目录 一、引言:跨域问题的本质与解决方案分类解决方案分类二、方案一:`WebMvcConfigurer` 全局配置(推荐)1. 核心代码(你提供的 `CorsConfig` 示例)2. 代码详解3. 优点4. 注意事项三、方案二:`CorsFilter` 过滤器配置(传统方式)1. 核心代码(你提供的 `ResourcesC…...

Mac版Visual Studio Code Copilot 无法使用的解决方法

1 app文件夹删除Visual Studio Code 2 终端里面 输入以下指令&#xff0c;删除各种缓存 rm -fr ~/Library/Preferences/com.microsoft.VSCode.helper.plist rm -fr ~/Library/Preferences/com.microsoft.VSCode.plist rm -fr ~/Library/Caches/com.microsoft.VSCode rm -f…...