1. 程式人生 > >Spring IOC容器的初始化-(三)BeanDefinition的註冊

Spring IOC容器的初始化-(三)BeanDefinition的註冊

store erro pan customize 註冊 failed mono def override

---恢復內容開始---

前言

在上一篇中有一處代碼是BeanDefiniton註冊的入口,我們回顧一下。

1.BeanDefiniton在IOC容器註冊

首先我們回顧兩點,1. 發起註冊的地方;2. 註冊的實現類

1.發起註冊的地方

我們先看第一點,在上篇博文中我們講了Bean的解析,在DefaultBeanDefinitonDocumentReader類的processBeanDefiniton()方法中,其中一個是去完成BeanDefiniton的載入,另一個是完成註冊。我們看下代碼:

DefaultBeanDefinitionDocumentReader類的processBeanDefinition方法

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //解析方法
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); } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

現在我們找到了BeanDefiniton的註冊入口,我們知道BeanDefinitonHolder=BeanDefiniton+BeanName,來看下registerBeanDefinition的代碼:
BeanDefinitionReaderUtils類的registerBeanDefinition方法

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

        // 根據beanName註冊BeanDefinition
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // 如果有別名,註冊別名
String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }

2 註冊的實現類

我們找registerBeanDefinition的實現類,會發現有三個實現類,那麽具體取哪個呢?還記得我們最初容器建立的時候用的什麽容器嗎?我們回顧下代碼:

AbstractRefreshableApplicationContext類的refreshBeanFactory方法

protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

而且,我們看下DefaultListableBeanFactory實現了BeanDefinitionRegistry接口,這個接口就是定義註冊的。並且這個類中有這麽一個HashMap,存放beandefiniton的地方。

//---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------

    @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;

        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 + "]");
                }
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            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<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);
        }
    }

到這裏,代碼就完成了IOC容器的初始化過程。此時,在使用的IOC容器DefaultListableBeanFactory中已經建立了整個Bean的配置信息,而且這些BeanDefinition已經可以被容器使用了。他們都在beanDefinitionMap中被檢索和使用。

---恢復內容結束---

Spring IOC容器的初始化-(三)BeanDefinition的註冊