Spring源码--IOC容器实现(4)--BeanDefinition的注册

在上一篇文章中,分析了BeanDefinition在IOC容器中载入和解析的过程。

BeanDefinition载入和解析

在这些动作完成之后,用户定义的BeanDefinition信息已经在IOC容器内建立了自己的数据结构以及

相应的数据表示,但此时这些数据不能供IOC容器直接使用,需要在IOC容器中对这些BeanDefinition

数据进行注册。这个注册为IOC容器提供了更友好的使用方式,在DefaultListableBeanFactory中,

是通过一个HashMap来持有载入的BeanDefinition的,这个HashMap的定义如下:

/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

下面分析BeanDefinition如何注册到HashMap的。

从上一篇文章的BeanDefinition()处理开始看看IOC容器如何注册BeanDefinition。

DefaultBeanDefinitionDocumentReader.processBeanDefinition()源码:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	/**
	  * BeanDefinitionHolder是对BeanDefinition对象的封装,封装了BeanDefinition、Bean的名字和别名。
 	  * 用来完成想IOC容器注册。得到BeanDefinitionHolder就意味着是通过BeanDefinitionParserDelegate
	  * 对XML元素的信息按照Spring的Bean规则进行解析得到的。
	  *
	  */
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// Register the final decorated instance.
			// 这里是向IOC容器注册解析得到的BeanDefinition的地方
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		// Send registration event.
		// 在BeanDefinition向IOC容器注册以后,发送消息
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

BeanDefinition注册在BeanDefinitionReaderUtils.registerBeanDefinition()方法中完成。

BeanDefinitionReaderUtils.registerBeanDefinition()方法源码:

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

   // Register bean definition under primary name.
   // 根据定义的唯一的beanName注册Beandefinition
   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 alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

注册registerBeanDefinition()方法的具体实现在BeanDefinitionRegistry接口的实现类DefaultListableBeanFactory

中来完成。

DefaultListableBeanFactory.registerBeanDefinition()方法源码:

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {
  // BeanName和BeanDefinition不能为空,否则停止注册
   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;
  // 检查是否有相同名字的BeanDefinition已经在IOC容器中注册了,如果有同名的BeanDefinition,
   // 但又不允许覆盖,就会抛出异常,否则覆盖BeanDefinition。
   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 {
      // 检查下容器是否进入了Bean的创建阶段,即是否同时创建了任何bean
      if (hasBeanCreationStarted()) { // 已经创建了Bean,容器中已经有Bean了,是在启动注册阶段创建的。
         // 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;
   }
  // 重置所有已经注册过的BeanDefinition或单例模式的BeanDefinition的缓存
   if (oldBeanDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
}

到这里完成了BeanDefinition的注册,就算完了IOC容器的初始化过程。此时,在使用的IOC容器

DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经

可以被容器使用了,它们都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息

进行处理和维护。这些信息就是容器建立依赖反转的基础,有了这些基础数据,就可以进一步完成

依赖注入,下一篇讨论依赖注入的实现原理。

参考文献:

1、《Spring技术内幕》

2、《Spring实战》

3、Spring官网API

4、Spring源码

猜你喜欢

转载自blog.csdn.net/yhl_jxy/article/details/81035291