Spring源码学习【二】IOC容器的初始化(三)BeanDefinition注册

目录

一、总览

二、源码分析


一、总览

经过以上的分析,我们知道Document中BeanDefinition的解析是在DefaultBeanDefinitionDocumentReader中进行的,让我们回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法中,继续分析BeanDefinition解析后的注册过程。在processBeanDefinition方法中,我们可以看到这样一句代码:

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

这里的处理就是将解析得到的BeanDefinition注册到bean工厂中,下面我们来看一看具体的源码。

二、源码分析

BeanDefinitionReaderUtils.registerBeanDefinition源码如下所示:

public class BeanDefinitionReaderUtils {

    public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        // 注册BeanDefinition
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // 为bean name注册别名
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }
}

BeanDefinitionRegistry是一个接口,其中定义了一系列与BeanDefinition注册相关的方法,代码如下:

public interface BeanDefinitionRegistry extends AliasRegistry {

   /**
    * 以beanName注册一个beanDefinition
    */
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefini-tionStoreException;

   /**
    * 移除beanDefinition
    */
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

   /**
    * 获取beanDefinition
    */
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

   /**
    * 检查是否存在以beanName为名的beanDefinition
    */
   boolean containsBeanDefinition(String beanName);

   /**
    * 获取所有beanDefinition的名称
    */
   String[] getBeanDefinitionNames();

   /**
    * 获取beanDefinition数目
    */
   int getBeanDefinitionCount();

   /**
    * 检查给定的beanName是否已使用
    */
   boolean isBeanNameInUse(String beanName);

}

在我们之前分析的FileSystemXmlApplicationContext中,实际上就是以DefaultListableBeanFactory作为基本的IOC容器的,DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,registry.registerBeanDefinition实际调用了DefaultListableBeanFactory中实现的registerBeanDefinition方法,如下:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements Con-figurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
   /** 持有beanDefinition的HashMap */
   private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

   /** 以注册顺序保存BeanDefinition名称 */
   private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

   /** 以注册顺序保存手动注册的单例名称 */
   private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

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

      // 验证beanDefinition,主要是验证beanDefinition重写的方法
      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);
      // 已存在beanDefinition
      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()) {
            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 + "]");
            }
         }
         // 注册BeanDefinition
         this.beanDefinitionMap.put(beanName, beanDefinition);
      }
      else { // 不存在同名beanDefinition,进行注册
         // 判断是否已经开始创建Bean,当getBean时则会开始创建Bean,为保证数据一致,需要进行同步处理
         if (hasBeanCreationStarted()) {
            synchronized (this.beanDefinitionMap) { // 同步锁
               this.beanDefinitionMap.put(beanName, beanDefinition);
               List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
               updatedDefinitions.addAll(this.beanDefinitionNames);
               updatedDefinitions.add(beanName);
               this.beanDefinitionNames = updatedDefinitions;
               if (this.manualSingletonNames.contains(beanName)) {
                  Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                  updatedSingletons.remove(beanName);
                  this.manualSingletonNames = updatedSingletons;
               }
            }
         }
         else { // 容器还在启动过程中,未开始创建Bean,直接注册BeanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
         }
         this.frozenBeanDefinitionNames = null;
      }
      // 如果当前beanDefinition覆盖了原有的beanDefinition或手动注册的单例
      // 则重置给定名称的beanDefinition的缓存和以该bean为双亲的beanDefinition
      if (oldBeanDefinition != null || containsSingleton(beanName)) {
         resetBeanDefinition(beanName);
      }
   }
}

到这里,BeanDefinition的注册就完成了,DefaultListableBeanFactory中通过Map持有BeanDefinition,这样BeanDefinition就在IOC容器中建立了相应的数据结构,但这些BeanDefinition还是相互独立的,下面就需要进行一步重要的处理:依赖注入。

猜你喜欢

转载自blog.csdn.net/greedystar/article/details/81205709