Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程
參考視頻:https://www.bilibili.com/video/BV1Bq4y1Q7GZ?p=4
通過視頻的學(xué)習(xí)和自身的理解整理出的筆記。
一、前期準(zhǔn)備
1.1 環(huán)境依賴
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.7.RELEASE</version> </dependency> </dependencies>
1.2 實(shí)體類
簡單的User類,在測試過程中創(chuàng)建這個(gè)User類的對象。
public class User { private Integer id; private String name; public User() { System.out.println("創(chuàng)建了"); } }
1.3 applicationContext.xml
在applicationContext.xml配置bean對象。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.zqc.domain.User" id="user"> </bean> </beans>
1.4 測試代碼
通過applicationContext.xml配置應(yīng)用程序的上下文,在容器中創(chuàng)建User對象。
public class SpringDemo { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) context.getBean("user"); } }
二、探究過程
2.1 目標(biāo)
目標(biāo):BeanDefinition是什么?是什么時(shí)候創(chuàng)建的?
2.2 BeanDefinition的創(chuàng)建過程
2.2.1 回顧bean對象的創(chuàng)建
前面在分析Bean創(chuàng)建的過程中,發(fā)現(xiàn)在執(zhí)行完refresh()方法后就完成了bean對象的創(chuàng)建。
在測試代碼中創(chuàng)建context對象:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext構(gòu)造器中調(diào)用了另一個(gè)構(gòu)造器:
該構(gòu)造器中執(zhí)行了refresh()方法
在refresh()方法中創(chuàng)建了非懶加載的單例對象:
所以BeanDefinition可定在這行代碼之前創(chuàng)建的。下面看看在refresh()方法的什么地方創(chuàng)建了BeanDefinition。
2.2.2 AbstractApplicationContext
?? refresh()
方法
首先我們要知道,Bean對象和BeanDefinition對象都是是通過BeanFactory創(chuàng)建。
所以,只有在獲取BeanFactory之后才能獲取到BeanDefinition。
在這一行創(chuàng)建了beanFactory對象。
查看一下beanFactory,找尋與BeanDefinition相關(guān)的屬性: beanDefinitionMap
、beanDefinitionNames
?? beanDefinitionMap
:
key:bean的名稱
value:beanDefinition,描述bean的相關(guān)信息
?? beanDefinitionNames
:beanDefination的名稱
說明當(dāng)ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
執(zhí)行完畢后,BeanDefination就已經(jīng)創(chuàng)建完畢了。
?? obtainFreshBeanFactory()
方法
?? refreshBeanFactory()
方法
通過這行代碼loadBeanDefinitions(beanFactory)
創(chuàng)建了BeanDefinition對象。
2.2.3 AbstractXmlApplicationContext
?? loadBeanDefinitions()
方法,輸入beanFactory
通過讀取xml文件來創(chuàng)建BeanDefinitions
beanFactory就是XmlBeanDefinitionReader里面的registry,所以后面我們看到的registry就是beanFactory對象。
?? loadBeanDefinitions()
方法,輸入beanDefinitionReader
方法重載,上面的形參類型為DefaultListableBeanFactory,這里的形參beanDefinitionReader,就是上面的beanFactory。
?? loadBeanDefinitions()
方法,輸入locations
在loadBeanDefinitions(location)
方法里創(chuàng)建了BeanDefinition。
2.2.4 AbstractBeanDefinitionReader
?? loadBeanDefinitions()
方法,輸入locations
?? loadBeanDefinitions()
方法,輸入locations
和Set<Resource>
?? loadBeanDefinitions()
方法,輸入可變參數(shù)resources
2.2.5 XmlBeanDefinitionReader
?? loadBeanDefinitions()
方法,輸入resources
?? loadBeanDefinitions()
方法
?? doLoadBeanDefinitions()
方法
?? registerBeanDefinitions()
方法
2.2.6 DefaultBeanDefinitionDocumentReader
?? registerBeanDefinitions()
方法
?? doRegisterBeanDefinitions()
方法
?? parseBeanDefinitions()
方法
這里通過解析xml文件遍歷里面的bean標(biāo)簽創(chuàng)建beanDefinition
?? parseDefaultElement()
方法
根據(jù)當(dāng)前的元素標(biāo)簽,選擇不同的解析方式。比如:import、alias、beans
?? processBeanDefinition()
方法
在這里創(chuàng)建beanDefinition對象并存儲(chǔ)在bdHolder中:
2.2.7 BeanDefinitionParserDelegate
?? parseBeanDefinitionElement()
方法
?? parseBeanDefinitionElement()
方法
?? parseBeanDefinitionElement()
方法
創(chuàng)建BeanDefinition對象后,繼續(xù)對xml文件進(jìn)行解析并設(shè)置beanDefinition。
下面繼續(xù)簡單看看createBeanDefinition的過程。
?? createBeanDefinition()
方法
2.2.8 BeanDefinitionReaderUtils
?? createBeanDefinition()
方法
2.2.9 結(jié)論
在容器創(chuàng)建時(shí)會(huì)先去創(chuàng)建一個(gè)beanFactory,然后使用XmlBeanDefinitionReader去讀取xml配置文件,把里面的標(biāo)簽進(jìn)行解析,然后創(chuàng)建BeanDefinition對象來存放bean標(biāo)簽中各個(gè)屬性的值。所以BeanDefinition相當(dāng)于就是保存了bean的定義信息的對象。
通過BeanDefinition里面的信息,就可以使用反射來創(chuàng)建bean對象。
2.3 BeanDefinition的存儲(chǔ)
2.3.1 DefaultBeanDefinitionDocumentReader
我們回到【2.2.6】節(jié)的DefaultBeanDefinitionDocumentReader的processBeanDefinition()方法中。
在這里創(chuàng)建beanDefinition對象并存儲(chǔ)在bdHolder中。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
那么接下來應(yīng)該將bdHolder保存下來。
可以看出來getReaderContext().getRegistry()
這就是一個(gè)beanFactory
對象
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
這段代碼的作用就是將beanDefintion對象注冊到beanFactory中。
下面我們看看registerBeanDefinition()
方法。
2.3.2 BeanDefinitionReaderUtils
下面看看registerBeanDefinition()
方法。
2.3.3 DefaultListableBeanFactory
最終會(huì)運(yùn)行到這里:
2.3.4 結(jié)論
BeanDefinition被創(chuàng)建后會(huì)被存入beanDefinitionMap集合和beanDefinitionNames集合中。
- beanDefinitionMap:key為beanName,value為beanDefinition
- beanDefinitionNames:存儲(chǔ)beanName
到此這篇關(guān)于Spring超詳細(xì)講解創(chuàng)建BeanDefinition流程的文章就介紹到這了,更多相關(guān)Spring BeanDefinition內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot與數(shù)據(jù)庫返回?cái)?shù)據(jù)中文亂碼
大家好,本篇文章主要講的是springboot與數(shù)據(jù)庫返回?cái)?shù)據(jù)中文亂碼,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01使用quartz時(shí),傳入?yún)?shù)到j(luò)ob中的使用記錄
這篇文章主要介紹了使用quartz時(shí),傳入?yún)?shù)到j(luò)ob中的使用記錄,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12springboot使用外置tomcat啟動(dòng)方式
這篇文章主要介紹了springboot使用外置tomcat啟動(dòng)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Spring Cloud負(fù)載均衡及遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解
這篇文章主要介紹了Spring Cloud負(fù)載均衡及遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08SpringMvc實(shí)現(xiàn)簡易計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了SpringMvc實(shí)現(xiàn)簡易計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07MyBatis?核心組件Configuration實(shí)例詳解
Configuration用于描述 MyBatis 的主配置信息,其他組件需要獲取配置信息時(shí),直接通過 Configuration 對象獲取,這篇文章主要介紹了MyBatis核心組件Configuration,需要的朋友可以參考下2023-08-08dubbo將異常轉(zhuǎn)換成RuntimeException的原因分析?ExceptionFilter
這篇文章主要介紹了dubbo將異常轉(zhuǎn)換成RuntimeException的原因分析?ExceptionFilter問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03