先看為什麼循環依賴怎麼出現的? 比如有AService和BService,具體代碼如下:
class AService {
@Autowired
BService b;
}
class BService {
@Autowired
AService a;
}
上面的代碼 A中引入了B,B中引入了A,這樣當spring執行個體A的時候,看到@Autowired引入了BService,然後會去執行個體化BService,執行個體化BService的時候,屬性中又引入了AService,是以又會去執行個體化AService,如此循環下去産生了循環依賴。
解決方法
在執行個體化A後(屬性注入之前),把它放入一個Map中暫時叫Map1,然後再注入屬性,執行個體化B去,執行個體化B的時候,B又需要引入A,此時直接從前面的Map1中去取出,
此時取出的A和前面執行個體化的A是同一個引用。
然後B執行個體化完并且屬性注入完成後,繼續執行A的屬性注入流程,後續A屬性注入也完成了。因為A都是同一個引用,是以此時B中持有的是完整的A執行個體。
A執行個體化完整後,再把A放入另一個Map中,這個Map都是放完整的執行個體化後的類的,上面的Map1存放的是沒有注入屬性的執行個體化類。
看樣子不需要三級緩存了為什麼還需要三級緩存?
三級緩存主要為了解決動态代理的問題。
下圖總結的圖檔
源碼細節
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
...
// 從三級緩存中擷取執行個體對象的邏輯,注意這裡可能來自于一級緩存/二級緩存/三級緩存
Object sharedInstance = getSingleton(beanName);
// 如果緩存中有,就進行一定的邏輯處理直接傳回。
if (sharedInstance != null && args == null) {
// 傳回執行個體對象。
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 調用建立執行個體的方法
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 從一級緩存讀取執行個體對象(完整的執行個體對象)
Object singletonObject = this.singletonObjects.get(beanName);
// 如果一級緩存沒有
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 從二級緩存擷取執行個體對象
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果二級緩存沒有
if (singletonObject == null && allowEarlyReference) {
// 加一個鎖,保證一緻性,待研究
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
// 一級緩存沒有,從二級緩存拿
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
// 二級緩存沒有,從三級緩存拿
if (singletonObject == null) {
// 從三級緩存拿,拿出來的是一個FactoryBean
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 調用FactoryBean的getObject方法。這裡可能會生成代理對象,也可能是非代理對象
singletonObject = singletonFactory.getObject();
// 生成的對象,放入二級緩存
this.earlySingletonObjects.put(beanName, singletonObject);
// 删除三級緩存的類
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
上面重要的方法是createBean,它調用了doCreateBean,它是重要的方法繼續分析
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
// 重要的方法,注意第二個參數是lamda表達式,看他傳入的參數是ObjectFactory,隻有一個方法getObject
// 就是在上面getSingleton方法中會去調用觸發的。addSingletonFactory會把ObjectFactory對象
// 放入三級緩存中。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
...
Object exposedObject = bean;
try {
// 屬性注入,在這個方法中會再次執行doGetBean方法,第二次再此執行該方法的時候,緩存中就會存在第一次進入的時候執行個體化好的半成品bean了。
populateBean(beanName, mbd, instanceWrapper);
// 調用各種回調接口
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
繼續分析getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 周遊實作了SmartInstantiationAwareBeanPostProcessor接口的實作類
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
// 這裡是擷取FactoryBean執行個體的
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
/**
* 此方法是核心,預設的實作是直接傳回傳入的bean執行個體
*/
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
這裡還有一個SmartInstantiationAwareBeanPostProcessor的實作類,就是生産AOP代理類AbstractAutoProxyCreator,看它的getEarlyBeanReference方法
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
...
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 生成動态代理,這塊在我的另一個文檔中分析動态代理生成的地方有提到。
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
...
}