我是靠谱客的博主 奋斗咖啡,最近开发中收集的这篇文章主要介绍Spring源码阅读-IOC容器初始化过程Resource定位:BeanDefinition载入:注册:以FileSystemXmlApplicationContext为例来看下IOC容器初始化的过程。,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Spring IOC容器的初始化过程:Resource定位,BeanDefinition载入,向IOC容器注册BeanDefinition。整个过程由refresh()方法触发,三个过程由不同的模块完成,使用户更加灵活的对这三个过程剪裁和扩展。

BeanDefinition 就是POJO对象在IOC容器中的抽象。通过BeanDefinition 这个数据结构,使IOC容器能够方便的对POJO对象也就是Bean进行管理。将BeanDefinition 注册到hashmap中,也就是一个IOC容器中,通过hashmap持有这些BeanDefinition结构。就好比我们对物品整理归类,苹果,桃子,草莓都是水果,可以归到水果类,然后对水果进行统一的处理,比如放到冰箱保鲜。这里BeanDefinition就是苹果或桃子或李子,容器就是冰箱。

IOC容器的初始化过程不包括Bean依赖注入。Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。(配置lazyinit属性除外)

具体过程(以FileSystemXmlApplicationContext为例):

Resource定位:

指BeanDefinition资源定位。它由ResourceLoader通过统一的Resource接口完成,这个Resource对各种形式的BeanDefinition的使用提供了统一接口。在文件系统中的BeanDefinition可以用FileSystemResource抽象;在类路径中的BeanDefinition可以用ClassPathResource来抽象。Resource定位就是找水果的过程,水果可能在树上,也可能在地里长着。

BeanDefinition载入:

指把用户定义好的Bean表示成IOC容器的数据结构,这个数据结构就是BeanDefinition。

注册:

指向IOC容器注册这些BeanDefinition的过程。通俗的讲就是将BeanDefinition注入到一个hashmap中。

以FileSystemXmlApplicationContext为例来看下IOC容器初始化的过程。

我们先看下FileSystemXmlApplicationContext继承关系:

FileSystemXmlApplicationContext源码:

package org.springframework.context.support;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

/**
 * FileSystemXmlApplicationContext是一个支持xml定义BeanDefinition的ApplicationContext,
 * 并且可以指定以文件形式的BeanDefinition的读入,这些文件可以使用文件路径和URL定义来表示。
 * 在测试环境和独立应用环境中,这个ApplicationContext非常有用。
 */
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {

    public FileSystemXmlApplicationContext() {
    }

    public FileSystemXmlApplicationContext(ApplicationContext parent) {
        super(parent);
    }

    /**
     * 从给定的xml文件中加载Bean定义,创建一个FileSystemXmlApplicationContext,并自动刷新上下文
     * configLocation包含的是BeanDefinition所在的文件路径 
     */
    public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    public FileSystemXmlApplicationContext(String... configLocations) throws BeansException {
        this(configLocations, true, null);
    }

    /**
     * 允许configLocation包含多个BeanDefinition的文件路径的同时,还允许指定自己的双亲IOC容器
     */
    public FileSystemXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
        this(configLocations, true, parent);
    }

    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
        this(configLocations, refresh, null);
    }

    /**
     * 在对象的初始化过程中,调用refresh函数载入BeanDefinition,
     * 这个refresh()启动了BeanDefinition的载入过程
     */
    public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }


    /**
     * 通过构造一个FileSystemResource来得到一个在文件系统中定位的BeanDefinition
     */
    @Override
    protected Resource getResourceByPath(String path) {
        if (path != null && path.startsWith("/")) {
            path = path.substring(1);
        }
        return new FileSystemResource(path);
    }

}

从前面的类图中我们可以看出,FileSystemXmlApplicationContext已经通过继承AbstractApplicationContext具备了ResourceLoader读入以Resource定义的BeanDefinition的能力。因为AbstractApplicationContext的基类是DefaultResourceLoader。

BeanDefinitionReader

在介绍IOC容器初始化过程之前,我们先了解一个类:BeanDefinition读取器-BeanDefinitionReader。BeanDefinitionReader利用ResouceLoader从指定位置加载Bean定义,将物理资源转化生成Resource。

图来自:https://blog.csdn.net/HNU_Csee_wjw/article/details/120406576

以编程的方式使用DefaultListableBeanFactory时,我们定义一个Resource来定位容器使用的BeanDefinition:ClassPathResource res = new ClassPathResource("beans.xml");

这里定义的Resource并不能由DefaultListableBeanFactory直接使用,而是通过BeanDefinitionReader来对这些信息进行处理。Spring为我们提供了一系列加载不同Resource的读取器的实现,使不同的容器可以配置相应的BeanDefinitionReader。比如FileSystemXmlApplicationContext的父类AbstractXmlApplicationContext用的读取器是XmlBeanDefinitionReader类型。

AbstractXmlApplicationContext


    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

    // 用给定的XmlBeanDefinitionReader加载BeanDefinition
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
    }

推荐阅读:SpringIOC源码解析(4)—— Resource、ResourceLoader、容器之间的微妙关系

下面我们进入正题,看一下FileSystemXmlApplicationContext的初始化流程:

FileSystemXmlApplicationContext的初始化流程由父类AbstractApplicationContext的refresh()方法触发。

AbstractApplicationContext类refresh()方法:

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // 子类启动refreshBeanFactory()
            // FileSystemXmlApplicationContext 是AbstractApplicationContext的子类
            // 在这一步执行refreshBeanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 准备用于此上下文的beanFactory
            prepareBeanFactory(beanFactory);

            try {
                // 设置beanFactory的后置处理
                postProcessBeanFactory(beanFactory);

                // 在上下文中调用注册为bean的后置处理器。
                invokeBeanFactoryPostProcessors(beanFactory);

                // 注册拦截bean创建的bean处理器。
                registerBeanPostProcessors(beanFactory);

                // 初始化上下文中的消息源
                initMessageSource();

                // 为上下文初始化事件多播机制
                initApplicationEventMulticaster();

                // 初始化其他特殊的Bean
                onRefresh();

                // 检查监听的Bean并注册他们到容器中
                registerListeners();

                // 实例化所有剩余的(非懒加载)的单例
                finishBeanFactoryInitialization(beanFactory);

                // 最后:发布容器事件
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // 为避免资源占用销毁在前面创建的单例
                destroyBeans();

                // 重置Reset 'active' 表示
                cancelRefresh(ex);

                // 向调用方抛出异常
                throw ex;
            }

            finally {
                // 重置Spring核心中的常见缺省缓存,因为我们可能不再需要单例bean的元数据。。。
                resetCommonCaches();
            }
        }
    }

先看一张流程图(为了突出关键步骤,只画了关键类,省略了参数):

FileSystemResource定位

结合流程图可以看到,最后getResourceByPath()方法会被子类FileSystemXmlApplicationContext实现,返回一个FileSystemResource对象,完成BeanDefinition的定位。Spring通过FileSystemResource对象,可以进行相关的IO操作。

定位完成后,就可以用返回的Resource对象来进行BeanDefinition的载入了。

BeanDefinition载入

所谓BeanDefinition载入,就是把xml文件中定义的Bean定义,进过转换和层层解析,根据解析结果,将属性值封装成Property value对象设置到BeanDefinition中,处理成IOC容器中的数据结构。

入口在BeanDefinitionParserDelegate类的parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)方法。

核心处理方法是:

parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean)

我们重点看下:

// 解析bean定义本身,不考虑名称或别名。如果在解析bean定义期间出现问题可能返回null
// 只是把Bean的属性设置载入到BeanDefinition,不涉及对象的实例化过程。
// 对象的实例化在依赖注入时完成
public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, BeanDefinition containingBean) {

        this.parseState.push(new BeanEntry(beanName));

        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }

        try {
            String parent = null;
            if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                parent = ele.getAttribute(PARENT_ATTRIBUTE);
            }
            // 生成需要的BeanDefinition对象,为Bean定义信息的载入做准备
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            // 对当前的Bean元素进行属性解析,并设置description信息
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            // 对各种<bean>元素的信息进行解析
            parseMetaElements(ele, bd);
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            // 解析<bean>的构造函数设置
            parseConstructorArgElements(ele, bd);
            // 解析<bean>的property设置
            parsePropertyElements(ele, bd);
            parseQualifierElements(ele, bd);

            bd.setResource(this.readerContext.getResource());
            bd.setSource(extractSource(ele));

            return bd;
        }
        // 这里是我们经常见到的异常处理(原来是在载入BeanDefinition时处理的)
        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;
    }

BeanDefinitionParserDelegate类:

解析<bean>的property设置,对property子元素进行解析,Array、List、Set、Map、prop等各种元素都会在这里解析,生成对应的数据对象。比如MangedList、ManagedArray、ManageSet等,是Spring对具体的BeanDefinition的数据封装。

    /**
     * 分析给定元素子元素属性
     */
    public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        // 遍历处理所以的子元素
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
                parsePropertyElement((Element) node, bd);
            }
        }
    }

public void parsePropertyElement(Element ele, BeanDefinition bd) {
        // 取得property的名字
        String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
        if (!StringUtils.hasLength(propertyName)) {
            error("Tag 'property' must have a 'name' attribute", ele);
            return;
        }
        this.parseState.push(new PropertyEntry(propertyName));
        try {
           // 如果同一个Bean中已经有同名的property存在,则不进行解析,直接返回。
            if (bd.getPropertyValues().contains(propertyName)) {
                error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
                return;
            }
            Object val = parsePropertyValue(ele, bd, propertyName);
            PropertyValue pv = new PropertyValue(propertyName, val);
            parseMetaElements(ele, pv);
            pv.setSource(extractSource(ele));
            bd.getPropertyValues().addPropertyValue(pv);
        }
        finally {
            this.parseState.pop();
        }
    }
/**
* 取得每个property的值,也许是一个list或其他
*/
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
        String elementName = (propertyName != null) ?
                        "<property> element for property '" + propertyName + "'" :
                        "<constructor-arg> element";

        // 应该只有一个子节点: 引用类型, 值类型, 集合等.
        NodeList nl = ele.getChildNodes();
        Element subElement = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
                    !nodeNameEquals(node, META_ELEMENT)) {
                // Child element is what we're looking for.
                if (subElement != null) {
                    error(elementName + " must not contain more than one sub-element", ele);
                }
                else {
                    subElement = (Element) node;
                }
            }
        }
        // 这里判断property的属性,是ref还是value。不允许同时是ref和value
        boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
        boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
        if ((hasRefAttribute && hasValueAttribute) ||
                ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
            error(elementName +
                    " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
        }
        // 如果是ref,创建一个RuntimeBeanReference类型的对象,封装ref的信息
        if (hasRefAttribute) {
            String refName = ele.getAttribute(REF_ATTRIBUTE);
            if (!StringUtils.hasText(refName)) {
                error(elementName + " contains empty 'ref' attribute", ele);
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName);
            ref.setSource(extractSource(ele));
            return ref;
        }
        // 如果是value,创建一个TypedStringValue类型的对象,这个对象封装了value的信息
        else if (hasValueAttribute) {
            TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
            valueHolder.setSource(extractSource(ele));
            return valueHolder;
        }
        // 如果还有其他子元素,触发对子元素的解析
        else if (subElement != null) {
            return parsePropertySubElement(subElement, bd);
        }
        else {
            // Neither child element nor "ref" or "value" attribute found.
            error(elementName + " must specify a ref or value", ele);
            return null;
        }
    }
/**
     * 分析属性或构造函数arg元素的值、ref或集合子元素。
     * @param ele 属性元素的子元素;我们还不知道是哪个
     * @param defaultValueType 任何的默认类型(类名)
     * {@code <value>} 可能创建的标记
     */
    public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
        if (!isDefaultNamespace(ele)) {
            return parseNestedCustomElement(ele, bd);
        }
        // 节点是Bean
        else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
            BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
            if (nestedBd != null) {
                nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
            }
            return nestedBd;
        }
        // 节点是引用类型
        else if (nodeNameEquals(ele, REF_ELEMENT)) {
            // 对任何bean的任何名称的通用引用。
            String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
            boolean toParent = false;
            if (!StringUtils.hasLength(refName)) {
                // 对同一XML文件中另一个bean的id的引用。
                refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
                if (!StringUtils.hasLength(refName)) {
                    // 对父上下文中另一个bean的id的引用。
                    refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
                    toParent = true;
                    if (!StringUtils.hasLength(refName)) {
                        error("'bean', 'local' or 'parent' is required for <ref> element", ele);
                        return null;
                    }
                }
            }
            if (!StringUtils.hasText(refName)) {
                error("<ref> element contains empty target attribute", ele);
                return null;
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
            ref.setSource(extractSource(ele));
            return ref;
        }
        // 节点是idref类型
        else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
            return parseIdRefElement(ele);
        }
        // 节点是value
        else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
            return parseValueElement(ele, defaultValueType);
        }
        // 节点是null
        else if (nodeNameEquals(ele, NULL_ELEMENT)) {
            // 对象是null,创建一个TypedStringValue类型的对象为其保留地址空间
            TypedStringValue nullHolder = new TypedStringValue(null);
            nullHolder.setSource(extractSource(ele));
            return nullHolder;
        }
        // 节点是数组类型
        else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
            return parseArrayElement(ele, bd);
        }
        // 节点是List集合类型
        else if (nodeNameEquals(ele, LIST_ELEMENT)) {
            return parseListElement(ele, bd);
        }
        // 节点是Set集合类型
        else if (nodeNameEquals(ele, SET_ELEMENT)) {
            return parseSetElement(ele, bd);
        }
        // 节点是Map类型
        else if (nodeNameEquals(ele, MAP_ELEMENT)) {
            return parseMapElement(ele, bd);
        }
        // 节点是props类型
        else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
            return parsePropsElement(ele);
        }
        else {
            error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
            return null;
        }
    }

我们看一下List这样的属性配置是如何被解析的:

// 返回ManagedList类型的对象
public List<Object> parseListElement(Element collectionEle, BeanDefinition bd) {
        String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
        NodeList nl = collectionEle.getChildNodes();
        ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
        target.setSource(extractSource(collectionEle));
        target.setElementTypeName(defaultElementType);
        target.setMergeEnabled(parseMergeAttribute(collectionEle));
        // 具体的List元素解析过程
        parseCollectionElements(nl, target, bd, defaultElementType);
        return target;
    }

    protected void parseCollectionElements(
            NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
        for (int i = 0; i < elementNodes.getLength(); i++) {
            Node node = elementNodes.item(i);
            // node需要是element类型
            if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
                // 将node添加到taget中,并递归解析下一层子元素 
                target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
            }
        }
    }

经过这样层层解析,我们就将xml文件中定义的Definition加载到了IOC容器中,并在容器中建立了映射,完成了IOC容器管理Bean对象的准备工作。这些数据结构可以以AbstractBeanDefinition为入口,让IOC容器执行索引、查询和操作。你没有看错,这一小节,经过了这么多的处理,就是对xml文件解析,把内容处理成BeanDefinition。看迷茫的同学可以结合类图,往回倒一下处理的入口。

这时候IOC容器BeanDefinition中存在的还只是一些静态的配置信息,要想让容器起作用,还需完成数据向容器的注册

BeanDefinition在IOC容器中的注册

我们回到DefaultBeanDefinitionDocumentReader类

    /**
     * 处理给定的bean元素,解析bean定义并将其注册到注册表中。
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // BeanDefinition载入
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // 注册实例
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

将BeanDefinition载入后,开始注册BeanDefinition到IOC容器。

注册的关键代码,在DefaultListableBeanFactory类:

在DefaultListableBeanFactory中,是通过一个hashmap来持有载入的BeanDefinition的:

/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
@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");

        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;
        // 如果有相同名字的Bean已经在IOC容器中注册了,如果不允许覆盖,则抛出异常
        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        if (oldBeanDefinition != null) {
            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)) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + oldBeanDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + oldBeanDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            // 覆盖old beanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            // 检查此工厂的bean创建阶段是否已启动,即,是否有任何bean被标记为同时创建。
            if (hasBeanCreationStarted()) {
                // 加锁
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

到此,完成了BeanDefinition的注册,完成了IOC容器的初始化过程。此时使用的IOC容器DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,并且可以在BeanDefinitionMap中被检索到和使用。通过容器对这些Bean信息进行处理和维护。

最后

以上就是奋斗咖啡为你收集整理的Spring源码阅读-IOC容器初始化过程Resource定位:BeanDefinition载入:注册:以FileSystemXmlApplicationContext为例来看下IOC容器初始化的过程。的全部内容,希望文章能够帮你解决Spring源码阅读-IOC容器初始化过程Resource定位:BeanDefinition载入:注册:以FileSystemXmlApplicationContext为例来看下IOC容器初始化的过程。所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部