Spring单例模式 Spring 中的单例 饿汉式加载 懒汉式加载

目录

核心特性

实现方式详解

1. 饿汉式(Eager Initialization)

2. 懒汉式(Lazy Initialization)

3. 静态内部类(Bill Pugh 实现)

4. 枚举(Enum)

破坏单例的场景及防御

Spring 中的单例

适用场景

缺点

优点

1. 手动注册 Bean(代码配置)

2. 使用 Spring Boot 自动配置

3. 使用 ThreadPoolTaskScheduler(Spring 内置)

4. 检查包扫描路径

常见误区示例

单例模式(Singleton Pattern)是一种创建型设计模式,其核心目标是确保一个类只有一个实例存在,并提供全局唯一的访问点。它常用于资源控制(如数据库连接池、线程池)、配置管理、日志对象等场景。


核心特性

  1. 唯一性:无论调用多少次,始终返回同一个对象实例。
  2. 全局访问:通过静态方法或静态变量提供全局访问入口。
  3. 私有构造:禁止通过 new 关键字直接实例化。

实现方式详解

以下是单例模式的几种典型实现(以 Java 为例):

1. 饿汉式(Eager Initialization)

特点:类加载时立即初始化实例,线程安全但可能浪费资源。

public class EagerSingleton {// 类加载时直接初始化实例private static final EagerSingleton instance = new EagerSingleton();// 私有构造方法private EagerSingleton() {}// 全局访问点public static EagerSingleton getInstance() {return instance;}
}

2. 懒汉式(Lazy Initialization)

特点:第一次调用时创建实例,需解决线程安全问题。

  • 基础版(非线程安全)
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
  • 线程安全版(双重检查锁,Double-Checked Locking)
public class ThreadSafeSingleton {// volatile 防止指令重排序private static volatile ThreadSafeSingleton instance;private ThreadSafeSingleton() {}public static ThreadSafeSingleton getInstance() {if (instance == null) {synchronized (ThreadSafeSingleton.class) {if (instance == null) {instance = new ThreadSafeSingleton();}}}return instance;}
}

3. 静态内部类(Bill Pugh 实现)

特点:利用类加载机制保证线程安全,延迟加载且无锁。

public class InnerClassSingleton {private InnerClassSingleton() {}// 静态内部类在调用 getInstance() 时才会加载private static class SingletonHolder {private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();}public static InnerClassSingleton getInstance() {return SingletonHolder.INSTANCE;}
}

4. 枚举(Enum)

特点:天然线程安全,防止反射攻击,简洁高效(推荐方式)。

public enum EnumSingleton {INSTANCE; // 单例实例public void doSomething() {// 业务逻辑}
}
// 使用:EnumSingleton.INSTANCE.doSomething();

破坏单例的场景及防御

  1. 反射攻击:通过反射调用私有构造方法创建新实例。
    • 防御:在构造方法中检查实例是否已存在,若存在则抛出异常。
  1. 反序列化:反序列化可能生成新对象。
    • 防御:实现 readResolve() 方法返回已有实例。
  1. 克隆:重写 clone() 方法并抛出异常。

Spring 中的单例

在 Spring 框架中,默认的 Bean 作用域是单例(@Scope("singleton")),但需注意:

  • Spring 单例是容器级别的:每个容器中保证唯一,而非 JVM 级别。
  • 非严格单例:如果通过 new 或反射创建,仍可能生成多个实例。

适用场景

  • 频繁使用的对象(减少资源开销)。
  • 需严格控全局状态的场景(如计数器、配置管理)。
  • 共享资源访问(如文件系统、数据库连接池)。

缺点

  • 违反单一职责原则(同时管理实例化和业务逻辑)。
  • 可能隐藏代码耦合。
  • 多线程需额外注意同步问题。

单例模式需要谨慎使用,避免滥用导致代码难以测试和维护。以下是不同解决方法的好处具体场景示例


优点

1. 手动注册 Bean(代码配置)

好处:完全控制线程池参数(核心线程数、队列容量等),适合需要定制化配置的场景。

@Configuration
public class SchedulerConfig {@Bean("scheduledExecutorService")public ScheduledExecutorService scheduledExecutorService() {return Executors.newScheduledThreadPool(5);}
}

示例场景
你需要一个固定大小为5的线程池,并明确指定线程名称格式:

@Bean("scheduledExecutorService")
public ScheduledExecutorService customExecutor() {return new ScheduledThreadPoolExecutor(5, new ThreadFactoryBuilder().setNameFormat("scheduler-%d").build());
}

2. 使用 Spring Boot 自动配置

好处:无需手动编码,通过配置文件快速启用调度功能,简化配置。

# application.properties
spring.task.scheduling.pool.size=5

示例场景
简单应用需要快速启用定时任务,只需在 @Scheduled 注解方法上使用:

@Scheduled(fixedRate = 5000)
public void task() {System.out.println("Task executed by auto-configured scheduler");
}

3. 使用 ThreadPoolTaskScheduler(Spring 内置)

好处:与 Spring 生态集成更好,支持更丰富的配置(错误处理、线程管理等)。

@Bean
public ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);scheduler.setThreadNamePrefix("spring-scheduler-");return scheduler;
}

示例场景
需要为不同的任务分配独立的调度器,或在任务失败时记录日志:

@Bean
public ThreadPoolTaskScheduler paymentScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(3);scheduler.setErrorHandler(t -> logger.error("Payment task failed", t));return scheduler;
}

4. 检查包扫描路径

好处:避免因配置类未被扫描导致的 Bean 未注册问题。
示例
假设主启动类在 com.example.app 包下,而配置类在 com.example.config 包中:

@SpringBootApplication
@ComponentScan("com.example.config") // 显式扫描配置包
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

常见误区示例

问题:Bean 名称拼写错误导致依赖注入失败。

// ❌ 错误:Bean 名称写成了 "scheduledExecutor"
@Bean("scheduledExecutor")
public ScheduledExecutorService executor() { ... }// ❌ 使用时名称不一致
@Autowired
@Qualifier("scheduledExecutorService") // 找不到 Bean!
private ScheduledExecutorService executor;

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

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

相关文章

DeepSeek MLA(Multi-Head Latent Attention)算法浅析

目录 前言1. 从MHA、MQA、GQA到MLA1.1 MHA1.2 瓶颈1.3 MQA1.4 GQA1.5 MLA1.5.1 Part 11.5.2 Part 21.5.3 Part 3 结语参考 前言 学习 DeepSeek 中的 MLA 模块,究极缝合怪,东抄抄西抄抄,主要 copy 自苏神的文章,仅供自己参考&#…

uniapp 中引入使用uView UI

文章目录 一、前言:选择 uView UI的原因二、完整引入步骤1. 安装 uView UI2. 配置全局样式变量(关键!)3. 在 pages.json中添加:4. 全局注册组件5. 直接使用组件 五、自定义主题色(秒换皮肤) 一、…

zookeeper-docker版

Zookeeper-docker版 1 zookeeper概述 1.1 什么是zookeeper Zookeeper是一个分布式的、高性能的、开源的分布式系统的协调(Coordination)服务,它是一个为分布式应用提供一致性服务的软件。 1.2 zookeeper应用场景 zookeeper是一个经典的分…

【量化金融自学笔记】--开篇.基本术语及学习路径建议

在当今这个信息爆炸的时代,金融领域正经历着一场前所未有的变革。传统的金融分析方法逐渐被更加科学、精准的量化技术所取代。量化金融,这个曾经高不可攀的领域,如今正逐渐走进大众的视野。它将数学、统计学、计算机科学与金融学深度融合&…

unity学习56:旧版legacy和新版TMP文本输入框 InputField学习

目录 1 旧版文本输入框 legacy InputField 1.1 新建一个文本输入框 1.2 InputField 的子物体构成 1.3 input field的的component 1.4 input Field的属性 2 过渡 transition 3 控件导航 navigation 4 占位文本 placeholder 5 文本 text 5.1 文本内容,用户…

汽车电子电控软件开发中因复杂度提升导致的架构恶化问题

针对汽车电子电控软件开发中因复杂度提升导致的架构恶化问题,建议从以下方向进行架构优化和开发流程升级,以提升灵活性、可维护性和扩展性: 一、架构设计与模块化优化 分层架构与模块解耦 采用AUTOSAR标准的分层架构(应用层、运行…

【弹性计算】弹性裸金属服务器和神龙虚拟化(一):功能特点

弹性裸金属服务器和神龙虚拟化(一):功能特点 特征一:分钟级交付特征二:兼容 VPC、SLB、RDS 等云平台全业务特征三:兼容虚拟机镜像特征四:云盘启动和数据云盘动态热插拔特征五:虚拟机…

腾讯云大模型知识引擎驱动的DeepSeek满血版医疗顾问大模型搭建实战

文章目录 1. 引言2. 什么是腾讯云大模型知识引擎(LKE)?核心优势功能特点应用场景 3. 模型搭建过程3.1 注册登录产品3.2 创建应用3.3 配置模型3.4 配置角色指令3.5 配置欢迎语3.6 配置知识库3.7 配置工作流3.8 启用联网搜索3.9 发布模型 4. 问…

nio中ByteBuffer使用

创建ByteBuffer ByteBuffer buffer ByteBuffer.allocate(10);// 字符串转 bytebufferByteBuffer buffer01 Charset.defaultCharset().encode("hello world"); ByteBuffer buffer02 ByteBuffer.wrap("hello".getBytes()); ByteBuffer buffer03 Standard…

如何在 IntelliJ IDEA 中集成 DeepSeek

如何在 IntelliJ IDEA 中集成 DeepSeek 在本教程中,我们将带您一步步完成将 DeepSeek 集成到 IntelliJ IDEA 中的过程。通过此集成,您可以在IDE中利用DeepSeek强大的功能,提高开发工作效率。 步骤 1:安装 Proxy AI 插件 首先&a…

【Maven】入门介绍 与 安装、配置

文章目录 一、Maven简介1. Maven介绍2. Maven软件工作原理模型图 二、Maven安装和配置1. Maven安装2. Maven环境配置3. Maven功能配置4. IDEA配置本地Maven软件 一、Maven简介 1. Maven介绍 https://maven.apache.org/what-is-maven.html Maven 是一款为 Java 项目管理构建、…

Java数据结构第十六期:走进二叉树的奇妙世界(五)

专栏:Java数据结构秘籍 个人主页:手握风云 目录 一、非递归实现遍历二叉树 1.1. 二叉树的前序遍历 1.2. 二叉树的中序遍历 1.3. 二叉树的后序遍历 一、非递归实现遍历二叉树 1.1. 二叉树的前序遍历 我们这里要使用栈来进行实现。我们反向思考一下为…

算法004——盛最多水的容器

力扣——盛最多水的容器点击即可跳转 当我们选择1号线和8号线时,下标为 1 和 8 形成容器的容积的高度是由 较矮的决定的,即下标为 8 的位置; 而宽度则是 1到8 之间的距离,为 8-17,此时容器的容积为 7 * 7 49。 当我…

算法-二叉树篇26-将有序数组转换为二叉搜索树

将有序数组转换为二叉搜索树 力扣题目链接 题目描述 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。 解题思路 很简单的遇到递归题目,对数组取半,然后构建中间节点作为该数组对应的…

十一、Spring Boot:使用JWT实现用户认证深度解析

Spring Boot JWT(JSON Web Token):无状态认证 在现代 Web 开发中,无状态认证是一种重要的安全机制,它允许服务器在不存储会话信息的情况下验证用户身份。JSON Web Token(JWT)是一种常用的无状态…

MIT何恺明再次突破传统:分形递归架构引爆生成模型新纪元!

论文链接:https://arxiv.org/pdf/2502.17437 代码链接:https://github.com/LTH14/fractalgen 亮点直击 分形生成模型:首次将分形理论引入生成模型,提出了一种具有自相似性的递归生成框架。 递归模块化:通过递归调用生…

用Python之requests库调用大型语言模型(LLM)API的流式输出与非流式输出比较

文章目录 1. 非流式输出与流式输出概述2. 非流式输出2.1 代码实例12.2 代码实例2 3. 流式输出3.1 流式输出的定义和作用3.2 流式输出适用的场景3.3 流式输出的实现方式与实现技术3.4 代码实例33.5 代码实例4 4. 小结 1. 非流式输出与流式输出概述 大模型收到输入后并不是一次性…

大模型技术:重塑未来的力量

大模型技术之所以成为当今科技领域的热点,是因为它拥有改变游戏规则的能力。以ChatGPT为例,这款由OpenAI开发的大型语言模型,首次实现了基于语言的智能涌现,推动了通用人工智能的技术飞跃和快速进化。大模型通过强大的数据处理能力…

【朝夕教育】《鸿蒙原生应用开发从零基础到多实战》005-TypeScript 中的枚举

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主&…

框架模块说明 #09 日志模块_02

背景 上篇我们介绍了系统日志处理方式,也结合我们实际和日志系统集成的需求,将我们的日志文件配置成json格式。这次我们针对我们操作日志的处理进行一些介绍。 还是采用传统的aop的形式进行操作日志的保存,并按业务类型进行定义保存到mongodb…