仿網(wǎng)站建設(shè)免費(fèi)b2b網(wǎng)站有哪些
概述
面向資源(XML、Properties)、面向注解定義的 Bean 是如何被解析成 BeanDefinition(Bean 的“前身”),并保存至 BeanDefinitionRegistry 注冊(cè)中心里面,實(shí)際也是通過 ConcurrentHashMap 進(jìn)行保存。
Spring 底層 IoC 容器 DefaultListableBeanFactory,實(shí)現(xiàn)了 BeanFactory 和 BeanDefinitionRegistry 接口,這個(gè)時(shí)候它處于“就緒狀態(tài)”,當(dāng)我們顯示或者隱式地調(diào)用 getBean(...) 方法時(shí),會(huì)觸發(fā)加載 Bean 階段,獲取對(duì)應(yīng)的 Bean。在該方法中,如果是單例模式會(huì)先從緩存中獲取,已有則直接返回,沒有則根據(jù) BeanDefinition 開始創(chuàng)建這個(gè) Bean。
主體流程:getBean doGetBean createBean doCreateBean createBeanInstance、instantiate、populateBean、initializeBean、registerDisposableBeanIfNecessary(注冊(cè)銷毀方法)
BeanFactory 體系結(jié)構(gòu)
下來熟悉下Sprig容器BeanFactory的體系

org.springframework.beans.factory.BeanFactory,Spring IoC 容器最基礎(chǔ)的接口,提供依賴查找單個(gè) Bean 的功能
org.springframework.beans.factory.ListableBeanFactory,繼承 BeanFactory 接口,提供依賴查找多個(gè) Bean 的功能
org.springframework.beans.factory.HierarchicalBeanFactory,繼承 BeanFactory 接口,提供獲取父 BeanFactory 的功能,具有層次性
org.springframework.beans.factory.config.ConfigurableBeanFactory,繼承 HierarchicalBeanFactory 接口,提供可操作內(nèi)部相關(guān)組件的功能,具有可配置性
org.springframework.beans.factory.config.AutowireCapableBeanFactory,繼承 BeanFactory 接口,提供可注入的功能,支持依賴注入
org.springframework.beans.factory.config.ConfigurableListableBeanFactory,繼承上面所有接口,綜合所有特性,還提供可提前初始化所有單例 Bean 的功能
org.springframework.beans.factory.support.DefaultListableBeanFactory,Spring 底層 IoC 容器,依賴注入的底層實(shí)現(xiàn)
getBean(String name) 方法,根據(jù)名稱獲取 Bean,當(dāng)然還有許多重載方法
最終都會(huì)調(diào)用
doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 方法
下面是編程方法獲取Bean對(duì)象的方法
// 創(chuàng)建 BeanFactory 容器DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);// XML 配置文件 ClassPath 路徑String location = "classpath:dependency-lookup-context.xml";// 加載配置int beanDefinitionsCount = reader.loadBeanDefinitions(location);System.out.println("Bean 定義加載的數(shù)量:" + beanDefinitionsCount);// 依賴查找System.out.println(beanFactory.getBean("user","1","jack2"));
按照這個(gè)代碼調(diào)試整理成下圖的流程圖
下圖是關(guān)于doGetBean 方法這一層的執(zhí)行邏輯。其他的核心方法后面在更新文章。


總結(jié)
可以看到這個(gè)方法加載 Bean 的過程中,會(huì)先從緩存中獲取單例模式的 Bean;
不管是從緩存中獲取的還是新創(chuàng)建的,都會(huì)進(jìn)行處理,如果是 FactoryBean 類型則調(diào)用其 getObject() 獲取目標(biāo)對(duì)象;
BeanFactory 可能有父容器,如果當(dāng)前容器找不到 BeanDefinition 則會(huì)嘗試讓父容器創(chuàng)建;
創(chuàng)建 Bean 的任務(wù)交由 AbstractAutowireCapableBeanFactory 去完成;
如果獲取到的 Bean 不是我們想要類型,會(huì)通過類型轉(zhuǎn)換機(jī)制轉(zhuǎn)換成目標(biāo)類型
獲取 beanName
從緩存中獲取單例 Bean
FactoryBean 的處理
非單例模式依賴檢查
BeanFactory 層次性加載 Bean 策略
將 beanName 標(biāo)記為已創(chuàng)建
獲取 RootBeanDefinition
依賴 Bean 的處理
不同作用域的 Bean 的創(chuàng)建
單例模式
多例模式
其他模式

過程如下:
從當(dāng)前容器獲取該模式的 Scope 對(duì)象 scope,不存在則拋出異常
從 scope 中獲取 beanName 對(duì)應(yīng)的對(duì)象(看你的具體實(shí)現(xiàn)),不存在則執(zhí)行原型模式的四個(gè)步驟進(jìn)行創(chuàng)建
想要自定義一個(gè)作用域,可以實(shí)現(xiàn) org.springframework.beans.factory.config.Scope 接口,并往 Spring 應(yīng)用上下文注冊(cè)即可 這個(gè)也是一個(gè)拓展接口
類型轉(zhuǎn)換

如果入?yún)?requiredType 不為空,并且 Bean 不是該類型,則需要進(jìn)行類型轉(zhuǎn)換,過程如下:
通過類型轉(zhuǎn)換機(jī)制,將 Bean 轉(zhuǎn)換成 requiredType 類型,對(duì) Spring 的類型轉(zhuǎn)換機(jī)制參考 org.springframework.core.convert.support.DefaultConversionService
我們也可以基于此做拓展的。
轉(zhuǎn)換后的 Bean 為空則拋出異常
返回類型轉(zhuǎn)換后的 Bean 對(duì)象
歸納拓展
對(duì) BeanFactory 接口的體系結(jié)構(gòu)進(jìn)行了分析,得知 DefaultListableBeanFactory 是 BeanFactory 的最底層實(shí)現(xiàn),也就是 Spring 的底層 IoC 容器。接著分析了 AbstractBeanFactory 的 getBean(...) 方法,當(dāng)我們顯示或者隱式地調(diào)用這個(gè)方法時(shí),會(huì)觸發(fā) Bean 的加載。上面對(duì) Bean 的加載過程進(jìn)行了分析。
不同作用域的 Bean 的創(chuàng)建,底層都會(huì)調(diào)用 AbstractAutowireCapableBeanFactory 的 createBean(...)方法進(jìn)行創(chuàng)建,創(chuàng)建 Bean 的過程涉及到 Bean 生命周期的大部分階段,例如實(shí)例化階段、屬性賦值階段、Aware 接口回調(diào)階段、初始化階段都是在這個(gè)方法中完成的。