四、单例设计模式(Singleton Pattern)
4.1 介绍
单例模式是一种创建型模式,单例模式提供一个创建对象的接口,但是多次调用该接口返回的是同一个实例的引用,目的是为了保证只有一个实例,并且提供一个访问这个实例的统一接口。
4.2 Spring中单例bean的创建
Spring中默认配置的bean的scope为singleton,也就是单例作用域。那么看看它是如何做到的。
protected Object doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name);
Object bean = null; // 解决set循环依赖
Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) {
...
} else {
... // 创建单件bean.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args);
} catch (BeansException ex) {
... throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} //创建原型bean
else if (mbd.isPrototype()) {
...
} //创建request作用域bean
else {
...
}
}
... return bean;
}
getSingleton代码:
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) {
...
beforeSingletonCreation(beanName);
... try {
singletonObject = singletonFactory.getObject();
} catch (BeanCreationException ex) {
...
} finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
addSingleton(beanName, singletonObject);
} return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName);
}
}private final Map singletonObjects = CollectionFactory.createConcurrentMapIfPossible(16);
可知Spring内部四通过一个ConcurrentMap来管理单件bean的。获取bean时候会先看看singletonObjects中是否有,有则直接返回,没有则创建后放入。
看个时序图:
Spring的bean工厂管理的单例模式管理的是多个bean实例的单例,是工厂模式管理所有的bean,而每个bean的创建又使用了单例模式。
4.4 使用场景
同一个jvm应用的不同模块需要使用同一个对象实例进行信息共享。
需要同一个实例来生成全局统一的序列号