Spring源码解析之加载bean

一、初始化阶段

ClassPathResource res = new ClassPathResource("spring/spring.xml");
//获取创建bean的beanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建Reader对象,用来解析res
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
//装载资源
reader.loadBeanDefinitions(res);
TradeAop tradeAop = (TradeAop) factory.getBean("tradeAop");

这段代码是加载IOC容器的过程:

   1:加载资源;

   2:获取beanFactory;

   3:根据beanFactory创建BeanDefinitionReader对象,用来解析资源;

   4:解析资源。BeanDefinitionReader加载和解析资源,将配置文件中的每个bean都解析成BeanDefinition对象。

   5:注册bean。本质是在内部维护这一个HashMap,存放bean对应的BeanDefinition对象。但是并没有实现依赖注入。

在4、5过程中的主要实现是在reader.loadBeanDefinitions()方法中实现的。因此这个方法作为入口来进行分析。

 

对应的bean加载逻辑图

二、源码分析

 doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
    try {
        //获取Doucument实例
        Document doc = this.doLoadDocument(inputSource, resource);
        //根据Document 注册Bean信息
        return this.registerBeanDefinitions(doc, resource);
    } catch (BeanDefinitionStoreException var4) {
        throw var4;
    } catch (SAXParseException var5) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5
    } catch (SAXException var6) {
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
    } catch (ParserConfigurationException var7) {
        throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
    } catch (IOException var8) {
        throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
    } catch (Throwable var9) {
        throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
    }
}

    doLoadDocument方法将资源文件封装成Document对象,代码如下:

    /**
     * loadDocument()根据xml文件加载相应的Document实例
     * getValidationModeForResource() 获取xml的验证模式
     * 
     */
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
        return this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, this.getValidationModeForResource(resource), this.isNamespaceAware());
    }

    2.1 XMl的验证模式
    protected int getValidationModeForResource(Resource resource) {
        //获取验证模式
        int validationModeToUse = this.getValidationMode();
        //如果是手动指定验证 则直接返回。如何设置呢调用:XmlBeanDefinitionReader.setValidating(boolean validating)
        if (validationModeToUse != 1) {
            return validationModeToUse;
        } else {
            //获取验证模式
            int detectedMode = this.detectValidationMode(resource);
            return detectedMode != 1 ? detectedMode : 3;
        }
    }

    
    public int detectValidationMode(InputStream inputStream) throws IOException {
        // Peek into the file to look for DOCTYPE.
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        try {
            boolean isDtdValidated = false;
            String content;
            //一行一行的读取XML文件的内容
            while ((content = reader.readLine()) != null) {
                content = consumeCommentTokens(content);
                if (this.inComment || !StringUtils.hasText(content)) {
                    continue;
                }
                //包含DOCTYPE 为 DTD模式
                if (hasDoctype(content)) {
                    isDtdValidated = true;
                    break;
                }
                //读取< 开始符号。验证模式在<之前
                if (hasOpeningTag(content)) {
                    // End of meaningful data...
                    break;
                }
            }
            return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
        }
        catch (CharConversionException ex) {
            // Choked on some character encoding...
            // Leave the decision up to the caller.
            return VALIDATION_AUTO;
        }
        finally {
            reader.close();
        }
    }

      loadDocument方法做的事情:

        1:调用getValidationModeForResource(resource)验证文件的格式是DTD、XSD模式

        2:将inputSource解析成Document对象

registerBeanDefinitions解析和注册bean的入口

//注册并且返回注册成功数量
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        int countBefore = getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
 }

这个方法主要实现的是 :

1、创建BeanDefinitionDocumentReader对象,并且XmlBeanDefinitionReader委托给这个对象去解析和注册bean

2、返回注册了bean的数目

所以核心方法是documentReader.registerBeanDefinitions(doc, createReaderContext(resource)) 并进行跟踪。

protected void doRegisterBeanDefinitions(Element root) {
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        //处理profile属性
        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;
                }
            }
        }
        //解析前处理
        preProcessXml(root);
        //解析
        parseBeanDefinitions(root, this.delegate);
        //解析后处理
        postProcessXml(root);

        this.delegate = parent;
    }

这个方法的过程分为四步:

1:解析profile属性:为什么要解析这个属性,profile属性是针对于不同环境的的引用。特别是数据库的配置环境。

2:preProcesXml方法:解析前的处理

3:postProcesXml方法:解析后的处理

4:parseBeanDefinitions(root, this.delegate) 这个方法才是真正核心处理bean的逻辑实现。下文会详细讲解。

方法preProcesXml,postProcesXml两个方法其实是个空的方法。真正的实现是交给子类的去实现。这里其实用到了模板方法的应用。

 

parseBeanDefinitions()方法如下:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        //标准bean的处理
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        //自定义bean的处理
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

我们知道bean的声明方式有两种:

  • 配置文件式声明:<bean id="studentService" class="org.springframework.core.StudentService"/>
  • 自定义注解方式:<tx:annotation-driven>

两种方式的读取和解析都存在较大的差异,所以采用不同的解析方法,如果根节点或者子节点采用默认命名空间的话,则调用 parseDefaultElement() 进行解析,否则调用 delegate.parseCustomElement() 方法进行自定义解析。

下面将对默认命名空间进行分析即:parseDefaultElement(ele, delegate)方法

//默认标签解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        //import标签
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        //alisa标签
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
         //bean标签
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        //beans标签
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

parseDefaultElement方法看着就很清晰,分别对import、alias、bean、beans标签进行解析。

下面主要分析一下bean标签的解析过程:

//解析bean标签
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //委托给BeanDefinitionParserDelegate去解析bean标签,返回BeanDefinitionHolder对象
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            //解析bean下面的自定义标签
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                //委托给BeanDefinitionReaderUtils进行bean的注册
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            //监听器通知bean已经加载完成
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

整个解析bean的标签分为四个过程:

1:委托给BeanDefinitionParserDelegate的parseBeanDefinitionElement方法去解析属性。如果解析成功,则返回BeanDefinitionHolder对象,BeanDefinitionHolder对象封装了beanName和对应的beanDefinition。

2:如果bdHolder不为空,则调用decorateBeanDefinitionIfRequired方法解析bean标签自定义的属性。

3:委托给BeanDefinitionReaderUtils去注册对BeanDefinitionHolder对象进行注册。

4:注册完成之后调用监听器进行通知。

那么先看第一个parseBeanDefinitionElement方法解析bean的标签

//BeanDefinitionParserDelegate类解析bean
/**解析标签属性并且封装成AbstractBeanDefinition对象
   * 1.提取id和name属性
   * 2.解析把那个封装成AbstractBeanDefinition
   * 3.如果检测到bean没有指定beanName,那么使用默认规则为此Bean生成beanName
   * 4.将获取到的信息封装到BeanDefinitionHolder的实例中
   */
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
        String id = ele.getAttribute(ID_ATTRIBUTE); //获取id属性
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); //获取name属性

        //分割name属性为,;的
        List<String> aliases = new ArrayList<>();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        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");
            }
        }

        //校验beanName的唯一性
        if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
        }

        //解析对应的元素
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                try {
                    //如果不存在beanName那么根据Spring中提供的命名规则为当前bean生成对应的beanName
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(
                                beanDefinition, this.readerContext.getRegistry(), true);
                    }
                    else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        // 
                        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具体的解析,在解析之前和之后进行了一些处理: 

     1:获取id和name以及对应的alias集合,确定beanName的唯一性。

     2:调用方法 parseBeanDefinitionElement() 对属性进行解析并封装成 GenericBeanDefinition 实例 beanDefinition

     3:根据所获取的信息(beanName、aliases、beanDefinition)构造 BeanDefinitionHolder 实例对象并返回。

 beanName 的命名规则:如果 id 不为空,则 beanName = id;如果 id 为空,但是 alias 不空,则 beanName 为 alias 的第一个元素,如果两者都为空,则根据默认规则来设置 beanName。

parseBeanDefinitionElement()方法包含了对bean标签属性解析的全部过程:

//解析把那个封装成AbstractBeanDefinition
public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    this.parseState.push(new BeanEntry(beanName));
    //获取class属性
    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    //获取parent属性
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    }
    try {
        //实例化一个AbstractBeanDefinition对象。本质是GenericBeanDefinition对象
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        //设置各种配置属性
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        //解析meta元素
        parseMetaElements(ele, bd);
        //解析lookup-method属性
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        //replaced-method属性
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        //解析构造函数
        parseConstructorArgElements(ele, bd);
        //解析property属性
        parsePropertyElements(ele, bd);
        //解析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;
}

      解析bean标签并封装进入BeanDefinition,注释已经很清楚了。对于BeanDefinition会开辟一篇讲解。

parseBeanDefinitionAttributes方法设置各种属性:

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}

		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		bd.setAutowireMode(getAutowireMode(autowire));

		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}

		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
			String candidatePattern = this.defaults.getAutowireCandidates();
			if (candidatePattern != null) {
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		}
		else {
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}

		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}

		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			bd.setInitMethodName(initMethodName);
		}
		else if (this.defaults.getInitMethod() != null) {
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
		}

		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			bd.setDestroyMethodName(destroyMethodName);
		}
		else if (this.defaults.getDestroyMethod() != null) {
			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
			bd.setEnforceDestroyMethod(false);
		}

		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}

从上面代码我们可以清晰地看到对 Bean 标签属性的解析,这些属性我们在工作中都或多或少用到过。就不过多的讲解了。从这里bean的标签已经全部解析完毕。当然还有自定义的标签之后会开一篇讲解。

当标签解析完毕之后会进入BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法对bean进行注册。其本质的含义是缓存一个HashMap将对应的beanName为key,BeanDefinition作为value。

public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {
        // 获取beanName.
        String beanName = definitionHolder.getBeanName();
        //注册bean
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        //注册别名
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

BeanDefinitionRegistry.registerBeanDefinition() 实现通过 beanName 注册 BeanDefinition,如下:

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");
        //校验bean 如果有method-overrieb被设置 就要抛出异常
        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,如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖;加入map缓存。
        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 + "]");
                }
            }
            // 覆盖 beanDefinition 与 被覆盖的 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 + "]");
                }
            }
            // 覆盖 beanDefinition 与 被覆盖的 beanDefinition 不是同类
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            // 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
            if (hasBeanCreationStarted()) {
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<>(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;
        }
        
         重新设置 beanName 对应的缓存
        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

处理过程如下:

1.首先 BeanDefinition 进行校验,该校验也是注册过程中的最后一次校验了,主要是对 AbstractBeanDefinition 的 methodOverrides 属性进行校验

2.根据 beanName 从缓存中获取 BeanDefinition,如果缓存中存在,则根据 allowBeanDefinitionOverriding 标志来判断是否允许覆盖,如果允许则直接覆盖,否则抛出 BeanDefinitionStoreException 异常

3.若缓存中没有指定 beanName 的 BeanDefinition,则判断当前阶段是否已经开始了 Bean 的创建阶段(),如果是,则需要对 beanDefinitionMap 进行加锁控制并发问题,否则直接设置即可。对于 hasBeanCreationStarted() 方法后续做详细介绍,这里不过多阐述。

4.若缓存中存在该 beanName 或者 单利 bean 集合中存在该 beanName,则调用 resetBeanDefinition() 重置 BeanDefinition 缓存。

注册bean的核心就是在beanDefinitionMap上。

 

注册 alias

BeanDefinitionRegistry.registerAlias 完成 alias 的注册。

public void registerAlias(String name, String alias) {
        // 校验 name 、 alias
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        synchronized (this.aliasMap) {
            // name == alias 则去掉alias
            if (alias.equals(name)) {
                this.aliasMap.remove(alias);
            }
            else {
                // 缓存缓存记录
                String registeredName = this.aliasMap.get(alias);
                if (registeredName != null) {
                    // 缓存中的相等,则直接返回
                    if (registeredName.equals(name)) {
                        // An existing alias - no need to re-register
                        return;
                    }
                    // 不允许则抛出异常
                    if (!allowAliasOverriding()) {
                        throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                name + "': It is already registered for name '" + registeredName + "'.");
                    }
                }
                // 当 A --> B 存在时,如果再次出现 A --> B --> C 则抛出异常
                checkForAliasCircle(name, alias);
                // 注册 alias
                this.aliasMap.put(alias, name);
            }
        }
    }

注册 alias 和注册 BeanDefinition 的过程差不多。在最好调用了 checkForAliasCircle() 来对别名进行了检测。

对于bean的加载、解析、注册大致就是这样。其中import、beans、alias标签没有分析。可以自己阅读。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值