真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【Spring6源碼?IOC】Bean的初始化-終結(jié)篇-創(chuàng)新互聯(lián)

前面兩篇,我們著重講解了一下《BeanDefinition的加載》和《bean的實(shí)例化》。

河口ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

這一篇我們來講解一下bean的初始化。

在這里插入圖片描述

我們這里的案例依舊是以SpringBoot3.0、JDK17為前提,案例代碼如下:

@Component
public class A {

    @Autowired
    private B b;
    
}
@Component
public class B {

    @Autowired
    private A a;
}

首先,先明確一下這個三級緩存:

一級緩存 singletonObjects 中存放完全初始化好的 bean 的實(shí)例。
二級緩存 earlySingletonObjects中存放早期對象(未完全初始化完成的 bean 實(shí)例)。
三級緩存 singletonFactories 中存放 bean 工廠對象。

bean 創(chuàng)建起來比較復(fù)雜,所以將bean緩存起來,方便之后使用。

上一篇,我們實(shí)例化了bean之后,將bean放入了第三級緩存,看一下這個addSingletonFactory方法,如果一級緩存中沒有對應(yīng)的bean,那么會將未初始化的bean放入三級緩存,會將bean提前暴露出來。
在這里插入圖片描述

在這里插入圖片描述
接下來,會通過populateBean()方法對bean的屬性進(jìn)行填充。
在這里插入圖片描述
步入populateBean()方法,首先會獲取BeanPostProcessors,主要是在bean初始化之前做一些事情,如下,我們總共獲取到4個BeanPostProcessors ,最后一個AutowiredAnnotationBeanPostProcessor是本節(jié)較為關(guān)鍵的BeanPostProcessor,它主要是用來處理我們@Autowired注解。

在這里插入圖片描述
我們進(jìn)入到AutowiredAnnotationBeanPostProcessor#postProcessProperties方法中,首先有個findAutowiringMetadata方法來處理@Autowired

在這里插入圖片描述
我們步入findAutowiringMetadata方法中,發(fā)現(xiàn)會從injectionMetadataCache的map集合中獲取。

在這里插入圖片描述

但是我們沒有往這個緩存中put對象啊,所以,這個metadata是null,而后,我們會簡單的判斷一下:

public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Classclazz) {
		return (metadata == null || metadata.needsRefresh(clazz));
	}

如果為null,我們會調(diào)用buildAutowiringMetadata方法,在這里我們會看到很熟悉的設(shè)計(jì),就像單例模式一樣的雙重鎖/雙重校驗(yàn)鎖(DLC,即double-checked locking)

而后會進(jìn)入buildAutowiringMetadata方法去創(chuàng)建相關(guān)信息。

這里主要有兩點(diǎn),一個是針對屬性上的注解,一個是針對方法上的注解,大部分的時候會放在屬性上,也有時候會放在方法上,比如set方法上。
在這里插入圖片描述
我們來一起看一下這個處理屬性的doWithLocalFields方法,首先通過getDeclaredFields方法獲取類的屬性集合,然后進(jìn)行遍歷調(diào)用函數(shù)去處理。

在這里插入圖片描述
我們來看一下是如何獲取類的屬性數(shù)組的,還用想嘛,當(dāng)然是反射了,不信你看。第一次從屬性緩存中獲取,肯定獲取不到啊,然后反射獲取,在加入緩存中。

在這里插入圖片描述
然后包裝成AutowiredFieldElement對象,add到currElements列表中,最后在把各個bean的所有元素add到elements列表中。

在這里插入圖片描述
最后會通過InjectionMetadata#forElements方法將所有的元素封裝成InjectionMetadata對象返回。
在這里插入圖片描述
最后把注入元素的信息放進(jìn)injectionMetadataCache的map集合中,以便下次就可以從緩存中獲取。

到這里,我們就解析完了帶有@Autowired注解的屬性,接下來進(jìn)入我們的核心方法inject。
在這里插入圖片描述

在這里首先會判斷bean中是否有屬性,如果有,循環(huán)遍歷屬性,調(diào)用inject方法。
在這里插入圖片描述
在這里插入圖片描述

屬性準(zhǔn)備就緒,著重看一下resolveFieldValue方法

在這里插入圖片描述

步入上圖的789行

在這里插入圖片描述
步入doResolveDependency方法,最后會對這個屬性B進(jìn)行解析
在這里插入圖片描述
步入resolveCandidate方法,這不是beanFactory么,真巧,來了老弟。
這不是想去緩存里找么,嘿嘿在這里插入圖片描述

此時b還沒有實(shí)例化,緩存中肯定找不到啊。
在這里插入圖片描述

找不到就去創(chuàng)建吧
在這里插入圖片描述
嗖,創(chuàng)建完了。
在這里插入圖片描述
創(chuàng)建完又要填充屬性了,B的屬性是A,來吧,在走一圈。
在這里插入圖片描述
最后還是要去beanFactory中去找,因?yàn)樵赼填充屬性的時候,a就已經(jīng)實(shí)例化過了,也已經(jīng)put進(jìn)三級緩存暴漏出來了,我們來看看是如何處理的。
在這里插入圖片描述
老樣子,看看248行代碼。
在這里插入圖片描述
哎,臥槽,怎么直接跳到下面來了?bean工廠里沒有?那不對啊,按理來說應(yīng)該可以從三級緩存中找到啊。服了,看看吧。
在這里插入圖片描述

經(jīng)過再一次的debug發(fā)現(xiàn),這個allowCircularReferences屬性默認(rèn)是false,在SpringBoot2.6.x之前都是默認(rèn)為true。

如果需要開啟循環(huán)依賴需要在配置文件配置:

spring:
  main:
    allow-circular-references: true

坑,SpringBoot2.6.x默認(rèn)禁用循環(huán)依賴。
在這里插入圖片描述
在這里插入圖片描述
開啟之后,再來一遍吧。

獲取a —》先去緩存中取,結(jié)果都沒有—》創(chuàng)建,a實(shí)例化—》添加進(jìn)三級緩存beanFactory—》填充屬性b—》獲取b—》先去緩存中取,緩存中也沒有—》創(chuàng)建,b實(shí)例化—》添加進(jìn)三級緩存beanFactory—》填充屬性a—》先去緩存中找,這下肯定有了,不信我們看看

在這里插入圖片描述
你看,有了吧,啥都有了。也能從三級緩存中取到,并且把這個bean放進(jìn)二級緩存earlySingletonObjects中。

然后就會進(jìn)入如下這個if判斷中,getObjectForBeanInstance方法中會做一些判斷如果是當(dāng)前實(shí)例,則會直接返回該實(shí)例。

在這里插入圖片描述
在這里插入圖片描述
最后得到a,退出解析方法

在這里插入圖片描述

在這里插入圖片描述
然后將這個屬性值放進(jìn)緩存中

在這里插入圖片描述
退出該方法
在這里插入圖片描述

然后把得到的A賦值給B的屬性

在這里插入圖片描述
就此,B的屬性A賦值結(jié)束。此時可以看到B是有值的,屬性A也是有值的,可是A的屬性B還沒有賦值呢。
在這里插入圖片描述

此時我們已經(jīng)創(chuàng)建完b,也就是說已經(jīng)調(diào)完了上述的那個lambda函數(shù),緊接著會調(diào)用addSingleton方法,將bean放進(jìn)一級緩存。
在這里插入圖片描述
在這里插入圖片描述
將b放進(jìn)一級緩存同樣也標(biāo)志著b初始化結(jié)束,緊接著,a會將b設(shè)置為自己的屬性。最后也會把a(bǔ)放進(jìn)一級緩存,就此over~
在這里插入圖片描述

在這里插入圖片描述
當(dāng)然,這里可能還存在很多問題,我給的這個demo,并不能完全展示出二級緩存的作用,因?yàn)閍只有一個屬性b,那么填充屬性之后,a就已經(jīng)存在一級緩存中。

可以這樣,A同時依賴于B和C,B和C都依賴于A。這樣就可以看出二級緩存的作用了。
在這里插入圖片描述

其實(shí)對于解決循環(huán)依賴來說,兩個緩存就完全足夠,一個存放未初始化的bean,一個存放已經(jīng)初始化的bean,那么要三級緩存干什么?

具體原因我們可以放在下一篇aop的源碼解析。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


文章名稱:【Spring6源碼?IOC】Bean的初始化-終結(jié)篇-創(chuàng)新互聯(lián)
本文地址:http://weahome.cn/article/dohsch.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部