一、spring IOC 容器中的 Bean 单例
在 spring IOC 容器中,针对 Bean 的 scope 默认采用的是 单例的模式。
下图是 AbstractBeanDefinition
也就是 Bean定义的相关代码
从代码定义中能够知道,在 Spring IOC 中,如果没有指定,默认情况下 Bean是单例的。
不过这里的单例针对的是 IOC 而言,从单例的定义来说,只要保证某个对象的实例在同一环境下的唯一实例,他就是一个单例模式。
二、Mybatis 中的单例
在 Mybatis 中两个地方用到了单例模式,一个是 ErrorContext
,一个是 LogFactory
2.1、 ErrorContext
ErrorContext
相关代码如下
从代码能够得出, ErrorContext
是一个懒汉的单例模式,在需要使用的使用才创建,对于线程安全问题,这里使用的 ThreadLocal
来解决。
这是一个线程级别的单例模式。
还是从单例的定义出发,只要保证某个对象的实例在同一环境下的唯一实例,他就是一个单例模式。而这里的环境,就是某个线程上下文。
在之后讨论到线程设计模式线程上下文(Thread Context)时,会继续深入讨论一下 ThreadLocal
2.2、 LogFactory
LogFactory
相关代码如下
从代码能够看出来 LogFactory
是一个饿汉的单例模式,在类加载的时候就对对象进行了实例化操作。
三、项目中的单例
3.1、枚举类
在项目中或多或少都会使用到枚举类,比如:
我们使用枚举来表示状态的时候,本身就是单例模式的应用。
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、工具类的定义上
3.4、线程上下文的单例
通过线程上下文的单例用以传递信息,如:
通过 ThreadLocal 来实现线程间的单例模式,更多内容在多线程设计模式进行展开。
【公众号】花好夜猿