Spring源碼閱讀筆記04:默認xml標籤解析

  上文咱們主要學習了Spring是如何獲取xml配置文件而且將其轉換成Document,咱們知道xml文件是由各類標籤組成,Spring須要將其解析成對應的配置信息。以前提到過Spring中的標籤包括默認標籤和自定義標籤兩種,而兩種標籤的用法以及解析方式存在着很大的不一樣,本文詳細分析默認標籤的解析過程。html

  默認標籤的解析是在parseDefaultElement函數中進行的,函數中的功能邏輯一目瞭然,分別對4種不一樣標籤(import、alias、bean和 beans)作了不一樣的處理。node

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        // 對import標籤的處理
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        // 對alias標籤的處理
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        // 對bean標籤的處理
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        // 對beans標籤的處理
        doRegisterBeanDefinitions(ele);
    }
}

  在4種標籤的解析中,對bean標籤的解析最爲複雜也最爲重要,這是本文重點分析對象,若是能理解此標籤的解析過程,其餘標籤的解析天然會迎刃而解。首先咱們進入函數processBeanDefinition(ele, delegate):數據庫

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            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));
    }
}

  大體的邏輯總結以下: 緩存

  1. 首先委託BeanDefinitionDelegate類的parseBeanDefinitionElement方法進行元素解析,返回BeanDefinitionHolder類型的實例bdHolder,通過這個方法後,bdHolder實例已經包含咱們配置文件中配置的各類屬性了,例如class、name、id、alias之類的屬性;
  2. 當返回的bdHolder不爲空的狀況下若存在默認標籤的子節點下再有自定義屬性,還須要再次對自定義標籤進行解析;
  3. 解析完成後,須要對解析後的bdHolder進行註冊,一樣,註冊操做委託給了BeanDefinitionReaderUtils的registerBeanDefinition方法;
  4. 最後發出響應事件,通知相關的監聽器,這個bean已經加載完成了;

  下面會針對各個操做作進一步分析。併發

1. 解析BeanDefinition

  首先咱們從元素解析及信息提取開始,也就是BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele),進入BeanDefinitionDelegate類的parseBeanDefinitionElement方法:ide

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 解析id屬性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 解析name屬性
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    // 分割name屬性
    List<String> aliases = new ArrayList<String>();
    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");
        }
    }

    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);
                    // Register an alias for the plain bean class name, if still possible,
                    // if the generator returned the class name plus a suffix.
                    // This is expected for Spring 1.2/2.0 backwards compatibility.
                    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;
}

  以上即是對默認標籤解析的全過程了。在開始對屬性展開全面解析前,Spring又作了一些功能劃分,主要以下:函數

  1. 提取元素中的id以及name屬性;
  2. 進一步解析其餘全部屬性並統一封裝至GenericBeanDefinition類型的實例中;
  3. 若是檢測到bean沒有指定beanName,那麼使用默認規則爲此Bean生成beanName;
  4. 將獲取到的信息封裝到BeanDefinitionHolder的實例中;

  咱們進一步地查看步驟2中對標籤其餘屬性的解析過程:學習

public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, BeanDefinition containingBean) {
    this.parseState.push(new BeanEntry(beanName));
    String className = null;
    // 解析class屬性
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }

    try {
        String parent = null;
        // 解析parent屬性
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        // 建立用於承載屬性的AbstractBeanDefinition類型的GenericBeanDefinition
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        // 硬編碼解析默認bean的各類屬性
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        // 提取description
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        // 解析元數據
        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標籤的全部屬性解析,不論經常使用的仍是不經常使用的咱們都看到了,儘管有些複雜的屬性還須要進一步的解析。咱們着重看一些複雜標籤屬性的解析。ui

1.1 建立用於屬性承載的BeanDefinition

  BeanDefinition是一個接口,在Spring中有三個實現類:RootBeanDefinition、ChildBeanDefinition以及GenericBeanDefinition,均繼承自AbstractBeanDefiniton,其中BeanDefinition是配置文件<bean>元素標籤在容器中的內部表示形式。<bean>元素標籤擁有class、scope、lazy-init等配置屬性,BeanDefinition則提供了相應的beanClass、scope、lazyInit屬性,BeanDefinition和<bean>中的屬性是一一對應的。其中RootBeanDefinition是最經常使用的實現類,它對應通常性的<bean>元素標籤, GenericBeanDefinition是自2.5版本之後新加入的bean文件配置屬性定義類,是一站式服務類。this

  在配置文件中能夠定義父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而沒有父<bean>的<bean>就使用RootBeanDefinition表示。

  Spring經過BeanDefinition將配置文件中的<bean>配置信息轉換爲容器的內部表示,並將這些BeanDefiniton註冊到BeanDefinitonRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的內存數據庫,主要是以map的形式保存,後續操做直接從BeanDefinitionRegistry中讀取配置信息

  由此可知,要解析屬性首先要建立用於承載屬性的實例,也就是建立GenericBeanDefinition類型的實例。而代碼createBeanDefinition(className,parent)的做用就是實現此功能:

protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
            throws ClassNotFoundException {
    return BeanDefinitionReaderUtils.createBeanDefinition(
            parentName, className, this.readerContext.getBeanClassLoader());
}

public static AbstractBeanDefinition createBeanDefinition(
            String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
    GenericBeanDefinition bd = new GenericBeanDefinition();
    // parentName可能爲空
    bd.setParentName(parentName);
    if (className != null) {
        // 若是classLoader不爲空,則使用已傳入的classLoader加載類對象,不然只是記錄className
        if (classLoader != null) {
            bd.setBeanClass(ClassUtils.forName(className, classLoader));
        }
        else {
            bd.setBeanClassName(className);
        }
    }
    return bd;
}

1.2 解析各類屬性

  當咱們建立了bean信息的承載實例後,即可以開始各類屬性解析了,這部分的主要邏輯在parseBeanDefinitionAttributes方法中:

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
            BeanDefinition containingBean, AbstractBeanDefinition bd) {
    // 解析scope屬性
    if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
        // Spring 2.x "scope" attribute
        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
            // scope與singleton兩個屬性只能指定其中之一,不能夠同時出現,不然Spring將會報出異常
            error("Specify either 'scope' or 'singleton', not both", ele);
        }
    }
    // 解析singleton屬性
    else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        // Spring 1.x "singleton" attribute
        bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?
                BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);
    }
    else if (containingBean != null) {
        // Take default from containing bean in case of an inner bean definition.
        // 在嵌入beanDefinition狀況下且沒有單獨指定scope屬性則使用父類默認的屬性
        bd.setScope(containingBean.getScope());
    }
    // 解析abstract屬性
    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }
    // 解析lazy-init屬性
    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }
    // 若沒有設置或設置成其餘字符都會被設置爲false
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
    // 解析autowire屬性
    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    bd.setAutowireMode(getAutowireMode(autowire));
    // 解析dependency-check屬性
    String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
    bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
    // 解析depends-on屬性
    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
        String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
        bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    }
    // 解析autowire-candidate屬性
    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));
    }
    // 解析primary屬性
    if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
        bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    }
    // 解析init-method屬性
    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
        String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
        if (!"".equals(initMethodName)) {
            bd.setInitMethodName(initMethodName);
        }
    }
    else {
        if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }
    }
    // 解析destroy-method屬性
    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
        String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
        if (!"".equals(destroyMethodName)) {
            bd.setDestroyMethodName(destroyMethodName);
        }
    }
    else {
        if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }
    }
    // 解析factory-method屬性
    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
        bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    }
    // 解析factory-bean屬性
    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
        bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    }
    return bd;
}

  咱們能夠清楚地看到Spring完成了對全部bean屬性的解析,這些屬性中有不少是咱們常用的,也有些是咱們不熟悉的,有興趣能夠查閱相關資料進一步瞭解。固然除了這部分屬性解析,後面還有一些其餘的屬性解析(好比constructor-arg、property等),在此就不所有列出了。

 

2. AbstractBeanDefinition

  至此便完成了對XML文檔到GenericBeanDefinition的轉換,也就是說到這裏,XML中全部的配置均可以在GenericBeanDefinition的實例類中找到對應的屬性。

  GenericBeanDefinition只是子類實現,大部分的通用屬性都保存在了AbstractBeanDefinition中,因此這裏再次經過AbstractBeanDefinition的屬性來回顧一下都解析了哪些對應的配置,以加深理解:

public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {
    // 此處省略靜態變量以及final常量
    
    /** bean的做用範圍,對應bean屬性scope */    
    private String scope = SCOPE_DEFAULT;
    
    /** 是不是單例,來自bean屬性scope */
    private boolean singleton = true;
    
    /** 是不是原型,來自bean屬性scope */
    private boolean prototype = false;

    /** 是不是抽象,對應bean屬性abstract */
    private boolean abstractFlag = false;
    
    /** 是否延遲加載,對應bean屬性lazy-init */
    private boolean lazyInit = false;
    
    /** 自動注入模式,對應bean屬性autowire */
    private int autowireMode = AUTOWIRE_NO;
    
    /** 依賴檢查,Spring 3.0後棄用這個屬性 */
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;

    /** 用來表示一個bean的實例化依靠另外一個bean先實例化,對應bean屬性depend-on */
    private String[] dependsOn;
    
    /** autowire-candidate屬性設置爲false,這樣容器在查找自動裝配對象時,
     *將不考慮該bean,即它不會被考慮做爲其餘bean自動裝配的候選
     *者,可是該bean自己仍是可使用自動裝配來注入其餘bean的
     *對應bean屬性autowire-candidate */
    private boolean autowireCandidate = true;

    /** 自動裝配時當出現多個bean候選着時,將做爲首選着,對應bean屬性primary */
    private boolean primary = false;
    
    /**  */
    private final Map<String, AutowireCandidateQualifier> qualifiers =
            new LinkedHashMap<String, AutowireCandidateQualifier>(0);

    /**  */
    private boolean nonPublicAccessAllowed = true;
    
    /**  */
    private boolean lenientConstructorResolution = true;
    
    /**  */
    private ConstructorArgumentValues constructorArgumentValues;

    /**  */
    private MutablePropertyValues propertyValues;

    /**  */
    private MethodOverrides methodOverrides = new MethodOverrides();

    /**  */
    private String factoryBeanName;

    /**  */
    private String factoryMethodName;

    /**  */
    private String initMethodName;

    /**  */
    private String destroyMethodName;

    /**  */
    private boolean enforceInitMethod = true;

    /**  */
    private boolean enforceDestroyMethod = true;

    /**  */
    private boolean synthetic = false;
    
    /**  */
    private int role = BeanDefinition.ROLE_APPLICATION;

    /**  */
    private String description;
    
    /** 這個bean定義的資源 */ 
    private Resource resource;
}

3. 註冊解析的BeanDefinition

  解析完成以後獲得的beanDinition已經能夠知足後續的使用要求了,惟一還剩下的工做就是註冊,也就是processBeanDefinition函數中的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext(). get())所完成的工做:

public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String aliase : aliases) {
            registry.registerAlias(beanName, aliase);
        }
    }
}

  從上面的代碼能夠看出,解析好的beanDefinition都會被註冊到BeanDefinitionRegistry類型的實例registry中,beanDefinition的註冊分紅了兩部分:經過beanName的註冊以及經過別名的註冊。

3.1 經過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");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            // 註冊前的最後一次校驗,這裏的校驗不一樣於以前的XML文件校驗
            // 主要是對於AbstractBeanDefinition屬性中的methodOverrides校驗
            // 校驗methodOverrides是否與工廠方法並存或者methodOverrides對應的方法根本不存在
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition oldBeanDefinition;
    // 由於beanDefinitionMap是全局變量,這裏確定會存在併發訪問的狀況
    synchronized (this.beanDefinitionMap) {
        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        // 處理註冊已經註冊的beanName狀況
        if (oldBeanDefinition != null) {
            // 若是對應的BeanName已經註冊而且在配置中配置了bean不容許被覆蓋,則拋出異常
            if (!this.allowBeanDefinitionOverriding) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                        "': There is already [" + oldBeanDefinition + "] bound.");
            }
            else {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName +
                            "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            }
        }
        else {
            // 記錄beanName
            this.beanDefinitionNames.add(beanName);
            this.frozenBeanDefinitionNames = null;
        }
        // 註冊beanDefinition
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    // 重置全部beanName對應的緩存
    if (oldBeanDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

  如上,在對於bean的註冊處理方式上,主要進行了以下幾個步驟:

  1. 對AbstractBeanDefinition的校驗。在解析XML文件的時候咱們提過校驗,可是此校驗非彼校驗,以前的校驗是針對於XML格式的校驗,而此時的校驗則是對於AbstractBeanDefinition的methodOverrides屬性的;
  2. 對beanName已經註冊的狀況的處理。若是設置了不容許bean的覆蓋,會拋出異常,不然直接覆蓋;
  3. 加入map緩存;
  4. 清除解析以前留下的對應 beanName的緩存;

3.2 經過別名註冊BeanDefinition

public void registerAlias(String name, String alias) {
    Assert.hasText(name, "'name' must not be empty");
    Assert.hasText(alias, "'alias' must not be empty");
    // 若是beanName與alias相同的話不記錄alias,並刪除對應的alias
    if (alias.equals(name)) {
        this.aliasMap.remove(alias);
    }
    else {
        // 若是alias不容許被覆蓋則拋出異常
        if (!allowAliasOverriding()) {
            String registeredName = this.aliasMap.get(alias);
            if (registeredName != null && !registeredName.equals(name)) {
                throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                        name + "': It is already registered for name '" + registeredName + "'.");
            }
        }
        // 當A->B存在時,若再次出現A->C->B時候則會拋出異常
        checkForAliasCircle(name, alias);
        this.aliasMap.put(alias, name);
    }
}

  由以上代碼中能夠得知註冊alias的步驟以下:

  1. alias與beanName相同狀況處理。若alias與beanName名稱相同則不須要處理並刪除掉原有alias;
  2. alias覆蓋處理。若aliasName已經使用並已經指向了另外一beanName則須要根據用戶的設置進行處理;
  3. alias循環檢查。當A->B存在時,若再次出現A->C->B時候則會拋出異常;
  4. 註冊alias;

4. 總結

  本文主要集中在分析從如何將默認xml標籤解析成BeanDefinition到將其註冊到容器中這一過程,至此Spring對配置的轉化工做就完成了,後面就要開始Bean的獲取這部分的邏輯的分析了。

相關文章
相關標籤/搜索