单例在生产开开发中属于常见的设计模式。

一、spring IOC 容器中的 Bean 单例

在 spring IOC 容器中,针对 Bean 的 scope 默认采用的是 单例的模式。

下图是 AbstractBeanDefinition 也就是 Bean定义的相关代码
01.png

从代码定义中能够知道,在 Spring IOC 中,如果没有指定,默认情况下 Bean是单例的。

不过这里的单例针对的是 IOC 而言,从单例的定义来说,只要保证某个对象的实例在同一环境下的唯一实例,他就是一个单例模式。

二、Mybatis 中的单例

在 Mybatis 中两个地方用到了单例模式,一个是 ErrorContext ,一个是 LogFactory

2.1、 ErrorContext

ErrorContext 相关代码如下
02.png

从代码能够得出, ErrorContext 是一个懒汉的单例模式,在需要使用的使用才创建,对于线程安全问题,这里使用的 ThreadLocal 来解决。

这是一个线程级别的单例模式。

还是从单例的定义出发,只要保证某个对象的实例在同一环境下的唯一实例,他就是一个单例模式。而这里的环境,就是某个线程上下文。

在之后讨论到线程设计模式线程上下文(Thread Context)时,会继续深入讨论一下 ThreadLocal

2.2、 LogFactory

LogFactory 相关代码如下
03.png
从代码能够看出来 LogFactory 是一个饿汉的单例模式,在类加载的时候就对对象进行了实例化操作。

三、项目中的单例

3.1、枚举类

在项目中或多或少都会使用到枚举类,比如:
04.png
我们使用枚举来表示状态的时候,本身就是单例模式的应用。

3.2、SpringFramework的使用

前面提到 Spring IOC 的 Bean 默认都是单例,而我们在使用 springframework 过程中加上的 @Component 或者派生注解,如:@RestController@Service 表示的就是将当前对象实例
托管给 spring IOC 管理,同时默认情况下,在同一个 IOC 容器中的 Bean 是单例的。

小贴士: 在代码使用过程中,可以通过 API 或者注解的方式来显式声明 Bean scope ,如:注解方式可以使用 @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) 如果是 @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) 就没有必要显式声明了,因为默认的就是 单例。

3.3、工具类的定义上

在工具类的定义上,定义JVM范围内的单例,供项目使用,如:
05.png

3.4、线程上下文的单例

通过线程上下文的单例用以传递信息,如:
06.png
通过 ThreadLocal 来实现线程间的单例模式,更多内容在多线程设计模式进行展开。


【公众号】花好夜猿
wxlogo.jpg