protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//首先檢查一級緩存中是否存在
Object singletonObject = this.singletonObjects.get(beanName);
/** * 若是一級緩存中不存在表明當前 Bean 還未被建立或者正在建立中 * 檢查當前 Bean 是否正處於正在建立的狀態中(當Bean建立時會將Bean名稱存放到 singletonsCurrentlyInCreation 集合中) */
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//檢查二級緩存中是否存在
singletonObject = this.earlySingletonObjects.get(beanName);
/** * @@若是二級緩存中不存在 而且 容許使用早期依賴 * allowEarlyReference : 它的含義是是否容許早期依賴 * @@那麼什麼是早期依賴? * 就是當Bean還未成爲成熟的Bean時就提早使用它,在實例化流程圖中咱們看到在添加緩存前剛剛實例化Bean可是還未依賴注入時的狀態 */
if (singletonObject == null && allowEarlyReference) {
//獲取三級緩存中的 Bean ObjectFactory
ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
//若是 Bean 對應的 ObjectFactory 存在
if (singletonFactory != null) {
//使用 getObject 方法獲取到 Bean 的實例
singletonObject = singletonFactory.getObject();
//將 bean 從三級緩存提高至二級緩存
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 {
/** * 咱們一開始經過 getSingleton() 方法中獲取三級緩存中存放的Bean,這裏就是向三級緩存中添加 bean 的地方 * 流程: * 1.檢查當前 bean 是否爲單例模式,而且是否容許循環引用[講解1],而且當前是否正在建立中(在getSingleton方法中添加的) * 2.若是容許提早曝光[講解2],addSingletonFactory() 方法向緩存中添加當前 bean 的 ObjectFactory * * [講解1]:當前 Bean 若是不容許循環引用(循環依賴也就是被依賴),則這裏就不會提早曝光,對應的 ObjectFactory * 則當發生循環依賴時會拋出 BeanCreationException 異常 * * [講解2]:提早曝光的含義就是說當 bean 還未建立完畢時就先將建立中狀態的bean放到指定緩存中,爲循環依賴提供支持 */
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//須要提早曝光
if (earlySingletonExposure) {
/** * 向緩存(三級緩存)中添加當前 bean 的 ObjectFactory */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
/** * Initialize the bean instance. * 初始化 Bean 實例階段 */
Object exposedObject = bean;
try {
/** * 依賴注入這時會遞歸調用getBean */
populateBean(beanName, mbd, instanceWrapper);
//調用初始化方法,如:init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
/** * 當容許提早曝光時進入判斷 * @這裏作了什麼? * 1.檢查當前bean是否經歷了一場循環依賴 * - 經過 getSingleton(beanName,false) 獲取緩存中的 bean,傳入 false 表明不獲取三級緩存中的bean * - 爲何說 檢查當前bean是否經歷了一場循環依賴呢? 由於上述說了傳入 false 表明不獲取三級緩存的 * - 那麼什麼狀況下才會存在與一級緩存和二級緩存呢?答案就是循環依賴後 [解釋1] 和bean實例化完成後 * - 因此若是 getSingleton 返回的 bean 不爲空,則這個bean就是剛剛經歷了循環依賴 * * 2.檢查提早曝光的bean和當前的Bean是否一致 * - 下面有個判斷 if (exposedObject == bean) ,這個判斷從緩存中獲取的bean 和 經歷過初始化後的 bean * - 是否一致,可能咱們有點暈,這裏解釋一下,緩存從的bean是何時存進去的?是在 addSingletonFactory 方法(649行) * - 而後這裏存進去的 bean 只是提早曝光的 bean,尚未依賴注入和初始化,可是在依賴注入和初始化時都是可能直接改變 * - 當前 bean 的實例的,這意味着什麼?意味着經歷了依賴注入和初始化的bean極可能和緩存中的bean就已經徹底不是一個 bean了 * 下面講解當一致或不一致時的邏輯: * 2.1 一致: * 不是很理解,直接賦值,但是經歷了各類 BeanPostProsser 或者依賴注入和初始化後不是就不同了嗎 * 2.2 不一致: * 看下方對於 else if 代碼塊的解釋 * * @[解釋1] * 當循環依賴時,A依賴着B,B依賴着A,實例化A首先將A放到三級緩存中而後發現依賴着B,而後去實例化B,發現依賴着A * 發現A在三級緩存,而後獲取三級緩存中的bean而且將A從三級緩存中提高到二級緩存中,實例化B完成,接着實例化A也完成。 * * @通俗講解 * 假設咱們業務上對某種數據加了緩存,假設 i 在緩存中存的值爲1,當我在數據庫中把 i 的值改爲 2 時,緩存中的 i 尚未被改變仍是 1 * 這時的數據已經和咱們的真實數據偏離了,不一致了,這時有兩種解決方式:1.服務器檢查到數據不一致拋出異常。(也就是進入else if 代碼塊) * 2.直接使用原始值也就是1(也就是將 allowRawInjectionDespiteWrapping 改爲 true),固然這兩種方式明顯不是咱們正常數據庫的操做,只是 * 爲了說明當前的這個例子而已。 * */
if (earlySingletonExposure) {
//獲取緩存中(除三級緩存) beanName 對應的 bean
Object earlySingletonReference = getSingleton(beanName, false);
//當經歷了一場循環依賴後 earlySingletonReference 就不會爲空
if (earlySingletonReference != null) {
//若是 exposedObject 沒有在初始化方法中被改變,也就是沒有被加強
if (exposedObject == bean) {
//直接賦值? 但是經歷了各類 BeanPostProsser 或者依賴注入和初始化後不是就不同了嗎
exposedObject = earlySingletonReference;
}
/** * * 走到 else if 時說明 當前 Bean 被 BeanPostProessor 加強了 * 判斷的條件爲: * 1.若是容許使用被加強的 * 2.檢查是否存在依賴當前bean的bean * * 若是存在依賴的bean已經被實例化完成的,若是存在則拋出異常 * 爲何拋出異常呢? * 由於依賴當前bean 的bean 已經在內部注入了當前bean的舊版本,可是經過初始化方法後這個bean的版本已經變成新的了 * 舊的哪一個已經不適用了,因此拋出異常 * */
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
/** * Register bean as disposable. * 註冊 Bean 的銷燬方法拓展 */
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}複製代碼
我也在學習過程當中,若是發現文中有不對的地方請直接聯繫捶我就好,若是有興趣能夠聯繫我咱們一塊兒學習!java