4、BeanDefinition的构建和注册

前言

上篇文章我们讲到了processBeanDefinition(ele, delegate) 方法的源码:

//此方法需要两个参数:1.在之前解析的子节点element,2.解析器
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //此处将element对象解析成BeanDefinitionHolder对象,这个BeanDefinitionHolder就相当于对BeanDefinition做了一层包装。
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
       //如果bean标签中嵌套了自定义标签,那么就会经过此方法解析,对element进行再次解析,并封装成最终的bdHolder
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         //此处是注册BeanDdfinition,用BeanDefinitionReaderUtils工具类进行注册,并存储在一个Map中。
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // 此处是发布事件:整个spring容器注册完成之后,发布事件,通知spring容器,spring监听此事件,如果监听到了,进行后续处理
      //但是此方法是个空方法,这是spring容器给开发者留的一个扩展点。
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

这篇文章我们详细讲解一下这个源码中的 将element对象解析成BeanDefinitionHolder对象的过程

解析element对象,包装成BeanDefinitionHolder对象

展开讲解BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele) 的源码:

//先调用这里,然后走其重载方法
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
   return parseBeanDefinitionElement(ele, null);
}

//这是核心方法:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    //获取id属性
   String id = ele.getAttribute(ID_ATTRIBUTE);
   //获取name属性
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
   
   //获取别名,name属性可以定义多个值(以 逗号/分号 分隔),而只有第一个值会当作name的值,其余的值,会被当做别名处理
   List<String> aliases = new ArrayList<>();
   if (StringUtils.hasLength(nameAttr)) {
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
   }
    
   String beanName = id;
   //如果没有id属性,且别名不为空,那么就取别名的第一个值,作为bean的id值。
   if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      beanName = aliases.remove(0);
      if (logger.isTraceEnabled()) {
         logger.trace("No XML 'id' specified - using '" + beanName +
               "' as bean name and " + aliases + " as aliases");
      }
   }
   
   //containingBean是这个方法的重载方法调用,所以containingBean肯定为null,
   //此代码块的作用是检验beanName是否是唯一的。
   if (containingBean == null) {
      checkNameUniqueness(beanName, aliases, ele);
   }
   
   //这里是真正封装beanDefinition的逻辑。此处是核心代码。上面只解决了id和name的标签,还有很多其他标签,就是在此解决的。
   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   
   if (beanDefinition != null) {
       //下面这个if块是beanName没有的情况执行的,出现这种情况的原因是,<bean>标签中既没有id属性,也没有name属性。这种情况就按照自己默认算法帮忙生成一个
      if (!StringUtils.hasText(beanName)) {
         try {
             //此if块肯定不执行,执行else代码块
            if (containingBean != null) {
               beanName = BeanDefinitionReaderUtils.generateBeanName(
                     beanDefinition, this.readerContext.getRegistry(), true);
            } else {
               //
               beanName = this.readerContext.generateBeanName(beanDefinition);
               String beanClassName = beanDefinition.getBeanClassName();
               if (beanClassName != null &&
                     beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                     !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                  aliases.add(beanClassName);
               }
            }
            if (logger.isTraceEnabled()) {
               logger.trace("Neither XML 'id' nor 'name' specified - " +
                     "using generated bean name [" + beanName + "]");
            }
         }
         catch (Exception ex) {
            error(ex.getMessage(), ele);
            return null;
         }
      }
      String[] aliasesArray = StringUtils.toStringArray(aliases);
      //将BeanDefinition对象包装一层,返回一个BeanDefinitionHolder 对象。
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
   }

   return null;
}

接下来展开讲解AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean)源码:

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {

   this.parseState.push(new BeanEntry(beanName));
    
   //获取class属性
   String className = null;
   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
      className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
   }
   //获取parent属性
   String parent = null;
   if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
      parent = ele.getAttribute(PARENT_ATTRIBUTE);
   }
    
   try {
       //这里创建了一个基本为空的BeanDefinition,实际创建的是其实现类 GenericBeanDefinition
       //这里同时也set其父类的名字和set自己类的信息
      AbstractBeanDefinition bd = createBeanDefinition(className, parent);
       //这里解析了大部分的标签:singleton、scope、abstract、lazy-init、autowire、depends-on、primary、init-method 等等
      parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
      //添加一些说明文字
      bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
      //
      parseMetaElements(ele, bd);
      
      //这里解析lookup-method 标签,look-up method方法查找
      parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
      //这里解析replaced-method 标签,replace method方法替换
      parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
      //这里解析constructor-arg 标签
      parseConstructorArgElements(ele, bd);
      //这里解析property 标签,这个里面需要注意的是,spring将所有的property标签封装到了BeanDefinition中的PropertyValues属性中。
      parsePropertyElements(ele, bd);
      //这里解析qualifier 标签
      parseQualifierElements(ele, bd);
      //这里set源文件xml
      bd.setResource(this.readerContext.getResource());
      bd.setSource(extractSource(ele));
      return bd;
   }
   catch (ClassNotFoundException ex) {
      error("Bean class [" + className + "] not found", ele, ex);
   }
   catch (NoClassDefFoundError err) {
      error("Class that bean class [" + className + "] depends on not found", ele, err);
   }
   catch (Throwable ex) {
      error("Unexpected failure during bean definition parsing", ele, ex);
   }
   finally {
      this.parseState.pop();
   }
   return null;
}

将BeanDefinitionHolder对象进行注册(存储)

接下来讲解BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()) 源码:

//这个方法有两个参数:
//definitionHolder:这个就是被包装了一层的BeanDefinition对象
//registry:注册器
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
   //获取bean的名字
   String beanName = definitionHolder.getBeanName();
   //通过注册器,将BeanDefinition存储起来,此处是核心
   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);
      }
   }
}

接下来讲解registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()) 源码:

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块是做安全校验用的,不重要,略过
   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
      catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               "Validation of bean definition failed", ex);
      }
   }
   
   //这里是判断这个beanName是否已经注册过
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   //如果不为空,那就注册过。然后这里做一些相应的处理,不重要
   if (existingDefinition != null) {
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      else if (existingDefinition.getRole() < beanDefinition.getRole()) {
         // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
         if (logger.isInfoEnabled()) {
            logger.info("Overriding user-defined bean definition for bean '" + beanName +
                  "' with a framework-generated bean definition: replacing [" +
                  existingDefinition + "] with [" + beanDefinition + "]");
         }
      }
      else if (!beanDefinition.equals(existingDefinition)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Overriding bean definition for bean '" + beanName +
                  "' with a different definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Overriding bean definition for bean '" + beanName +
                  "' with an equivalent definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
       //此处校验这个工厂的bean是否已经开始进行注册阶段了,显然这里是还没有开始,所以会走else块,if块没啥用
      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;
            removeManualSingletonName(beanName);
         }
      }
      else {
         //注册/存储BeanDefinition,此处也是最关键的
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }

   if (existingDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
   else if (isConfigurationFrozen()) {
      clearByTypeCache();
   }
}

总结:

本片文章讲解了Spring默认标签的解析 ,构建,注册

下一篇文章我们将讲解Spring创建对象的流程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值