springboot单例模式注入对象_设计模式系列之单例模式(SingletonPatte。。。

springboot单例模式注⼊对象_设计模式系列之单例模式
(SingletonPatte。。。
模式概述
模式定义
实际开发中,我们会遇到这样的情况,为了节约系统资源或者数据的⼀致性(⽐如说全局的Config、携带上下⽂信息的Context等等),有时需要确保系统中某个类只有唯⼀⼀个实例,当这个唯⼀实例创建成功之后,我们⽆法再创建⼀个同类型的其他对象,所有的操作都只能基于这个唯⼀实例。为了确保对象的唯⼀性,我们可以通过单例模式来实现,这就是单例模式的动机所在。
单例模式(Singleton Pattern): 确保某⼀个类只有⼀个实例,⽽且⾃⼰实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的⽅法。单例模式是⼀种对象创建型模式。
单例模式有三个要点:
1. 某个类只能有⼀个实例
2. 它必须⾃⾏创建这个实例
3. 它必须⾃⾏向整个系统提供这个实例
模式结构图
单例模式是结构最简单的设计模式⼀,在它的核⼼结构中只包含⼀个被称为单例类的特殊类。单例模式结构图如下所⽰:
单例模式结构图
单例模式结构图中只包含⼀个单例⾓⾊:
Singleton(单例):在单例类的内部实现只⽣成⼀个实例,同时它提供⼀个静态的getInstance()⼯⼚⽅法,让客户可以访问它的唯⼀实例;为了防⽌在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了⼀个Singleton类型的静态对象,作为外部共享的唯⼀实例。
饿汉式单例与懒汉式单例
饿汉式单例
人造神
饿汉式单例类是实现起来最简单的单例类。由于在定义静态变量的时候实例化单例类,因此在类加载的时候就已经创建了单例对象,典型代码如下:
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() { }
public static EagerSingleton getInstance() {
return instance;
}
}
懒汉式单例
懒汉式单例在第⼀次调⽤getInstance()⽅法时实例化,在类加载时并不⾃⾏实例化,这种技术⼜称为延迟加载(Lazy Load)或者懒加载技术,即需要的时候再加载实例,为避免多线程环境下同时调⽤getInstance()⽅法从⽽⽣成多个实例,需要确保线程安全,相应实现也就有多种⽅式。
第⼀种⽅法可以使⽤关键字synchronized,代码实现如下:
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() { }
波特五力分析public synchronized static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
在getInstance()⽅法前⾯增加了关键字synchronized进⾏同步,以处理多线程同时访问的安全问题。我们知道使⽤synchronized关键字最好是在离共享资源最近的位置加锁,这样同步带来的性能影响会减⼩。所以让⼈感觉上⾯的实现可以优化为如下代码:
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
instance = new LazySingleton();
}
}
return instance;
}
问题貌似得以解决,事实并⾮如此。如果使⽤以上代码来实现单例,还是会存在单例对象不唯⼀。原因如下:
假如在某⼀瞬间线程A和线程B都在调⽤getInstance()⽅法,此时instance对象为null值,均能通过instance == null的判断。由于实现
了synchronized加锁机制,线程A进⼊synchronized修饰的代码块中执⾏实例创建代码,线程B处于排队等待状态,必须等待线程A执⾏完毕后才可以进⼊synchronized修饰的代码块。但当A执⾏完毕时,
线程B并不知道实例已经创建,将继续创建新的实例,导致产⽣多个单例对象,违背单例模式的设计思想,因此需要进⾏进⼀步改进,在synchronized中再进⾏⼀次(instance == null)判断,这种⽅式称为双重检查锁定(Double-Check Locking)。使⽤双重检查锁定实现的懒汉式单例类典型代码如下所⽰:
public class LazySingleton {
private volatile static LazySingleton instance = null;
private LazySingleton() { }
public static LazySingleton getInstance() {
// 第⼀重判断
if (instance == null) {
// 使⽤synchronized关键字加锁
synchronized (LazySingleton.class) {
/
/第⼆重判断
if (instance == null) {
instance = new LazySingleton(); //创建单例实例
}
}
}
return instance;
}
}
需要注意的是,如果使⽤双重检查锁定来实现懒汉式单例类,最好在静态成员变量instance之前增加修饰符volatile,被volatile修饰的变量可以保证多线程环境下的可见性以及禁⽌指令重排序。由于volatile关键字会屏蔽Java虚拟机所做的⼀些优化,可能对执⾏效率稍微有些影响,因此使⽤双重检查
锁定来实现单例模式也不⼀定是最完美的实现⽅式。
如果是java语⾔的程序,还可以使⽤静态内部类的⽅式实现。代码如下:epad
public class Singleton {
private Singleton() {
}
private static class HolderClass {
final static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return HolderClass.instance;
}
}
由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第⼀次调⽤getInstance()时将加载内部类HolderClass,在该内部类中定义了⼀个static类型的变量instance,此时会⾸先初始化这个变量,由Java虚拟机来保证其线程安全性,确保该成员变量只初始化⼀次。
模式应⽤
模式在JDK中的应⽤
在JDK中,java.lang.Runtime使⽤了饿汉式单例,如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
}
模式在开源项⽬中的应⽤
Spring框架中许多地⽅使⽤了单例模式,这⾥随便举个例⼦,如org.springframework.aop.framework.ProxyFactoryBean中的部分代码如下:
/**
* Return the singleton instance of this class's proxy object,
* lazily creating it if it hasn't been created already.
* @return the shared singleton proxy
*/
cddprivate synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
一面五星红旗教学设计
Class> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
AllInterfacesForClass(targetClass, this.proxyClassLoader));
}
/
/ Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
模式总结
单例模式作为⼀种⽬标明确、结构简单、理解容易的设计模式,在软件开发中使⽤频率相当⾼,在很多应⽤软件和框架中都得以⼴泛应⽤。主要优点
(1) 单例模式提供了对唯⼀实例的受控访问。因为单例类封装了它的唯⼀实例,所以它可以严格控制客户怎样以及何时访问它。
(2) 由于在系统内存中只存在⼀个对象,因此可以节约系统资源,对于⼀些需要频繁创建和销毁的对象
单例模式⽆疑可以提⾼系统的性能。谭徽在
(3) 允许可变数⽬的实例。基于单例模式我们可以进⾏扩展,使⽤与单例控制相似的⽅法来获得指定个数的对象实例,既节省系统资源,⼜解决了单例单例对象共享过多有损性能的问题。
适⽤场景
在以下情况下可以考虑使⽤单例模式:
(1) 系统只需要⼀个实例对象,如系统要求提供⼀个唯⼀的序列号⽣成器或资源管理器,或者需要考虑资源消耗太⼤⽽只允许创建⼀个对象。
(2) 客户调⽤类的单个实例只允许使⽤⼀个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

本文发布于:2024-09-23 06:33:09,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/109480.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:单例   实例   对象   模式   实现
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议