Spring4 IOC容器初始化源碼

目錄:

  1. 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é)

  1. 根據(jù)指定路徑加載資源
  2. refresh方法加載bean是初始化的入口。
  3. 使用loadBeanDefinition方法載入bean定義資源:
  4. 使用ResourceLoader通過(guò)給定的類(lèi)路徑加載資源世落,spring將資源文件封裝成了Resource類(lèi)淮腾,這樣就拿到了Resource對(duì)象。
  5. 使用DocumentLoader將資源Resource轉(zhuǎn)換為Document文檔對(duì)象岛心,這樣就拿到了Document對(duì)象来破。
  6. 使用DefaultBeanDefinitionDocumentReader類(lèi)解析Document對(duì)象中的<import>,<alias>忘古,<bean>徘禁,<beans>元素。
  7. 將<bean>元素和對(duì)應(yīng)屬性封裝成BeanDefinition髓堪,再將BeanDefinition封裝成BeanDefinitionHolder送朱。
  8. DefaultListableBeanFactory類(lèi)中注冊(cè)BeanDefinition。
  9. 注冊(cè)過(guò)程就是維護(hù)一個(gè)公共的ConcurrentHashMap類(lèi)型的BeanDefinitionMap來(lái)保存Bean配置的BeanDefinition干旁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驶沼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子争群,更是在濱河造成了極大的恐慌回怜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件换薄,死亡現(xiàn)場(chǎng)離奇詭異玉雾,居然都是意外死亡翔试,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)复旬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)垦缅,“玉大人,你說(shuō)我怎么就攤上這事驹碍”谙眩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵志秃,是天一觀的道長(zhǎng)怔球。 經(jīng)常有香客問(wèn)我,道長(zhǎng)洽损,這世上最難降的妖魔是什么庞溜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮碑定,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘又官。我一直安慰自己延刘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布六敬。 她就那樣靜靜地躺著碘赖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪外构。 梳的紋絲不亂的頭發(fā)上普泡,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音审编,去河邊找鬼撼班。 笑死,一個(gè)胖子當(dāng)著我的面吹牛垒酬,可吹牛的內(nèi)容都是我干的砰嘁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼勘究,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼矮湘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起口糕,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缅阳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后景描,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體十办,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秀撇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了橘洞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌袜。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖炸枣,靈堂內(nèi)的尸體忽然破棺而出虏等,到底是詐尸還是另有隱情,我是刑警寧澤适肠,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布霍衫,位于F島的核電站,受9級(jí)特大地震影響侯养,放射性物質(zhì)發(fā)生泄漏敦跌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一逛揩、第九天 我趴在偏房一處隱蔽的房頂上張望柠傍。 院中可真熱鬧,春花似錦辩稽、人聲如沸惧笛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叉橱。三九已至砖顷,卻和暖如春抵怎,著一層夾襖步出監(jiān)牢的瞬間莺债,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工到千, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昌渤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓父阻,卻偏偏與公主長(zhǎng)得像愈涩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子加矛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理履婉,服務(wù)發(fā)現(xiàn),斷路器斟览,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,811評(píng)論 6 342
  • 1.1 Spring IoC容器和bean簡(jiǎn)介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,583評(píng)論 0 8
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書(shū)筆記毁腿,整理的知識(shí)點(diǎn),也是為了防止忘記,尊重勞動(dòng)成果已烤,轉(zhuǎn)載注明出處哦鸠窗!如果你也喜歡,那...
    波波波先森閱讀 12,291評(píng)論 6 86
  • 1胯究、去年看了人類(lèi)簡(jiǎn)史稍计,有三個(gè)被我記住的觀點(diǎn) a、只有人類(lèi)才會(huì)虛構(gòu)故事裕循,正是因?yàn)樘摌?gòu)故事的本領(lǐng)臣嚣,才得以讓人類(lèi)延續(xù)到今...
    一凡SU閱讀 553評(píng)論 3 2