91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

品Spring:動手才知道,三十步才能完成一個bean實例的創建

發布時間:2020-05-29 13:41:48 來源:網絡 閱讀:759 作者:wx5d30212829a35 欄目:編程語言

在容器啟動快完成時,會把所有的單例bean進行實例化,也可以叫做預先實例化。

這樣做的好處之一是,可以及早地發現問題,及早的拋出異常,及早地解決掉。

本文就來看下整個的實例化過程。其實還是比較繁瑣的。

一、從容器中找出所有的bean定義名稱

因為不知道誰是單例bean,所以只能先全部找出來。如下圖01:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


二、循環遍歷所有的bean名稱,檢查是否符合條件

首先要合并bean定義,因為bean定義可以有父子關系,類似繼承。

然后這個合并后的bean定義必須是,非抽象的,單例的,非延遲初始化的。

那么它就滿足條件,如下圖02:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


三、判斷是否為FactoryBean<?>類型

如果不是的話,說明該beanName對應一個普通的bean,可以直接實例化。

如果是的話,說明該beanName對應的是一個工廠,這個工廠本身是單例的。

但是它里面生產的bean不一定是單例的。即使是的話,還要判斷是否要積極的去初始化工廠里的bean。

具體的判斷如下圖03:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


:提到FactoryBean<?>類型,是否想起&符號的作用呢?

四、開始進入眾所熟知的getBean(String name)方法

在上一圖中可以看到Spring對bean的實例化時竟然是調用的getBean(..)方法。

這樣共用一套代碼,簡單省事。不僅如此,當獲取一個bean的依賴時,也可以用該方法。

這樣getBean(..)就是一個綜合方法,沒有bean實例就生成,有的話就直接返回。

如下圖04:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


五、對手工直接注冊的單例對象進行檢測

bean實例除了可以用bean定義生成外,還可以由開發人員直接注冊一個bean實例。

這樣在使用bean定義生成實例前,先使用beanName去手動注冊的bean實例集合中找一下。

如下圖05:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


如果找到了,就不用生成了,否則就會根據bean定義生成bean實例。

六、對FactoryBean<?>類型的檢測

這和上面提到的是一個類型,它是一個工廠,可以認為是包裹在了實際bean實例的外面。

這樣可以有一些特殊的作用,不好之處就是每次都要檢測下,然后從它內部拿出實際的bean實例。

具體檢測過程不再展開,如下圖06:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


七、對類型進行轉換,如果有必要的話

上面我們僅僅是用beanName去手動注冊的實例集合中尋找,萬一這個手動注冊的實例類型和bean定義要求的不兼容呢?

因此要進行類型檢測與轉換,實在不行就拋異常,如下圖07:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


如果成功的話,就表明手動注冊的bean定義實例滿足要求,將它返回即可。

:如果在第五步沒有找到beanName對應的手動注冊的bean實例,那開始根據bean定義來生成bean實例。繼續往下看。

八、準備好顯式指定的依賴,如@DependsOn指定的

先獲取合并后的bean定義,然后從中讀出顯式指定的依賴,并逐個處理。

使用registerDependentBean(..)將依賴關系寫入容器,由容器維護。

并同樣使用getBean(..)方法實例化這些依賴,一模一樣的套路。

其實就是遞歸,如下圖08:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


:接下來使用createBean(..)方法正式開始創建bean

九、解析出bean的Class<?>

因為在注冊bean定義時并不一定加載類,可能只是一個字符串的類名稱。

所以要根據類名稱去加載類,并得到類的Class<?>。如下圖09:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


十、調用bean后處理器的postProcessBeforeInstantiation方法

此時還處在實例化之前,讓用戶有機會來提供一個bean實例或代理。

這樣Spring就不再進行后續的實例化步驟,直接返回這個用戶提供的。

如果用戶沒有提供的話,Spring繼續后續的處理。如下圖1011:

品Spring:動手才知道,三十步才能完成一個bean實例的創建



品Spring:動手才知道,三十步才能完成一個bean實例的創建


十一、調用InstanceSupplier生成bean實例,如果有的話

在注冊bean定義時,可以設置一個Supplier<?>類型的函數式接口。

其實就是用戶可以提供一段創建bean實例的代碼,這樣Spring就使用它來創建bean實例。

然后將這個實例返回即可,如下圖12:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


十二、通過FactoryMethod來生成bean實例,如果FactoryMethodName不為null的話

如下圖13:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


FactoryMethod就是工廠方法,說明bean的實例是通過調用這個工廠方法返回的,而不是通過反射調用構造函數返回的。

工廠方法有兩種,靜態的和實例的。如果是實例的,那還要有一個FactoryBeanName來指定一個bean名稱,根據它可以從容器中獲取一個對象,用作工廠。

如果是靜態的,那就不需要實例了,直接把bean定義中的類型作為工廠類即可。如下圖14:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


然后根據工廠方法的名稱,從bean定義中解析出對應的Method對象。然后再解析出構造方法參數用作工廠方法的參數。

最終通過反射調用這個工廠方法,獲取返回值,就是bean實例了,如下圖15:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


這個bean實例會用一個BeanWrapper接口進行包裝,這個接口提供一些基礎的JavaBean功能,如數據的類型轉換然后再進行屬性綁定等。

十三、調用bean后處理器的determineCandidateConstructors方法來確定候選構造方法

如下圖16:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


這里涉及到從多個候選構造方法中選出一個最合適的,是一個比較復雜的過程。

最后也是通過反射調用構造方法,獲取到bean的實例。如下圖17:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


然后也用BeanWrapper接口進行包裝。

十四、使用更適合的構造方法來實例化,如果有的話

如果上一步沒有執行的話,則使用bean定義中更適合的構造方法,如下圖18:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


十五、使用默認無參的構造方法來實例化

如果上一步沒有執行的話,則使用默認無參構造方法,如下圖19:


品Spring:動手才知道,三十步才能完成一個bean實例的創建



:至此bean實例已經創建好了。

十六、應用bean后處理器的postProcessMergedBeanDefinition方法

上兩篇文章詳細介紹了bean后處理器,主要是用來實現注解的功能的。

如下圖2021:


品Spring:動手才知道,三十步才能完成一個bean實例的創建



品Spring:動手才知道,三十步才能完成一個bean實例的創建


十七、此時就可以暴露早期的bean引用了,如果需要的話

如允許循環引用的話,就需要這個操作,如下圖22:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


十八、應用bean后處理器的postProcessAfterInstantiation方法

如下圖23:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


且該方法如果返回false,該bean實例后續的bean后處理器操作將不再執行。

十九、根據設置的自動裝配類型處理自動裝配問題

如下圖24:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


如果配置的是按名稱自動裝配,則會把所有setter方法中參數類型是非基本類型的都找出來。

然后按照屬性名稱從容器中找出同名的bean,作為屬性值保存起來以備后用。如下圖25:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


如果配置的是按類型自動裝配,則會把所有setter方法中參數類型是非基本類型的都找出來。

然后按照屬性類型從容器中解析出對應的bean,作為屬性值保存起來以備后用。如下圖26:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


注:以上的setter方法上不需要標任何注解,因為顯式設置了自動裝配類型。

而默認情況其實是沒有設置的,即AUTOWIRE_NO,所以我們要標上@Autowired注解。

二十、應用bean后處理器的postProcessProperties方法

在這一步其實是完成了依賴的注入,如下圖27:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


二十一、其余屬性值到bean屬性的綁定

這一步是由BeanWrapper這個接口完成的,如下圖28:


品Spring:動手才知道,三十步才能完成一個bean實例的創建


注:至此bean的所有依賴裝配和屬性設置都已完畢。

二十二、應用bean后處理器的postProcessBeforeInitialization方法

這一步就開始執行初始化方法了。如下圖2930:

品Spring:動手才知道,三十步才能完成一個bean實例的創建



品Spring:動手才知道,三十步才能完成一個bean實例的創建


二十三、執行bean的初始化方法afterPropertiesSet()

如果bean實現了InitializingBean接口,此刻會調用它唯一的方法。

如下圖31:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


二十四、執行bean定義中指定的初始化方法initMethod

如果bean定義是使用@Bean注冊的,可以通過設置注解屬性指定初始化方法。

如下圖32:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


注:三種可以指定初始化的方法:

1)@PostConstruct注解,

2)InitializingBean接口,

3)@Bean注解

這里有兩個問題需要記住:

1)如果兩種或三種方式都指向了同一個方法,這個方法也只會被執行一次。

2)三種方式指定的初始化方法的執行順序就按剛剛列出的1、2、3這個順序。

二十五、應用bean后處理器的postProcessAfterInitialization方法

如下圖33、34:

品Spring:動手才知道,三十步才能完成一個bean實例的創建



品Spring:動手才知道,三十步才能完成一個bean實例的創建


注:至此bean的初始化工作已經完成。

二十六、注冊bean銷毀時要執行的代碼,如果需要的話

除了使用了之前說過的三種方式指定過銷毀發方法之外,如果bean實現了AutoCloseable接口也算。

如果使用@Bean注冊且沒有指定銷毀方法,那么默認把close和shutdown方法作為銷毀方法。

這些情況都是需要注冊的,如下圖35:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


注:至此bean實例本身已經準好了。

二十七、緩存單例的bean

如果這個bean是單例的,而且是新創建的,會把它緩存到容器里,以備后用。

如下圖36:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


二十八、進行Scope處理

如果一個bean指定了Scope,即它的生命周期既非單例也非原型而是屬于某一個范圍。

Spring暫時支持的范圍如下圖37:

品Spring:動手才知道,三十步才能完成一個bean實例的創建


實現原理其實很簡單,比如Session范圍,那就先從Session中獲取,沒有的話生成一個放入Session中即可。

二十九、對FactoryBean<?>類型的檢測與處理

剛剛創建的這個bean可能是FactoryBean<?>類型,即一個工廠。而我們想要的可能是工廠里生成的bean。

簡單來說,那就從工廠中把bean拿出來即可。

三十、類型的檢測與轉換

最終得到的bean實例可能與期望的類型不兼容,此時就要進行類型轉換。

轉換成功的話就返回,失敗的話就拋出類型不匹配異常。

至此一個bean的創建工作已經全部結束。

整體流程步驟就是這樣,只是忽略了一些和流程無關的細節實現。

點擊獲取?附送學習進階架構資料、PDF書籍文檔、面試資料

品Spring:動手才知道,三十步才能完成一個bean實例的創建

品Spring:動手才知道,三十步才能完成一個bean實例的創建


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

师宗县| 鹤峰县| 洪泽县| 绥滨县| 石门县| 长治市| 大埔区| 阜新| 简阳市| 吴忠市| 凌云县| 长汀县| 绥化市| 岐山县| 上饶县| 阿合奇县| 崇左市| 迁西县| 河南省| 西乡县| 铅山县| 桐梓县| 昌黎县| 新巴尔虎右旗| 城步| 托克逊县| 泗阳县| 彭泽县| 吴旗县| 阿图什市| 和田市| 南木林县| 富平县| 宣汉县| 宜城市| 罗田县| 海盐县| 绿春县| 东兰县| 宁城县| 台东县|