循環(huán)依賴
@Component
public class Depend1 {
@Autowired
private Depend2 d;
public Depend1(){}
}
@Component
public class Depend2 {
@Autowired
private Depend1 d;
public Depend2(){}
}
假設(shè)Depend1先被實(shí)例化脊凰,當(dāng)屬性填充時(shí)腕让,其中一個(gè)屬性依賴Depend2沟优,就會(huì)跳至實(shí)例化Depend2隆嗅,當(dāng)Depend2屬性填充時(shí)功舀,又依賴Depend1棺棵,構(gòu)成了循環(huán)依賴谒撼。
通過(guò)set方法構(gòu)成循環(huán)依賴可以通過(guò)三級(jí)緩存解決食寡,但是通過(guò)構(gòu)造函數(shù)構(gòu)成的循環(huán)依賴會(huì)報(bào)錯(cuò)的
流程
AbstractBeanFactory的doGetBean創(chuàng)建bean時(shí),
做兩件事:
1廓潜、getSingleton(beanName)先從緩存中獲得已經(jīng)注冊(cè)的代理對(duì)象抵皱。通常獲得為null
2、如果沒(méi)有被注冊(cè)辩蛋,并且是單例時(shí)呻畸,getSingleton(beanName,ObjectFactory)創(chuàng)建對(duì)象,ObjectFactory定義了創(chuàng)建bean的具體方法
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
}else{
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
getSingleton(beanName,ObjectFactory)創(chuàng)建bean時(shí)
做兩件事:
1堪澎、通過(guò)傳入的ObjectFactory創(chuàng)建對(duì)象擂错,
2、finally中addSingleton(beanName,singletonObject) 將創(chuàng)建的bean加入緩存
此時(shí)bean已經(jīng)完成實(shí)例創(chuàng)建樱蛤、屬性注入钮呀、init方法執(zhí)行
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
boolean newSingleton = false;
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
上面的singletonFactory.getObject()實(shí)際調(diào)用的是doCreateBean
主要做
1、createBaenInstance()昨凡,會(huì)根據(jù)無(wú)參構(gòu)造器爽醋、工廠方法創(chuàng)建bean實(shí)例(還沒(méi)有依賴注入)
2、addSingletonFactory()將創(chuàng)建的bean放入緩存
注意:ObjectFactory中的getEarlyBeanRefernce會(huì)根據(jù)bean得到其代理對(duì)象
3便脊、之后是屬性注入
4蚂四、init方法執(zhí)行
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
// 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) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
return exposedObject;
}
可以看到bean對(duì)象實(shí)例化后屬性注入前會(huì)放入一次緩存,屬性注入等完成后會(huì)再次放入緩存哪痰。 每次獲得bean對(duì)象時(shí)先從緩存中撈取
下面看下注入屬性前放入緩存的操作
1遂赠、放入三級(jí)緩存,存的實(shí)際是獲得bean代理對(duì)象的方法晌杰,而不是bean對(duì)象
2跷睦、確保二級(jí)緩存中沒(méi)有
/**一級(jí)緩存 Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/**二級(jí)緩存 Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/**三級(jí)緩存 Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Set of registered singletons, containing the bean names in registration order */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
// ObjectFactory創(chuàng)建的是bean對(duì)象的代理對(duì)象
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
對(duì)象完全創(chuàng)建好后,再次放入緩存的邏輯:
1肋演、放入一級(jí)緩存singletonObjects抑诸,存儲(chǔ)的是bean對(duì)象的代理對(duì)象
2烂琴、保證二級(jí)緩存中沒(méi)有該bean
3、保證三級(jí)緩存中沒(méi)有該bean
/**一級(jí)緩存 Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/**二級(jí)緩存 Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/**三級(jí)緩存 Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Set of registered singletons, containing the bean names in registration order */
private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
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);
}
}
DefaultSingletonBeanRegistry
讀緩存時(shí):
1蜕乡、先從二級(jí)緩存中撈取
2奸绷、否則,從三級(jí)緩存中拿取獲得代理對(duì)象的方法层玲,并生成代理對(duì)象
3号醉、將代理對(duì)象放入二級(jí)緩存
4、移除三級(jí)緩存
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);
}
為什么要三級(jí)緩存
A.沒(méi)有循環(huán)依賴
1称簿、讀緩存:
①二級(jí)緩存中沒(méi)有
②三級(jí)緩存中沒(méi)有
2扣癣、通過(guò)BeanFactory創(chuàng)建bean后第一次放入緩存
①放入三級(jí)緩存
②一、二級(jí)緩存中清除
3憨降、屬性注入
4父虑、init
執(zhí)行BeanPostProcessor時(shí)會(huì)創(chuàng)建bean的代理對(duì)象
5、第二次放入緩存
①將代理對(duì)象放入一級(jí)緩存
②二三級(jí)緩存清除
B.循環(huán)依賴
1授药、Depend1讀緩存沒(méi)有
2士嚎、通過(guò)BeanFactory創(chuàng)建bean后第一次放入緩存
3、屬性注入時(shí)發(fā)現(xiàn)依賴Depend2悔叽,開(kāi)始創(chuàng)建Depend2對(duì)象
4莱衩、從緩存中讀Depend2,沒(méi)有
5娇澎、通過(guò)BeanFactory創(chuàng)建Depend2后第一次放入緩存
6笨蚁、屬性注入時(shí)發(fā)現(xiàn)依賴Depend1,開(kāi)始創(chuàng)建Depend1
7趟庄、從緩存中讀取Depend1
①二級(jí)緩存中沒(méi)有
②三級(jí)緩存中獲得BeanFactory創(chuàng)建代理對(duì)象
8括细、Depend2獲得Depend1的代理對(duì)象,完成屬性注入
9戚啥、完成Depend2創(chuàng)建
10奋单、Depend1獲得Depend2對(duì)象,完成創(chuàng)建
不考慮代理對(duì)象猫十,實(shí)際用二級(jí)緩存就可以解決循環(huán)依賴览濒,只需要?jiǎng)?chuàng)建實(shí)例后屬性注入前,將實(shí)例存入二級(jí)緩存拖云,循環(huán)依賴時(shí)直接從二級(jí)緩存中獲得bean對(duì)象
但是對(duì)外只能暴露bean對(duì)象的代理對(duì)象時(shí)贷笛,只能用三級(jí)緩存:
如果二級(jí)緩存中存儲(chǔ)bean對(duì)象,注入時(shí)注入的就不是代理對(duì)象
如果二級(jí)緩存中存儲(chǔ)創(chuàng)建bean對(duì)象的代理對(duì)象的BeanFactory宙项,則每次獲得的不是同一個(gè)代理對(duì)象