背誦并默寫:
SpringIOC有兩個核心思想就是IOC控制反轉和DI依賴注入,IOC 控制反轉的基本思想是,將原來的物件控制從使用者,有了spring之后可以把整個物件交給spring來幫我們進行管理,DI 依賴注入,就是把對應的屬性的值注入到具體的物件中,spring提供<bean/>標簽和@Autowired和@Resource注解等方式注入,注入方式本質上是AbstractAutowireCapableBeanFactory的populateBean() 方法先從beanDefinition 中取得設定的property值,例如autowireByName方法會根據bean的名字注入;autowireByType方法根據bean的型別注入,完成屬性值的注入(涉及bean初始化程序),物件會存盤在map結構中,在spring使用Map結構的singletonObjects存放完整的bean物件(涉及三級快取和回圈依賴),整個bean的生命周期,從創建到使用到銷毀的程序全部都是由容器來管理(涉及bean的生命周期),
擴展,如果面試官不叫停可以繼續說(*bean生命周期)
IOC核心流程重點關注有 bean生命周期,主要分為初始化和銷毀
1、在正式進入容器的重繪前,會進行一些前置操作,主要為了(1)確認要使用的容器,通常使用的是:XmlWebApplicationContext,如果是用 Spring Boot,一般是AnnotationConfigApplicationContext,但其實都差別不大,最終都會繼承AbstractApplicationContext,核心邏輯也都是在 AbstractApplicationContext 中實作,(2)還有一個目的是提供一個給開發者初始化 ApplicationContext 的機會,
————————————初始化程序————————————
2、初始化 BeanFactory默認為 DefaultListableBeanFactory 、它會加載 Bean 定義,向bean工廠中設定一些引數;例如:BeanNameAware.setBeanName() 在創建此bean的bean工廠中設定bean的名稱和BeanClassLoaderAware.setBeanClassLoader();setBeanFactory() : 回呼提供了自己的bean實體工廠等,然后將 beanName、BeanDefinition 放到 BeanFactory 的快取中,用于后續創建 Bean 實體時使用,
3、觸發 BeanFactoryPostProcessor;BeanFactoryPostProcessor 介面是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IOC 容器允許 BeanFactoryPostProcessor 在容器實體化任何 bean 之前讀取 bean 的定義,并可以修改它,BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優先級;另外,Mybatis 中的 MapperScannerConfigurer 是一個典型的 BeanDefinitionRegistryPostProcessor 的擴展使用;
我們也可以implements BeanFactoryPostProcessor 再使用@Component注冊到Spring,實作自己的 postProcessBeanFactory() 邏輯,
4、注冊所有的 BeanPostProcessor,將所有實作了 BeanPostProcessor 介面的類加載到 BeanFactory 中,BeanPostProcessor 介面是 Spring 初始化 bean 時對外暴露的擴展點,方便后續對bean物件完成具體的擴展功能;
我們也可以implements BeanPostProcessor再使用@Component注冊到Spring,實作自己的postProcessBeforeInitialization()和postProcessAfterInitialization()
5、實體化所有剩余的非懶加載單例 bean,將所有BeanDefinition物件實體化成具體的bean物件,(1)首先會遍歷所有被加載到快取中的 beanName,觸發所有剩余的非懶加載單例 bean 的實體化,(2)同時通過 beanName 嘗試從快取中獲取,如果存在則跳過實體化程序;否則,進行 bean 的實體化,(3)根據 BeanDefinition,使用建構式創建 bean 實體 或者 進行 bean 實體屬性填充,最后執行 bean 實體的初始化,
6、生成完整的bean物件,通過getBean方法可以直接獲取,
————————————銷毀————————————
7、在BeanFactory 關閉的時候,Bean的生命周期會呼叫如下方法:(1)DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在銷毀之前將此BeanPostProcessor 應用于給定的bean實體,能夠呼叫自定義回呼,像是DisposableBean 的銷毀和自定義銷毀方法,這個回呼僅僅適用于工廠中的單例bean(包括內部bean)(2)實作了自定義的 destory() 方法
擴展,還不叫停繼續說(*重點關注的類)
這里面主要關注物件有,bean 是一個由Spring IOC容器實體化,組裝和管理的物件;
BeanDefinition 是bean的定義,用來存盤bean的所有屬性方法定義,ApplicationContext 是BeanFactory 的子介面,在 BeanFactory 的基礎上構建,是相對比較高級的IOC容器實作,包含 BeanFactory 的所有功能,還提供了其他高級的特性,比如:事件發布、國際化資訊支持、統一資源加載策略等,正常情況下,我們都是使用的 ApplicationContext,還有BeanFactory是基礎型別 IOC 容器,提供完整的 IOC 服務支持,FactoryBean 是一種特殊的 bean,它是個工廠 bean,可以自己創建 bean 實體,如果一個類實作了 FactoryBean 介面,則該類可以自己定義創建實體物件的方法,只需要實作它的 getObject() 方法即可,
結尾
面試官,這是我對Spring IOC的整體理解,包含了一些詳細的處理程序,您看一下有什么問題,可以指點我一下(心里想看老子不吊打你)
———————————等等面試官還沒叫停?—————————————
擴展,還不叫停石錘面試官睡著了,那我們展開繼續說(*bean的初始化程序中回圈依賴和解決)
剛才說,物件會存盤在map結構中,在Spring使用Map結構的singletonObjects存放完整的bean物件,
但是創建這個singletonObjects的程序,Spring在啟動的時候會先初始化掃描我們配置的包下面的所有的類,進行決議和注冊到beanDecfinition中,然后在根據beanDecfinition的資訊對類進行實體化,填充屬性等操作變成一個bean,放到我們spring的容器中,在變成bean的程序中,會遇到物件與物件之間的依賴,比如A類中有一個屬性B類,那么spring在創建A物件的時候發現了需要一個B物件,這個時候spring就會暫時停止對A的創建,會先去創建B物件,等B物件創建完之后,將B物件注入到A物件中,再接著創建A物件剩下的作業,
這個程序我們分為兩部分,首先1、通過反射創建出一個物件,然后2、往物件中的屬性賦值,
我們很好理解第一步,我們得到物件的全路徑名,就可以利用反射創建A物件,得到A物件中的屬性,這時我們會把這個A物件標為正在創建中,并且放到快取中,
在第二步時就要給屬性賦值,這時如果屬性中要注入B類的話,spring會首先到容器中找有沒有B類的物件,有的話就直接注入在屬性上,沒有的話就就要重新創建一個B物件,在創建B物件的程序中,必然也會有兩步:1、通過反射創建出一個物件,2、往物件中的屬性賦值,第一步和之前一樣我們不說,第二步的就有可能會注入我們之前正在創建的A物件,同樣也到容器中查找,沒有找到,因為我們還沒有創建完成,這個時候我們會發現他正在創建中,然后我們可以從快取中取出創建好但沒有注入屬性值的A物件,然后就去拿著這個A物件給當前B物件注入值,這樣就完成了當前B物件的注入,B物件創建完成之后,就會把B物件注入到A中,A物件就創建完成了,

end
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/299521.html
標籤:java
上一篇:【Java 基礎語法】萬字決議 Java 的包和繼承
下一篇:CGBTN2108復習匯總
