23种设计模式之单例模式以及在MyBatis中的应用

记一次Redis出问题及解决方案 Q1: redis服务关闭前确认数据还是在的,重启后发现一条数据都没了,key* 查也是空的 A1: 经仔细检查发现redis.conf配置文件配置的数据存储目录配置的是dir ./ 也就是相对目录,也就是说在哪个目录执行redis-server redis.config启动命令 redis数据就会存到哪个目录,同样就会加载哪个目录下的数据文件(dump.rdb),前后两次启动命令的位置不一样导致第二次启动没有加载到(dump.rdb)文件,从而导致查不出数据 Q2:springboot 集成r 阅读详情

什么是单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

以上的话用我自己的语言来叙述就是:我们可以提供一种只能创建一个对象的类,这个对象在运行时内存中只能有一份。
接下来我们来看如何保证这个对象在运行时内存中只能有一份

单例模式的几种实现方式:

该模式的实现方式有多种,我将列出最经典的几种,其实知道了这几种其他的也就不难理解了:

1、懒汉式,线程不安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

在上面的代码中能实现单例的主要原因主要在于构造方法是私有的,在类的外部无法创建对象,然后只要在内部事先创建好本类对象,并通过对外开放的静态公有方法返回该内部创建的对象,但这里是线程不安全的,我们来解析一波为什么多线程下会破坏其中的单例:
当两个线程对这同一个getInstance方法进行调用时,由于在两个线程中instance此时没有引用任何对象,所以判断出instance都为空,所以在两个线程中都会返回不同的对象,显然这违背了单例,如果要是按照严格意义来说,我觉得上面不能称之为单例模式。
下面我再介绍几种线程安全的单例:

2、懒汉式,线程安全

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
	    if (instance == null) {  
	        instance = new Singleton();
	    }
    	return instance;
    }
}

上面的代码与上面唯一不一样的就是在getInstance方法前加上了synchronized关键字,意思是给这个方法加上了线程锁,每次只允许一个线程执行该资源,其他线程在外面等着!那么这样就不会出现上面这种创建多个对象的情况了,但是这样效率会大大折扣了。
下面再来另外一种饿汉式单例

3、饿汉式,天然线程安全

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    	return instance;  
    }  
}

这种给静态属性初始化的方式叫饿汉式,然后在外部调用该类getInstance方法获取该类静态对象。
为什么这种方式是线程安全的呢,我们再来解释一波为什么这是线程安全的:
当类在加载的时候类的静态属性就会初始化,要优先于其他代码,也就是说当我们调用getInstance时instance已在静态区了,所以返回的总是一个对象,不管几个线程同时调用都是一样,所以这个方法中也不用判断instance是否为空。
但是也不免会遇到利用其他方式导致了类的加载初始化,所以这种方式在某种情况下会产生垃圾对象

4、双检锁/双重校验锁(DCL,即 double-checked locking)

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
	    if (singleton == null) {  
	        synchronized (Singleton.class) {  
		        if (singleton == null) {  
		            singleton = new Singleton();  
		        }  
	        }  
	    }  
    return singleton;  
    }  
}

可以看到这个双重校验锁就是在懒汉模式的基础上加上了volatile和synchronized修饰,这种方式线程安全,而且还能在多线程中保证程序的效率,那么我们来解释一下这种机制原理:
首先可以看到我们的静态属性加上了volatile关键字修饰,这样可以防止指令重排序造成的线程不安全问题,比如singleton在没有加volatile的情况下,对象在线程A中发生new操作时发生了指令重排,因为new大致可以分为3个步骤,1.开辟内存,2.将这片内存初始化,3.使singleton引用指向这片内存,我们可以发现这并不是一个原子操作,2和3没有依赖,所以2和3会发生重排序,那么这两个发生了重排序的话,B线程会发现这个对象初始化不成功,这个时候就会发生异常,所以我们就得加上volatile防止指令重排序。
现在再来看看方法中的那两个双重校验,也就是那两个if:第一个if若是不成立则100%创建好该对象了,这样就不会经过这个锁,这也就是效率高的原因,接下来就是锁中的if,其实这个if会在多个线程同时访问时都为null是才会走到这里来,也就是第一次实例化的时候,然后只要有一个线程出了这个锁,那么其他线程进锁这个if绝对不会成立,因为其他线程已经创建好对象了。

5、登记式/静态内部类

public class Singleton {  
    private static class SingletonHolder {  
   		private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() { 
    	return SingletonHolder.INSTANCE;  
    }  
}

显然这种方式可以与双重校验锁方法达到同样的效果,同时又与饿汉式相似都在类加载时实例化,不同的是登记式是一种延迟加载,就是在加载Singleton类是不会实例化INSTANCE对象,加载本类的静态内部类才会实例化,这样我们可以保证getInstance方法获取到的是一个唯一的示例对象。为什么饿汉式可能会发生多次加载而登记式不会呢?首先getInstance是一个静态方法,整个程序只有一份,当多个线程访问同一个getInstance时内部类SingletonHolder会保证只加载一次,所以这样又可以达到与双重校验锁一样高的效率

6、枚举,线程安全,完美

public enum  Singleton {
    OBJ;
    private Object obj = null;
    private Singleton(){
        obj = new Object();
    }
    public Obj getInstance(){
        return obj;
    }
}

/*Test*/
public class Test {
    public static void main(String[] args) {
        Object obj1 = Singleton.OBJ.getInstance();
        Object obj2 = Singleton.OBJ.getInstance();
        System.out.println(obj1 == obj2);	//结果为true
    }
}

它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
亲自测试如下:
在这里插入图片描述
通过反汇编可以发现下面这几行代码:

 static {
	 OBJ = new Singleton("OBJ", 0);
	  $VALUES = (new Singleton[] {
	      OBJ
	  });
    }

其实enmu底层是通过继承Enmu类来实现的,这是其中的一部分代码,其中源码与饿汉式的实现差不多,但是这种方式天然防反射,线程安全,效率高,可以使用这种方法。
这里太多的解释我也不做出来了,因为我本身没有深入研究过这里的源码

MyBatis中使用单例创建会话对象

我们首先要知道,mybatis与数据库进行交互时需要获取xml文件中的数据库连接信息,整个获取对象就是一个工厂模式,但是我们希望这个对象只有一份,因为这样就可以达到更高的效率,和节省更多的空间,因为在频繁的读取xml时会消耗很多性能,所以我们把读取文件作为单例,先看如下代码:

public class MyBitesUtil {
	//工厂,可以生产SqlSession对象
	static SqlSessionFactory factory = null;
	//静态代码块
	static {
		try {
			InputStream is = 
		 			Resources.getResourceAsStream("config/mybatis-config.xml");
			factory =  new SqlSessionFactoryBuilder().build(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	public static SqlSession getSqlSession() {
		return factory.openSession();
	}
}

由于factory是只有单份的了,所以再关闭了factory之后,在次调用getSqlSession方法就不用再次重新读取xml文件了,只要将关闭后的factory对象再次open就ok了
还提供一种方式:

public class MyBitesUtil {
    private static MyBitesUtil factory;

    /**
     * 私有化构造
     */
    private MyBitesUtil(){
    }
    /*
    * 单实例对象
     */
    public static MyBitesUtil init(){
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        }catch (IOException e){
            e.printStackTrace();
        }
        synchronized (MyBitesUtil.class){
            if(factory == null){
                factory = new SqlSessionFactoryBuilder().build(inputStream);
            }
        }
        return factory;
    }

    public static SqlSession getSqlSession(){
        if (factory == null){
            init();
        }
        return factory.openSession();
    }

}

我只列出以上两个示例,其实知道了上面的两个示例,其他的方法自己也能够写的出来了,现在可以自己动手试一试了。

【K8S系列】Kubernetes 中 Pod 无法通过 Service 名称访问服务的 DNS 解析失败问题【已解决】 在 Kubernetes 中,Service 提供了一种稳定的方式,通过名称访问一组 Pod。当其他 Pod 无法通过 Service 名称访问服务,并且出现 DNS 解析失败时,通常会导致应用无法正常工作。本文将详细分析此问题的常见原因及其解决方案。 阅读详情

相关推荐

Mybatis系列9:单例模式在Mybatis查找文件路径中的应用

包装器模式在Mybatis中的应用

纵横千里 捭阖四方 的专栏 356

VMware Workstation Pro 17 高效安装与激活指南

本文详细介绍了VMware Workstation Pro 17的高效安装与激活方法,包括系统要求、安装步骤、常见问题解决方案及性能优化技巧。通过专业的指导,帮助用户快速掌握这款强大的虚拟机软件,提升工作效率。

weixin_29322855的博客 398

MyBatis设计模式之单例模式

mybatis 源码中单例模式如下: 1 获取ErrorContext 实例。 ErrorContext是用在每个线程范围内的单例,用于记录该线程的执行环境错误信息。ErrorContext的单例实现代码: ​​ ...

DJLDYHZSZ的博客 1569

基于STM32开发的智能语音控制系统

本文将介绍如何使用STM32微控制器开发一个智能语音控制系统,通过语音识别模块、OLED显示屏、Wi-Fi模块等实现对家用电器或其他设备的语音控制。智能语音控制系统的核心是STM32微控制器,通过语音识别模块识别用户的语音指令,并根据指令控制家用电器或其他设备。:定期测试语音识别模块、继电器控制模块、OLED显示屏和Wi-Fi模块的工作状态,确保系统能够在各种情况下正常运行,并保持智能语音控制系统的可靠性。本系统同样适用于办公环境,可以通过语音指令控制办公室设备,如照明、空调等,提供智能化的办公体验。

stm32d1219的博客 6905

MDPI期刊投稿全流程解析:从注册到提交的实用指南

本文详细解析了向MDPI期刊投稿的全过程,从注册账号、完善个人资料、上传稿件,到填写作者信息、推荐审稿人及提交附信等关键步骤。指南强调了使用机构邮箱、遵循期刊模板、认真准备Cover Letter等实用技巧,旨在帮助作者高效、规范地完成投稿,避免常见错误,提升稿件处理效率。

weixin_29250403的博客 916

Mybatis-设计模式总结

Builder模式的定义是“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。”,它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加复杂的对象的构建,甚至只会构建产品的一个部分。

输入知识,消化知识,输出知识,分享知识,教人让我学习更好,业精于勤荒于嬉,行成于思毁于随 1668

NHANES更新数据后,权重计算方式也更新了

官网说明在此:如果你比我还懒,我下载了几个说明文件。2021年8月至2023年8月的总样本量与之前的2年周期相似。然而,。特别是,与之前包括过度抽样的周期相比,非西班牙裔白人的样本量较高,而非西班牙裔黑人的样本量较低。此外,60岁及以上人群的样本量较高,而年轻群体的样本量较低。子组的估计值可能具有较低的精确度,因此,检测组间差异的统计能力可能较低。此外,年龄和种族/西班牙裔亚组(尤其是儿童和青少年年龄组)的估计值可能会显示意想不到的模式。

珏世佳人的博客 2407

Mybatis源码单例模式详解

定义 单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。 1. 获取ErrorContext实例 ErrorContext是用在每个线程范围内的单例,用于记录该线程的执行环境错误信息。 代码片段 public class ErrorContext { private static final String LINE_SEPARAT...

半页童话 878

RK3588 部署 YOLO26 目标检测:从环境搭建到 NPU 推理

采集图像(500+ 张,覆盖不同光照和角度)→ 筛选(删除模糊、无目标的图像)→ LabelImg 标注(选择 YOLO 格式)→ 划分 train:val:test = 7:2:1labelImg├── train/├── val/nc: 3类别顺序必须与 LabelImg 标注时一致。YOLO26 在 RK3588 上的部署流程是 PC 端训练 → ONNX 导出(opset=11)→ RKNN 转换(INT8 量化)→ 板端推理。

LXY_LOVE36的博客 403

ATECC508A芯片开发笔记(三):获取508A串号、随机数源码及I2C抓包分析

ATECC508A芯片开发笔记(三):读取508A串号、获取随机数源码及I2C抓包分析 APP层函数编写及源码分析 At508_GetSernum() GetSernum抓包记录 At508_GetRandom( ) GetRandom抓包记录 经过前两章节,CryptoAuthlib库已经成功适配在代码中了,下面简单测试一下API函数,并分析下I2C通讯流程: APP层函数编写及源码分析利用li

HowieXue 薛永浩的博客 2万+

mybatis基础知识

mybatis基础知识 mybatis的定义:mybatis是一个java持久层框架,java中操作关系型 数据库用的是jdbc,mybatis是对jdbc的一个封装。 一 、MyBatis架构: 二 、MyBatis入门程序 需要4个配置文件: log4j.properties(公用文件) SqlMapConfig.xml (mybatis全局配置文件,只有一个,主要全局配置,加载map...

weixin_43900110的博客 282

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【设计模式】之单例模式详解与应用(四)

开心一刻【女人问的问题,70%她都是知道答案才问的,所以还是老实交待哦~~~】课程介绍总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态

IT技术分享 666

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

(Java笔记)多态和HungrySingle设计模式

第一章 多态 多态:意为多种形态,在不同的场景下会表现的不同 1.1 如何编写多态 public class Test { public static void main(String[] args) { //1: 父类变量指向子类对象 Animal an = new Dog();//编译看左边 运行看右边 //2:多态 an...

qq_45734860的博客 269

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

常见设计模式在mybatis中的应用

请你说说,设计模式在mybatis有哪些具体的应用? 设计模式分类 是不是看着头大,哈哈;头大就对了,我们没必要每个都去深究,我们只需要结合例子知道部门设计模式是如何使用的就可以了!接下来我们结合mybatis这个框架,探讨下常用设计的使用吧! 关于设计模式的示例及讲解可以看C语言中文网中关于设计模式的描述及示例:23种设计模式详解 那么mybatis中运用的设计模式有哪些呢? 工厂模式 简单理解,就是工厂模式就是提供一个工厂类,当客户端需要调用的时候就可以得到想要的结果,而不需要关注内部的实现!就好.

iME_cho的博客 543

Mybatis 源码系列:领略设计模式在 Mybatis 其中的应用

,它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和Builder模式,相对于工厂模式会产出一个完整的产品,Builder应用于更加复杂的对象的构建,甚至只会构建产品的一个部分。在这个过程中,有一个相似的特点,就是这些Builder会读取文件或者配置,然后做大量的XpathParser解析、配置或语法的解析、反射生成对象、存入结果缓存等步骤,这么多的工作都不是一个构造函数所能包括的,因此大量采用了Builder模式来解决。

程序人生 1284

跟着Mybatis 学习 23 种设计模式

MyBatis框架中应用了23种设计模式,主要分为创建型、结构型和行为型三大类。在创建型模式中,工厂方法(SqlSessionFactory)、单例(ErrorContext)、建造者(SqlSessionFactoryBuilder)等模式用于对象创建和管理。结构型模式如适配器(Log接口)、装饰器(Cache)、代理(Mapper接口)等处理对象间关系。行为型模式包括策略(Executor)、模板方法(BaseExecutor)等控制对象行为。这些模式协同工作,使MyBatis具有灵活、可扩展的架构,如

csdn_tom_168的博客 758

MyBatis 和 Spring 中的 23 种设计模式,真香,拿去用吧!

大家都知道源码框架有23个设计模式,但是我们大多停留在概念层面,真实开发中很少应用到,也不知道如何落地!!!那有没有办法解决了?我整理了Mybatis和Spring源码中使用了大量...

架构师小秘圈 353

Mybatis 使用的 9 种设计模式

虽然我们都知道有 23 个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。Mybatis至少遇到了以下的设计模式的使用:Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

2401_83384536的博客 820

23种设计模式精髓与经典应用案例全流程解析

设计模式不是死记硬背,而是解决实际业务问题的套路。通过分类梳理、流程图、生命周期图和时序图,结合经典源码和应用场景,能够建立系统性认知,提升架构能力。无论单体还是分布式,合理运用设计模式,都是高质量系统的关键。知其然,更知其所以然。愿你成为架构高手!

IT技术学习与工作笔记分享 1171

Java 23 种设计模式:从踩坑到精通 —— 开篇及系列介绍

摘要:本文是《Java 23种设计模式:从踩坑到精通》系列的总入口与导航页。文章梳理了设计模式的起源与三大分类,结合SOLID六大原则,详解为什么2026年设计模式依然重要。提供25篇完整目录、面试高频Top10速记、场景速查索引、易混模式对比表及分级阅读路线,可作为长期收藏的设计模式学习手册。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 3333

Java设计模式全解析(共 23 种)

Java 中的设计模式是为了解决在软件开发中常见问题的一些“最佳实践”总结。设计模式分为三大类,共 23 种经典模式:

xxiaobaibaibai的博客 1134

23种设计模式面试题宝典:从基础到高级全面解析(2025持续更新版)

设计模式是软件设计中常见问题的典型解决方案,是可复用面向对象软件的基础。掌握设计模式不仅能够写出更优雅、更易维护的代码,更是高级开发者面试的必考内容。三大分类体系及核心关注点分类包含模式关注重点创建型模式(5种)单例、工厂、抽象工厂、建造者、原型对象创建机制,降低创建和使用的耦合度结构型模式(7种)适配器、装饰器、代理、外观、桥接、组合、享元类和对象的组合,形成更大的结构行为型模式(11种)策略、模板方法、观察者、迭代器、责任链、命令、备忘录、状态、访问者、中介者、解释器。

用文字记录技术,用分享回馈社区,用坚持见证成长 1万+

项目中那会用到单例模式_面试吹牛用:Mybatis 中用到的 9 种设计模式!

点击上方蓝色字体,选择“标星公众号”优质文章,第一时间送达上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家(已修复)下一篇:昨天分享资料不小心把百度网盘深处的秘密泄露了(已修复)作者:叶修之秋来源:juejin.im/post/5d01f0e4f265da1bc23f726a虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到。Mybatis源码中...

weixin_30415591的博客 180

Mybatis 中经典的 9 种设计模式

虽然我们都知道有23个设计模式,但是大多停留在概念层面,真实开发中很少遇到。Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的使用: 1、Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStateme...

yamaxifeng_132的专栏 1558

GOF23种设计模式-单例模式

单例模式 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。 比如Mybatis的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式。 单例模式有八种方式: 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方

MARK19960120的博客 227
上一篇: 使用MyBatis实现分页
下一篇: MyBatis(笔记,第五部分注解)
min黎子
博客等级 码龄8年 24粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值