在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, &quot;Bean name must not be empty&quot;);
	Assert.notNull(beanDefinition, &quot;BeanDefinition must not be null&quot;);

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					&quot;Validation of bean definition failed&quot;, 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,
						&quot;Cannot register bean definition [&quot; + beanDefinition + &quot;] for bean '&quot; + beanName +
						&quot;': There is already [&quot; + oldBeanDefinition + &quot;] bound.&quot;);
			}
			else {
				if (this.logger.isInfoEnabled()) {
					this.logger.info(&quot;Overriding bean definition for bean '&quot; + beanName +
							&quot;': replacing [&quot; + oldBeanDefinition + &quot;] with [&quot; + beanDefinition + &quot;]&quot;);
				}
			}
		}
  //这是正常注册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);
}</code></pre>


  • 完成了BeanDefinition的注册,就完成了IoC容器的初始化过程。此时,在使用的IoC容器DefaultListableBean-Factory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,它们都在beanD-efinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。这些信息是容器建立依赖反转的基础。
posted @ 2019-01-26 00:47  WongJeffung  阅读(575)  评论(0编辑  收藏  举报