四懂诗、單例設(shè)計(jì)模式(Singleton Pattern)
4.1 介紹
阿里巴巴長(zhǎng)期招聘Java研發(fā)工程師p6,p7,p8等上不封頂級(jí)別殃恒,有意向的可以發(fā)簡(jiǎn)歷給我,注明想去的部門(mén)和工作地點(diǎn):1064454834@qq.com
歡迎關(guān)注微信公眾號(hào):技術(shù)原始積累 獲取更多技術(shù)干貨
單例模式是一種創(chuàng)建型模式离唐,單例模式提供一個(gè)創(chuàng)建對(duì)象的接口,但是多次調(diào)用該接口返回的是同一個(gè)實(shí)例的引用亥鬓,目的是為了保證只有一個(gè)實(shí)例域庇,并且提供一個(gè)訪(fǎng)問(wèn)這個(gè)實(shí)例的統(tǒng)一接口。
4.2 Spring中單例bean的創(chuàng)建
Spring中默認(rèn)配置的bean的scope為singleton熟呛,也就是單例作用域惰拱。那么看看它是如何做到的。
在AbstractBeanFactory類(lèi)里面的doGetBean方法:
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循環(huán)依賴(lài)
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
...
}
else {
...
// 創(chuàng)建單件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);
}
//創(chuàng)建原型bean
else if (mbd.isPrototype()) {
...
}
//創(chuàng)建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內(nèi)部四通過(guò)一個(gè)ConcurrentMap來(lái)管理單件bean的馋没。獲取bean時(shí)候會(huì)先看看singletonObjects中是否有降传,有則直接返回,沒(méi)有則創(chuàng)建后放入。
看個(gè)時(shí)序圖:
image.png
Spring的bean工廠管理的單例模式管理的是多個(gè)bean實(shí)例的單例笔链,是工廠模式管理所有的bean,而每個(gè)bean的創(chuàng)建又使用了單例模式鉴扫。
4.4 使用場(chǎng)景
- 同一個(gè)jvm應(yīng)用的不同模塊需要使用同一個(gè)對(duì)象實(shí)例進(jìn)行信息共享澈缺。
- 需要同一個(gè)實(shí)例來(lái)生成全局統(tǒng)一的序列號(hào)
歡迎關(guān)注微信公眾號(hào):技術(shù)原始積累 獲取更多技術(shù)干貨
image.png