BeanDefinitionHolder的创建

Spring框架中BeanDefinition的继承结构如下图:

Spring源码阅读——4

BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。<bean>元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit属性,BeanDefinition和<bean>中的属性是一一对应的。

在创建BeanDefinition时,可以生成RootBeanDefinition或者是GenericBeanDefinition或者ChildBeanDefinition的实例。但是现在大多数情况下都是创建GenericBeanDefinition的实例。

  • RootBeanDefinition:是最常用的实现类,它对应一般性的<bean>元素标签;
  • GenericBeanDefinition:是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类;
  • ChildBeanDefinition:在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而没有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。

在BeanDefinition的加载、解析、处理、注册过程中的处理阶段。需要创建一个BeanDefinitionHolder对象。其创建过程如下图所示:

  • DefaultBeanDefinitionDocumentReader类中的processBeanDefinition调用了代理创建BeanDefinitionHolder对象的方法

  • protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       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));
       }
    }

  • BeanDefinitionParserDelegate类中

    • @Nullable
      public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
         return parseBeanDefinitionElement(ele, null);
      }

    • @Nullable
      public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
         String id = ele.getAttribute(ID_ATTRIBUTE);
         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

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

         if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
         }

         //此处创建BeanDefinition对象
         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

         if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
               try {
                  if (containingBean != null) {
                     beanName = BeanDefinitionReaderUtils.generateBeanName(
                           beanDefinition, this.readerContext.getRegistry(), true);
                  }
                  else {
                     beanName = this.readerContext.generateBeanName(beanDefinition);
                     // Register an alias for the plain bean class name, if still possible,
                     // if the generator returned the class name plus a suffix.
                     // This is expected for Spring 1.2/2.0 backwards compatibility.
                     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);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
         }

         return null;
       

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

         this.parseState.push(new BeanEntry(beanName));

         String className = null;
         if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
         }
         String parent = null;
         if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
         }

         try {
           AbstractBeanDefinition bd = createBeanDefinition(className, parent);

            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

            parseMetaElements(ele, bd);
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

            parseConstructorArgElements(ele, bd);
            parsePropertyElements(ele, bd);
            parseQualifierElements(ele, bd);

            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;
      }

    • protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
            throws ClassNotFoundException {

         return BeanDefinitionReaderUtils.createBeanDefinition(
               parentName, className, this.readerContext.getBeanClassLoader());

      }

  • 在BeanDefinitionReaderUtils类中

    • 创建了BeanDefinition实例
    • public static AbstractBeanDefinition createBeanDefinition(
            @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader)
            throws ClassNotFoundException {

         GenericBeanDefinition bd = new GenericBeanDefinition();
         bd.setParentName(parentName);
         if (className != null) {
            if (classLoader != null) {
               bd.setBeanClass(ClassUtils.forName(className, classLoader));
            }
            else {
               bd.setBeanClassName(className);
            }
         }
         return bd;
      }

  • 以上就是在处理阶段如何创建BeanDefinition的部分

转载于:https://my.oschina.net/liyurong/blog/1930139

相关文章:

  • 2021-06-29
  • 2021-08-20
  • 2021-09-11
  • 2021-09-21
  • 2022-01-10
  • 2022-12-23
  • 2022-01-23
  • 2021-08-04
猜你喜欢
  • 2021-04-22
  • 2022-01-23
  • 2021-08-17
  • 2021-04-10
  • 2021-11-01
  • 2021-12-16
  • 2021-08-18
相关资源
相似解决方案