目錄:
-
spring4中IOC容器初始化
(1) 設(shè)置資源的加載setConfigLocations
(2) AbstractApplicationContext類(lèi)之refresh方法加載bean
(3)AbstractApplicationContext類(lèi)之obtainFreshBeanFactory方法委派子類(lèi)加載bean
(4)AbstractRefreshableApplicationContext類(lèi)之refreshBeanFactory方法
(5)AbstractXmlApplicationContext類(lèi)之loadBeanDefinitions方法讀取XML配置文件bean
(6)AbstractBeanDefinitionReader類(lèi)之loadBeanDefinitions方法讀取XML配置的Bean,將其轉(zhuǎn)化為Resource類(lèi)
(7)XmlBeanDefinitionReader類(lèi)之loadBeanDefinitions方法加載Resource類(lèi)(bean資源)
(8)DocumentLoader類(lèi)之loadDocument將Resource對(duì)象轉(zhuǎn)換為Document對(duì)象
(9)XmlBeanDefinitionReader類(lèi)之registerBeanDefinitions方法解析Document對(duì)象
(10) DefaultBeanDefinitionDocumentReader類(lèi)之registerBeanDefinitions方法解析Document中的Bean定義
(11)DefaultBeanDefinitionDocumentReader類(lèi)之解析<import>痴奏,<alias>,<bean>,<beans>元素
(12) BeanDefinitionReaderUtils類(lèi)之registerBeanDefinition將BeanDefinition在IOC容器中注冊(cè)
(13) DefaultListableBeanFactory類(lèi)之registerBeanDefinition方法真正注冊(cè)BeanDefinition
(14)spring4中IOC容器初始化步驟總結(jié)
spring4中IOC容器初始化
1. 設(shè)置資源的加載setConfigLocations
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
ClassPathXmlApplicationContext構(gòu)造方法:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 設(shè)置ApplicationContext為null
super(parent);
// 將配置文件的路徑存放到字符串?dāng)?shù)組中
setConfigLocations(configLocations);
if (refresh) {
// spring加載bean的核心方法哭懈,作用就是刷新spring的上下文
refresh();
}
}
public void setConfigLocations(String... locations) {
// 如果locations數(shù)組不為null
if (locations != null) {
// 判斷數(shù)組路徑不為null
Assert.noNullElements(locations, "Config locations must not be null");
// configLocations開(kāi)辟空間
this.configLocations = new String[locations.length];
// 遍歷俘种,然后為configLocations數(shù)組賦值
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
說(shuō)明:
傳入多個(gè)配置文件路徑可以設(shè)置分隔符為 ,; \t\n
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
public void setConfigLocation(String location) {
setConfigLocations(StringUtils.tokenizeToStringArray(location, CONFIG_LOCATION_DELIMITERS));
}
2. AbstractApplicationContext類(lèi)之refresh方法加載bean
spring IOC創(chuàng)建容器之前嘀韧,會(huì)先判斷BeanFactory容器是否已經(jīng)存在:① 如果容器已經(jīng)存在篇亭,那么銷(xiāo)毀bean。關(guān)閉beanFactory锄贷,將序列號(hào)設(shè)置為null暗赶,將beanFactory設(shè)置為null鄙币。② 如果容器不存在肃叶,那么創(chuàng)建容器DefaultListableBeanFactory蹂随,加載所有的bean定義和創(chuàng)建bean的單例。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//調(diào)用容器準(zhǔn)備刷新的方法因惭,獲取容器的當(dāng)時(shí)時(shí)間岳锁,同時(shí)給容器設(shè)置同步標(biāo)識(shí)
prepareRefresh();
//告訴子類(lèi)啟動(dòng)refreshBeanFactory()方法,Bean定義資源文件的載入從
//子類(lèi)的refreshBeanFactory()方法啟動(dòng)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//為BeanFactory配置容器特性蹦魔,例如類(lèi)加載器激率、事件處理器等
prepareBeanFactory(beanFactory);
try {
//為容器的某些子類(lèi)指定特殊的BeanPost事件處理器
postProcessBeanFactory(beanFactory);
//調(diào)用所有注冊(cè)的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//為BeanFactory注冊(cè)BeanPost事件處理器.
//BeanPostProcessor是Bean后置處理器,用于監(jiān)聽(tīng)容器觸發(fā)的事件
registerBeanPostProcessors(beanFactory);
//初始化信息源勿决,和國(guó)際化相關(guān).
initMessageSource();
//初始化容器事件傳播器.
initApplicationEventMulticaster();
//調(diào)用子類(lèi)的某些特殊Bean初始化方法
onRefresh();
//為事件傳播器注冊(cè)事件監(jiān)聽(tīng)器.
registerListeners();
//初始化所有剩余的單態(tài)Bean.
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件處理器乒躺,并發(fā)布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
//銷(xiāo)毀以創(chuàng)建的單態(tài)Bean
destroyBeans();
//取消refresh操作,重置容器的同步標(biāo)識(shí).
cancelRefresh(ex);
throw ex;
}
}
}
3. AbstractApplicationContext類(lèi)之obtainFreshBeanFactory方法委派子類(lèi)加載bean
AbstractApplicationContext類(lèi)obtainFreshBeanFactory方法委派給子類(lèi)AbstractRefreshableApplicationContext中的refreshBeanFactory方法來(lái)載入bean資源文件低缩,刷新內(nèi)部bean工廠嘉冒。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新Bean工廠
refreshBeanFactory();
// 獲取bean工廠
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
// 返回bean工廠
return beanFactory;
}
4. AbstractRefreshableApplicationContext類(lèi)之refreshBeanFactory方法
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果beanFactory不為null
if (hasBeanFactory()) {
// 1. 獲取beanFactory;如果為null咆繁,就拋出IllegalStateException.
// 2. 銷(xiāo)毀bean
destroyBeans();
// 關(guān)閉beanFactory讳推,將序列號(hào)設(shè)置為null,將beanFactory設(shè)置為null
closeBeanFactory();
}
try {
// 創(chuàng)建父級(jí)別的DefaultListableBeanFactory(真正的IOC容器)
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 將beanFactory設(shè)置序列化id
beanFactory.setSerializationId(getId());
// 自定義上下文使用的工廠beanFactory(主要是定制化自動(dòng)裝配等配置)
customizeBeanFactory(beanFactory);
// 使用XmlBeanDefinitionReader加載XML配置文件
loadBeanDefinitions(beanFactory);
// 初始化beanFactory
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
流程說(shuō)明:
① 首先判斷BeanFactory工廠是否已經(jīng)創(chuàng)建玩般,如果已經(jīng)創(chuàng)建那么就銷(xiāo)毀關(guān)閉BeanFactory工廠银觅。(可以發(fā)現(xiàn)spring每次都是建立新的IOC容器)
② 創(chuàng)建DefaultListableBeanFactory真正的ioc容器。
③ 調(diào)用loadBeanDefinitions方法加載Bean坏为,實(shí)際使用XmlBeanDefinitionReader類(lèi)操作的究驴。
5. AbstractXmlApplicationContext類(lèi)之loadBeanDefinitions方法讀取XML配置文件bean
// 使用XmlBeanDefinitionReader加載Bean
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 通過(guò)BeanFactory來(lái)創(chuàng)建一個(gè)新的XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 設(shè)置資源加載的環(huán)境
beanDefinitionReader.setEnvironment(this.getEnvironment());
// 設(shè)置資源加載器,而容器本身就是一個(gè)資源加載器
beanDefinitionReader.setResourceLoader(this);
// 設(shè)置schema匀伏、dtd解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 當(dāng)Bean讀取器讀取Bean定義的Xml資源文件時(shí)洒忧,啟用Xml的校驗(yàn)機(jī)制
initBeanDefinitionReader(beanDefinitionReader);
// Bean加載器真正加載Bean的方法
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 獲取配置文件的路徑存放到字符串?dāng)?shù)組
Resource[] configResources = getConfigResources();
// 如果該資源對(duì)象數(shù)組不為null
if (configResources != null) {
// 使用AbstractBeanDefinitionReader讀取定位的Bean定義資源
reader.loadBeanDefinitions(configResources);
}
// 獲取ClassPathXmlApplicationContext類(lèi)中setConfigLocations方法設(shè)置的資源路徑的數(shù)組
String[] configLocations = getConfigLocations();
// 如果資源路徑數(shù)組不為null
if (configLocations != null) {
// 使用AbstractBeanDefinitionReader讀取定位的Bean定義資源
reader.loadBeanDefinitions(configLocations);
}
}
@Override
protected Resource[] getConfigResources() {
return this.configResources;
}
說(shuō)明:
XmlBeanDefinitionReader實(shí)例化并且初始化,設(shè)置資源加載環(huán)境帘撰、資源加載器跑慕、設(shè)置schema、dtd解析器摧找、啟動(dòng)Xml校驗(yàn)機(jī)制核行、設(shè)置之前配置configLocation配置文件的路徑。委派它的父類(lèi)AbstractBeanDefinitionReader類(lèi)實(shí)現(xiàn)loadBeanDefinitions讀取XML配置文件bean
6. AbstractBeanDefinitionReader類(lèi)之loadBeanDefinitions方法讀取XML配置的Bean蹬耘,將其轉(zhuǎn)化為Resource類(lèi)
// 通過(guò)資源路徑數(shù)組來(lái)加載Bean
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
// 計(jì)數(shù)值(加載次數(shù))
int counter = 0;
// 遍歷資源路徑數(shù)組
for (String location : locations) {
counter += loadBeanDefinitions(location);
}
return counter;
}
// 通過(guò)單個(gè)資源路徑來(lái)加載Bean
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
// 從指定的資源位置加載bean
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
// 獲取資源加載器(根據(jù)給定的資源文件地址返回對(duì)應(yīng)的Resource)
ResourceLoader resourceLoader = getResourceLoader();
// 如果資源加載器為空就拋出異常
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// 將資源文件路徑解析為Spring容器支持的資源對(duì)象Resource數(shù)組
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// 最終還是委派給XmlBeanDefinitionReader來(lái)加載資源Resource
// 返回加載次數(shù)
int loadCount = loadBeanDefinitions(resources);
// 如果實(shí)際資源不為空芝雪,將資源添加進(jìn)去
// 而傳入的集合為null
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// 通過(guò)URL方式加載資源
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean defintions from location [" + location + "]");
}
return loadCount;
}
}
說(shuō)明:
AbstractBeanDefinitionReader類(lèi)只是通過(guò)我們之前設(shè)置的configLocation的路徑查找對(duì)應(yīng)的資源(路徑有classpath*、url等)综苔,進(jìn)行加載惩系,加載完所有資源位岔,封裝為Resource類(lèi)。加載完畢后由子類(lèi)XmlBeanDefinitionReader類(lèi)的loadBeanDefinitions方法來(lái)讀取Resource類(lèi)(bean定義的資源)堡牡。
7. XmlBeanDefinitionReader類(lèi)之loadBeanDefinitions方法加載Resource類(lèi)(bean資源)
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 將資源Resource包裝成特殊編碼的EncodedResource
return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader讀取Bean定義的資源
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 將資源文件解析為字節(jié)輸入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 定義輸入源抒抬,設(shè)置了資源文件xml的字節(jié)輸入流
InputSource inputSource = new InputSource(inputStream);
// 如果編碼不為空,那么在定義的輸入源中設(shè)置編碼
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 真正讀取過(guò)程
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 使用配置的文檔來(lái)加載程序和加載指定文檔
// 將Resource資源(XML文件)轉(zhuǎn)換為Document獨(dú)享晤柄,而解析加載過(guò)程使用了documentLoader實(shí)現(xiàn)
Document doc = doLoadDocument(inputSource, resource);
// 對(duì)Bean定義解析
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
// 使用配置的文檔來(lái)加載程序和加載指定文檔
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
說(shuō)明:
XmlBeanDefinitionReader類(lèi)之loadBeanDefinitions方法加載Resource類(lèi):①委派DocumentLoader類(lèi)的loadDocument方法將Resource類(lèi)轉(zhuǎn)成Document類(lèi)擦剑。②使用XmlBeanDefinitionReader類(lèi)的registerBeanDefinitions方法解析Document中的bean定義。
8. DocumentLoader類(lèi)之loadDocument將Resource對(duì)象轉(zhuǎn)換為Document對(duì)象
使用JAXP來(lái)解析XML文檔為Document對(duì)象芥颈,JAXP就是封裝的DOM接口惠勒,使用DOM技術(shù)來(lái)解析文檔模型(譬如元素節(jié)點(diǎn),文檔節(jié)點(diǎn))
// 使用JAXP來(lái)解析XML文檔為Document對(duì)象
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
// 創(chuàng)建文檔解析工廠
DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
if (logger.isDebugEnabled()) {
logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
}
// 創(chuàng)建文檔解析器
DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
// 解析Bean定義的資源
return builder.parse(inputSource);
}
// 創(chuàng)建DocumentBuilderFactory工廠實(shí)例
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)
throws ParserConfigurationException {
// 創(chuàng)建文檔解析工廠
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(namespaceAware);
// 設(shè)置文檔校驗(yàn)?zāi)P?validationMode不為0
if (validationMode != XmlValidationModeDetector.VALIDATION_NONE) {
// 設(shè)置校驗(yàn)為true
factory.setValidating(true);
// 如果文檔校驗(yàn)?zāi)P蜑閄SD校驗(yàn)
if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
// Enforce namespace aware for XSD...
factory.setNamespaceAware(true);
try {
// SCHEMA_LANGUAGE_ATTRIBUTE 使用JAXP屬性配置驗(yàn)證的語(yǔ)言
// XSD_SCHEMA_LANGUAGE XSD模式語(yǔ)言的JAXP屬性值
factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
}
catch (IllegalArgumentException ex) {
ParserConfigurationException pcex = new ParserConfigurationException(
"Unable to validate using XSD: Your JAXP provider [" + factory +
"] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? " +
"Upgrade to Apache Xerces (or Java 1.5) for full XSD support.");
pcex.initCause(ex);
throw pcex;
}
}
}
return factory;
}
// 使用JAXP創(chuàng)建一個(gè)文檔解析器DocumentBuilder爬坑,用于解析XML文檔
protected DocumentBuilder createDocumentBuilder(
DocumentBuilderFactory factory, EntityResolver entityResolver, ErrorHandler errorHandler)
throws ParserConfigurationException {
// 通過(guò)工廠創(chuàng)建文檔解析器
DocumentBuilder docBuilder = factory.newDocumentBuilder();
if (entityResolver != null) {
docBuilder.setEntityResolver(entityResolver);
}
if (errorHandler != null) {
docBuilder.setErrorHandler(errorHandler);
}
return docBuilder;
}
上面步驟將bean資源封裝成了Resource纠屋、Document對(duì)象,下面將Document對(duì)象解析并且加載到spring IOC容器中盾计。
9. XmlBeanDefinitionReader類(lèi)之registerBeanDefinitions方法解析Document對(duì)象
// 解析DOM文檔Document中包含的Bean定義
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 創(chuàng)建BeanDefinitionDocumentReader用來(lái)解析Document
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 獲取容器中注冊(cè)的Bean的數(shù)量
int countBefore = getRegistry().getBeanDefinitionCount();
// 此處委派給了DefaultBeanDefinitionDocumentReader來(lái)實(shí)現(xiàn)Bean定義的解析
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 返回解析的Bean數(shù)量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
// 創(chuàng)建一個(gè)BeanDefinitionDocumentReader用來(lái)解析Document
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
// 使用構(gòu)造器通過(guò)反射來(lái)創(chuàng)建對(duì)象售担,強(qiáng)制類(lèi)型轉(zhuǎn)換為BeanDefinitionDocumentReader類(lèi)型
return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
說(shuō)明:
真正解析Document對(duì)象,委派給DefaultBeanDefinitionDocumentReader類(lèi)的registerBeanDefinitions方法實(shí)現(xiàn)闯估。
10. DefaultBeanDefinitionDocumentReader類(lèi)之registerBeanDefinitions方法解析Document中的Bean定義
// 根據(jù)spring-beans的XSD文件來(lái)解析bean的定義
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
// 初始化XML描述符
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 獲取document的根元素
Element root = doc.getDocumentElement();
// 在給定的根元素root的內(nèi)部注冊(cè)每個(gè)Bean的定義
doRegisterBeanDefinitions(root);
}
// 在給定的根元素的內(nèi)部注冊(cè)每個(gè)Bean的定義
protected void doRegisterBeanDefinitions(Element root) {
// 使用BeanDefinitionParserDelegate用于完成真正的解析過(guò)程
BeanDefinitionParserDelegate parent = this.delegate;
// 對(duì)BeanDefinitionParserDelegate進(jìn)行初始化
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
// 在解析Bean定義之前灼舍,擴(kuò)展解析自定義配置
preProcessXml(root);
// 從Document的根元素root開(kāi)始進(jìn)行Bean定義的Document對(duì)象
parseBeanDefinitions(root, this.delegate);
// 在解析Bean定義之后,擴(kuò)展解析自定義配置
postProcessXml(root);
this.delegate = parent;
}
說(shuō)明:
獲取Document對(duì)應(yīng)的根元素涨薪,從根元素root開(kāi)始解析文檔骑素。
-------------------------開(kāi)始解析標(biāo)簽元素----------------------
從根節(jié)點(diǎn)開(kāi)始遍歷文檔標(biāo)簽節(jié)點(diǎn)進(jìn)行解析
// 解析文檔中的根級(jí)別元素(import標(biāo)簽,alias標(biāo)簽刚夺,bean標(biāo)簽献丑,beans元素)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// Bean定義的document對(duì)象使用spring的默認(rèn)xml命名空間
if (delegate.isDefaultNamespace(root)) {
// 獲取bean根元素下的所有子節(jié)點(diǎn)
NodeList nl = root.getChildNodes();
// 遍歷所有子節(jié)點(diǎn)
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判斷節(jié)點(diǎn)是否為Element元素節(jié)點(diǎn)
if (node instanceof Element) {
// 將節(jié)點(diǎn)node強(qiáng)制類(lèi)型轉(zhuǎn)為Element元素
Element ele = (Element) node;
// 使用Spring的Bean規(guī)則解析元素節(jié)點(diǎn)
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {// 使用用戶自定義的命名空間解析
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 根節(jié)點(diǎn)沒(méi)有使用spring的默認(rèn)命名空間,就使用用戶自定義的命名空間解析
delegate.parseCustomElement(root);
}
}
11. DefaultBeanDefinitionDocumentReader類(lèi)之解析<import>侠姑,<alias>创橄,<bean>,<beans>元素
// 解析Document元素Element節(jié)點(diǎn)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 如果元素節(jié)點(diǎn)是<import>節(jié)點(diǎn)
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
// 解析Document元素中的<import>節(jié)點(diǎn)
importBeanDefinitionResource(ele);
}
// 如果元素節(jié)點(diǎn)是<alias>節(jié)點(diǎn)
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
// 解析Document元素中的<alias>節(jié)點(diǎn)
processAliasRegistration(ele);
}
// 如果元素節(jié)點(diǎn)是<bean>節(jié)點(diǎn)
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
// 解析Document元素中的<bean>節(jié)點(diǎn)
processBeanDefinition(ele, delegate);
}
// 如果元素節(jié)點(diǎn)是<beans>節(jié)點(diǎn)
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// 解析Document元素中的<beans>節(jié)點(diǎn)
doRegisterBeanDefinitions(ele);
}
}
------------------------- ① 真正解析<import>元素 ----------------------
解析import標(biāo)簽配置的url莽红,判斷路徑是否為絕對(duì)路徑妥畏,然后重新調(diào)用loadBeanDefinitions方法,加載路徑對(duì)應(yīng)的xml資源安吁。
// 解析<import>節(jié)點(diǎn)元素并且將bean定義從給定資源中加載到bean工廠
protected void importBeanDefinitionResource(Element ele) {
// 獲取導(dǎo)入資源的location屬性
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
// 如果location屬性值為空醉蚁,那么直接返回
if (!StringUtils.hasText(location)) {
getReaderContext().error("Resource location must not be empty", ele);
return;
}
// 使用系統(tǒng)變量值來(lái)解析location屬性值
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
Set<Resource> actualResources = new LinkedHashSet<Resource>(4);
// 判斷l(xiāng)ocation屬性值的定位是否為絕對(duì)路徑
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
}
catch (URISyntaxException ex) {
// cannot convert to an URI, considering the location relative
// unless it is the well-known Spring prefix "classpath*:"
}
// 如果location定位為絕對(duì)路徑
if (absoluteLocation) {
try {
// 通過(guò)指定路徑加載bean定義的資源,返回<import>節(jié)點(diǎn)的加載次數(shù)
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
}
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error(
"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
}
}
else {// 否則location定位按照相對(duì)路徑處理
try {
int importCount;
// 通過(guò)指定路徑獲取相對(duì)路徑下的資源Resource
Resource relativeResource = getReaderContext().getResource().createRelative(location);
// 判斷相對(duì)路徑對(duì)應(yīng)的資源是否存在
if (relativeResource.exists()) {
// 使用XmlBeanDefinitionReader讀取相對(duì)路徑下的資源
importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
actualResources.add(relativeResource);
}
else {
String baseLocation = getReaderContext().getResource().getURL().toString();
importCount = getReaderContext().getReader().loadBeanDefinitions(
StringUtils.applyRelativePath(baseLocation, location), actualResources);
}
if (logger.isDebugEnabled()) {
logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
}
}
catch (IOException ex) {
getReaderContext().error("Failed to resolve current resource location", ele, ex);
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
ele, ex);
}
}
Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
// 在解析完<Import>元素之后鬼店,發(fā)送容器導(dǎo)入其他資源處理完成事件
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
-------------------------② 真正解析<bean>元素----------------------
解析bean屬性:id网棍、name、別名妇智、class滥玷、meta元信息氏身、構(gòu)造方法、parent屬性惑畴、單例屬性蛋欣,property屬性、qualifier屬性桨菜。創(chuàng)建BeanDefinition豁状,將屬性設(shè)置到BeanDefinition中(只是進(jìn)行初始化并沒(méi)有將其依賴注入到beanFactory中)。然后創(chuàng)建一個(gè)BeanDefinitionHolder對(duì)象倒得,構(gòu)造器方式設(shè)置BeanDefinition、Bean名稱夭禽、別名數(shù)組霞掺。
// 解析Document元素中的<bean>節(jié)點(diǎn)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// BeanDefinitionHolder類(lèi)對(duì)BeanDefinition的封裝
// 使用BeanDefinitionParserDelegate解析默認(rèn)的bean標(biāo)簽(包括屬性及子元素標(biāo)簽的解析)
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 解析自定義標(biāo)簽
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// IOC容器注冊(cè)BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//在完成向Spring IoC容器注冊(cè)解析得到的Bean定義之后,發(fā)送注冊(cè)事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
// 解析提供的Bean元素
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// 獲取bean元素中的id屬性
// public static final String ID_ATTRIBUTE = "id";
String id = ele.getAttribute(ID_ATTRIBUTE);
// 獲取bean元素中的name屬性
// public static final String NAME_ATTRIBUTE = "name";
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
// 將bean元素中name屬性值存放到別名中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// 如果bean設(shè)置了id讹躯,那么將id作為beanName
// 如果別名集合不為空菩彬,那么將別名集合的第一個(gè)元素作為beanName
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
// 檢查Bean元素配置的id、name或者別名是否重復(fù)
checkNameUniqueness(beanName, aliases, ele);
}
// 解析bean定義本身潮梯,而不考慮名稱或別名骗灶。
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 如果bean元素沒(méi)有配置id、別名或者name并且沒(méi)有包含子Bean元素
// 那么就解析Bean生成唯一beanName并注冊(cè)
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 如果bean元素沒(méi)有配置id秉馏、別名或者name并且包含子Bean元素
// 那么就解析Bean使用別名注冊(cè)
beanName = this.readerContext.generateBeanName(beanDefinition);
// 為了保持對(duì)于Spring 1.2/2.0向后兼容性
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
// 解析bean定義本身耙旦,而不考慮id、名稱萝究、別名(上面已經(jīng)處理過(guò)了)
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
// 專(zhuān)門(mén)記錄解析的Bean元素
this.parseState.push(new BeanEntry(beanName));
String className = null;
// 獲取bean元素中的class屬性
// public static final String CLASS_ATTRIBUTE = "class";
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
// 獲取bean元素中的parent屬性
// public static final String PARENT_ATTRIBUTE = "parent";
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 為Bean元素配置的class名稱和parent屬性值創(chuàng)建BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 對(duì)當(dāng)前的Bean元素中配置的一些屬性進(jìn)行解析和設(shè)置免都,如配置的單態(tài)(singleton)屬性等
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
// 為Bean元素解析的Bean設(shè)置description信息
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 對(duì)Bean元素的meta(元信息)屬性解析
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析Bean元素的構(gòu)造方法設(shè)置
parseConstructorArgElements(ele, bd);
// 解析Bean元素的property屬性
parsePropertyElements(ele, bd);
// 解析Bean元素的qualifier屬性
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
------------------------- ③ 真正解析<property>元素 ----------------------
解析<property>標(biāo)簽及其子標(biāo)簽及其屬性,將property屬性關(guān)聯(lián)bean并且添加到BeanDefinition:
(1)解析property標(biāo)簽及其子標(biāo)簽和屬性帆竹,得到指向解析的property標(biāo)簽引用對(duì)象ref绕娘。
(2)定義一個(gè)屬性對(duì)象PropertyValue,構(gòu)造器方式封裝引用對(duì)象ref栽连、set方法方式封裝Element對(duì)象险领,方式為:pv.setSource(extractSource(ele));(Element對(duì)象為bean封裝)。
(3)將屬性對(duì)象PropertyValue添加到BeanDefinition對(duì)象中秒紧。
// 解析Property元素及其子元素
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
// 獲取bean元素中的子元素
NodeList nl = beanEle.getChildNodes();
// 遍歷子元素節(jié)點(diǎn)
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判斷子元素是否<property>子元素
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
// 調(diào)用解析<property>子元素方法解析
parsePropertyElement((Element) node, bd);
}
}
}
// 解析Property元素
public void parsePropertyElement(Element ele, BeanDefinition bd) {
// 獲取property元素中的name屬性
// public static final String NAME_ATTRIBUTE = "name";
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
// 校驗(yàn)屬性值不為null
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
// 判斷Bean定義中是否存在這個(gè)property元素
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
// 遍歷property元素及其子元素绢陌,同時(shí)解析遍歷到的元素的屬性,如:ref噩茄、value下面。
Object val = parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);
// 解析property元素中的元屬性,key绩聘、value
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
上面解析完spring中的各種標(biāo)簽沥割,將property屬性與PropertyValue對(duì)象關(guān)聯(lián)耗啦,將PropertyValue對(duì)象與BeanDefinition對(duì)象關(guān)聯(lián),將BeanDefinitionHolder對(duì)象關(guān)聯(lián)机杜≈慕玻回到DefaultBeanDefinitionDocumentReader類(lèi)的processBeanDefinition方法中,開(kāi)始向spring IOC容器注冊(cè)BeanDefinitionHolder椒拗。
12. BeanDefinitionReaderUtils類(lèi)之registerBeanDefinition將BeanDefinition在IOC容器中注冊(cè)
// 將Bean定義注冊(cè)到Bean工廠
// BeanDefinitionHolder包括了BeanDefinition和bean的別名
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 獲取Bean定義的名稱
String beanName = definitionHolder.getBeanName();
// 使用Bean名稱和BeanDefinition向IOC容器注冊(cè)
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
// 如果BeanDefinition有別名似将,那么向ioc容器注冊(cè)別名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
說(shuō)明:
從BeanDefinitionHolder中獲取BeanDefinition,將BeanDefinition注冊(cè)的任務(wù)委派到DefaultListableBeanFactory類(lèi)的registerBeanDefinition方法實(shí)現(xiàn)蚀苛。
13. DefaultListableBeanFactory類(lèi)之registerBeanDefinition方法真正注冊(cè)BeanDefinition
// 存儲(chǔ)注冊(cè)的BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
// 使用Bean名稱和BeanDefinition向IOC容器注冊(cè)
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 校驗(yàn)BeanDefinition在验;校驗(yàn)方法的注解、方法名稱等
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
// 通過(guò)beanName獲取對(duì)應(yīng)的舊的BeanDefinition
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 檢查是否有同名的BeanDefinition已經(jīng)在IoC容器中注冊(cè)
if (oldBeanDefinition != null) {
// 如果不允許BeanDefinition重寫(xiě)堵未,那么拋出BeanDefinition存儲(chǔ)異常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
// 如果新的需要注冊(cè)的BeanDefinition不等于之前已經(jīng)注冊(cè)的BeanDefinition
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
// 進(jìn)行新的需要注冊(cè)的BeanDefinition覆蓋之前已經(jīng)注冊(cè)的BeanDefinition
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
// 設(shè)置新的需要注冊(cè)的BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else { // 之前沒(méi)有注冊(cè)過(guò)BeanDefinition
if (hasBeanCreationStarted()) {// 如果已經(jīng)創(chuàng)建BeanDefinition不為空
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
// 設(shè)置當(dāng)前需要注冊(cè)BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 創(chuàng)建存儲(chǔ)更新BeanDefinition的名稱的集合
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
// 將之前的BeanDefinition的名稱插入到集合中
updatedDefinitions.addAll(this.beanDefinitionNames);
// 將當(dāng)前的BeanDefinition的名稱插入到集合中
updatedDefinitions.add(beanName);
// 設(shè)置最新的BeanDefinition的名稱集合
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {// 如果已經(jīng)創(chuàng)建BeanDefinition為空
// 設(shè)置beanName對(duì)應(yīng)的beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 將beanName添加到名稱集合中
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 重置所有已經(jīng)注冊(cè)過(guò)的BeanDefinition的緩存
if (oldBeanDefinition != null || containsSingleton(beanName))
resetBeanDefinition(beanName);
}
}
說(shuō)明:
將BeanDefinition對(duì)象注冊(cè)到BeanDefinitionMap容器中腋舌,就相當(dāng)于注冊(cè)初始化到spring IOC容器中,IOC操作BeanDefinitionMap就可以獲取到所有的Bean的資源渗蟹、配置信息块饺,根據(jù)BeanDefinitionMap中的所有BeanDefinition,就可以實(shí)現(xiàn)依賴注入雌芽。
以上就完成了ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");代碼對(duì)于spring IOC容器的初始化授艰。
spring4中IOC容器初始化的步驟總結(jié)
- 根據(jù)指定路徑加載資源
- refresh方法加載bean是初始化的入口。
- 使用loadBeanDefinition方法載入bean定義資源:
- 使用ResourceLoader通過(guò)給定的類(lèi)路徑加載資源世落,spring將資源文件封裝成了Resource類(lèi)淮腾,這樣就拿到了Resource對(duì)象。
- 使用DocumentLoader將資源Resource轉(zhuǎn)換為Document文檔對(duì)象岛心,這樣就拿到了Document對(duì)象来破。
- 使用DefaultBeanDefinitionDocumentReader類(lèi)解析Document對(duì)象中的<import>,<alias>忘古,<bean>徘禁,<beans>元素。
- 將<bean>元素和對(duì)應(yīng)屬性封裝成BeanDefinition髓堪,再將BeanDefinition封裝成BeanDefinitionHolder送朱。
- DefaultListableBeanFactory類(lèi)中注冊(cè)BeanDefinition。
- 注冊(cè)過(guò)程就是維護(hù)一個(gè)公共的ConcurrentHashMap類(lèi)型的BeanDefinitionMap來(lái)保存Bean配置的BeanDefinition干旁。