1. 程式人生 > >【2】Ioc容器的初始化過程 --- BeanDefinition在IoC容器中的註冊

【2】Ioc容器的初始化過程 --- BeanDefinition在IoC容器中的註冊

1. 準備

在上一個階段的基礎之上進行下一步分析

開始的地方

//這裡是處理BeanDefinition的地方,具體委託給BeanDefinitionParserDelegate完成,ele對應XML元素,DOM樹元素

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

    //BeanDefinitionHolder是BeanDefiniton物件的封裝類,封裝類BeanDefinition,Bean的名字和別名,用它完成向Ioc容器註冊

    //得到這個BeanDefinitionHolder就說明BeanDefinition是通過BeanDefinitionParserDelegate對XML元素按SpringBean的規則解析得到

    //這裡只關注解析,方法進入這裡

    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);

    if (bdHolder != 

null) {

        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

  

        try {

            //在上一個階段,已經解析好了BeanDefinition,然後在這裡向IoC容器註冊BeanDefinition

            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());

        catch (BeanDefinitionStoreException var5) {

            this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);

        }

        //在BeanDefinition向IoC容器註冊完以後,傳送訊息

        this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));

    }

  

}

 

2. 開始分析

BeanDefinitionReaderUtil.registerBeanDefinition

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

    String beanName = definitionHolder.getBeanName();

    //註冊BeanDefinition

    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    String[] aliases = definitionHolder.getAliases();

    if (aliases != null) {

        String[] var4 = aliases;

        int var5 = aliases.length;

 

        for(int var6 = 0; var6 < var5; ++var6) {

            String aliase = var4[var6];

            registry.registerAlias(beanName, aliase);

        }

    }

}

DefaultListableBeanFactory. registerBeanDefinition

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 var7) {

            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var7);

        }

    }

 

    Map var3 = this.beanDefinitionMap;

    //註冊的過程需要synchronized,保證資料的一致性

    synchronized(this.beanDefinitionMap) {

        //這裡檢查是不是有相同名字的BeanDefinition已經在IoC容器中註冊了,如果有相同的名字BeanDefinition,但是又不允許覆蓋,那麼會丟擲異常

        BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);

        if (oldBeanDefinition != null) {

            if (!this.allowBeanDefinitionOverriding) {

                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");

            }

 

            if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {

                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 (this.logger.isInfoEnabled()) {

                this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");

            }

        else {

            //這是正常註冊BeanDefinition的過程,把Bean的名字存入到beanDefinitionNames的同時,把beanName作為Map的Key,把beanDefinition作為value存入到IoC容器持有的

            //beanDefinitionMap中

            this.beanDefinitionNames.add(beanName);

            this.frozenBeanDefinitionNames = null;

        }

        //這裡是個Map<String,BeanDefinition>,在DefaultListableBeanFactory中,由此也能看出IoC容器中持有一個Map

        this.beanDefinitionMap.put(beanName, beanDefinition);

    }

 

    this.resetBeanDefinition(beanName);

}

 

3. 流程圖分析

 

4. 總結

這個階段比較容易,不過是把解析好的BeanDefinition放如IoC容器中的Map當中即可