迴圈依賴就是依賴關係形成環,比如最簡單的迴圈依賴:A物件依賴B,B物件依賴A
通過以下xml方式設定一個迴圈依賴的範例:
<bean id="person1" class="com.example.leetcode.spring.bean.Person">
<property name="parent" ref="person2"></property>
<property name="name" value="tom"></property>
</bean>
<bean id="person2" class="com.example.leetcode.spring.bean.Person">
<property name="parent" ref="person1"></property>
<property name="name" value="jack"></property>
</bean>
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 這裡會檢查單例bean是否已經在登入檔,並返回。
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
...
}
複製程式碼
// 用來儲存已經建立好的單例物件
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 用來儲存單例beanname到ObjectFactory的對映
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 用來提前儲存還未初始化好的單例物件
/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
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;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
...
instanceWrapper = createBeanInstance(beanName, mbd, args);
...
// 檢查是否提前將單例bean存入快取
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 這裡將beanname與工廠對映放入快取登入檔中(也就是上面的singletonFactories)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
...
// 注入依賴屬性
populateBean(beanName, mbd, instanceWrapper);
...
}
假設我們從beanfactory獲取person1物件, 迴圈依賴處理流程如下:
在出現迴圈依賴時,三個map之間的流程如下:
earlySingletonObjects二級快取是雞肋嗎?
earlySingletonObjects快取的目的是,通過三級快取在獲取物件會執行一些列的後置處理器,通過earlySingletonObjects來快取提升效能。