在IoC容器中的注册

概念

载入和解析Bean定义信息而得到BeanDefinition后,还需要将IoC容器注册这些BeanDefinition,才能让IoC容器使用。这个过程是通过调用BeanDefinitionRegistry接口的实现来完成的。通过分析,我们可以看到,在IoC容器内部将BeanDefinition注入到BeanFactory的一个HashMap中去,IoC容器就是通过这个HashMap来持有BeanDefinition数据的。


分析注册过程

  • 解析完<bean>后,将解析结果封装在BeanDefinitionHolder中,然后将其向容器进行注册。代码如下:

//DefaultBeanDefinitionDocumentReader的processBeanDefinition方法
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //对bean元素开始解析
    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));
        }
    }

//BeanDefinitionReaderUtils的registerBeanDefinition方法,这个BeanDefinitionRegistry是个接口
//DefaultListableBeanFactory实现了这个接口,在这里也就是之前创建的DefaultListableBeanFactory
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);
            }
        }
    }

//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 ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    //注册过程需要synchronized,保持数据一致性
        synchronized (this.beanDefinitionMap) {
      //这里检查是不是有相同名字的BeanDefinition已经在IoC容器中注册了,如果有相同名宇的
      //BeanDefinition,但又不允许搜盖,那么会抛出异常
            Object oldBeanDefinition = 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.");
                }
                else {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Overriding bean definition for bean '" + beanName +
                                "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                    }
                }
            }
      //这是正常注册BeanDefinition的过程,把Bean的名字存入到beanDefinitionNames的同时.把
      //beanName作为Map的key,把beanDefinition作为value存入到IoC容器持有的beanDefinitionMap中去
            else {
                this.beanDefinitionNames.add(beanName);
                this.frozenBeanDefinitionNames = null;
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }

        resetBeanDefinition(beanName);
    }


  • 完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时,在使用的IoC容器DefaultListableBean-Factory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,它们都在beanD-efinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。这些信息是容器建立依赖反转的基础。

猜你喜欢

转载自www.cnblogs.com/huangzefeng/p/10322416.html