單例在Spring的同一個(gè)容器中只會(huì)被創(chuàng)建一次,后續(xù)再獲取bean昨稼,就直接從單例緩存中獲取了溉箕。
先嘗試從SingletonObjects緩存中加載實(shí)例;如果不成功則嘗試從earlySingletonObjects中加載已經(jīng)在創(chuàng)建完成之前提前暴露的單例Bean悦昵;如果失敗了肴茄,則從singletonFactories中獲取beanName對(duì)應(yīng)的ObjectFactory,然后在調(diào)用ObjectFactory#getObject()方法創(chuàng)建對(duì)應(yīng)的Bean但指,并放到earlySingletonObjects中寡痰,并從SingletonFactories中remove掉這個(gè)ObjectFactory抗楔。而對(duì)于后續(xù)的所有操作都只是為了循環(huán)依賴檢測(cè)時(shí)候使用,也就是allowEarlyReference為true的情況下才使用拦坠。
為了解決循環(huán)依賴的問(wèn)題连躏,Spring中創(chuàng)建bean的原則是不等bean創(chuàng)建完成就會(huì)將創(chuàng)建bean的ObjectFactory提前曝光加入到緩存中, 一旦下一個(gè)Bean創(chuàng)建時(shí)需要依賴上一個(gè)bean則直接使用ObjectFactory贞滨。
1. 從緩存中獲取單例bean
beans.factory.support.DefaultSingletonBeanRegistry
@Override
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
/**
* Return the (raw) singleton object registered under the given name.
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
簡(jiǎn)單解釋一下用于存儲(chǔ)bean的不同的map
- singletonObjects
用于保存BeanName和創(chuàng)建bean實(shí)例之間的關(guān)系入热,bean name --> bean instance
- singletonFactories
用于保存BeanName和創(chuàng)建bean的工廠之間的關(guān)系,bean name --> ObjectFactory
- earlySingletonObjects
保運(yùn)BeanName和創(chuàng)建bean實(shí)例之間的關(guān)系晓铆,與singletonObjects的不同在于勺良,當(dāng)一個(gè)單例bean被放到這里面后,name當(dāng)bean還在創(chuàng)建過(guò)程中骄噪,就可以通過(guò)getBean方法獲取到了尚困,其目的是用來(lái)檢測(cè)循環(huán)引用。
- registeredSingletons
用來(lái)保存當(dāng)前所有已注冊(cè)的單例bean