spring中xml标签加载解析的一般过程

本文详细解析了Spring框架中默认标签的解析流程,包括element元素的解析、bean定义的装饰、注册以及事件传递的过程。主要内容涉及BeanDefinitionHolder、BeanDefinitionParserDelegate、BeanDefinitionReaderUtils等关键类的作用,以及如何通过NamespaceHandler处理命名空间修饰。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

默认标签的解析过程:

DefaultBeanDefinitonDocumentReader class中processBeanDefinition

(1)     该方法先解析element元素获得BeanDefinitionHolder,

(2)     由BeanDefintionParserDelegate对于holder进行装饰加工

(3)     由BeanDefinitionReaderUtils.registerBeanDefinition对于holder进行注册

(4)     之后发送注册事件getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder))

其中主要的方法如下:

protected voidprocessBeanDefinition(Elementele,BeanDefinitionParserDelegate delegate) {

      BeanDefinitionHolderbdHolder= delegate.parseBeanDefinitionElement(ele);//(1)

      if (bdHolder != null) {

         bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//(2)

         try {

            // Register the final decorated instance.

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

         }

         catch(BeanDefinitionStoreException ex) {

            getReaderContext().error("Failed to register bean definition with name'" +

                   bdHolder.getBeanName() + "'", ele, ex);

         }

         // Send registration event.

         getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder));//(4)

      }

   }

下面细节介绍首先是

(1)  对于element元素的解析

BeanDefinitionHolder bdHolder=delegate.parseBeanDefinitionElement(ele);   

delegate:BeanDefinitionParserDelegate该类主要是完成对于element的解析工作,位于org.springframework.beans.factory.xml包下

public BeanDefinitionHolder parseBeanDefinitionElement(Elementele){

      returnparseBeanDefinitionElement(ele, null);

}

该方法提供解析element,如果解析出错会返回一个null。

它调用如下的方法进行解析,string id ID_ATTRIBUTE 指的是常亮字符“id”<bean id>这里面的,name也是类似。

public BeanDefinitionHolder parseBeanDefinitionElement(Elementele,BeanDefinition containingBean) {

//对应id name 等标签

      Stringid = ele.getAttribute(ID_ATTRIBUTE);

      StringnameAttr= ele.getAttribute(NAME_ATTRIBUTE);

      List<String>aliases= newArrayList<String>();

      if (StringUtils.hasLength(nameAttr)) {

         String[]nameArr= StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);

         aliases.addAll(Arrays.asList(nameArr));

      }

      StringbeanName= id;

      if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {

         beanName = aliases.remove(0);

         if (logger.isDebugEnabled()) {

            logger.debug("No XML 'id' specified - using '" + beanName+

                   "' as bean name and "+ aliases+ " as aliases");

         }

      }

      if (containingBean == null) {

         checkNameUniqueness(beanName, aliases, ele);

      }

      //解析的BeanDefinition放到GenericBeanDefintion中

      AbstractBeanDefinitionbeanDefinition= 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);

                   StringbeanClassName= beanDefinition.getBeanClassName();

                   if (beanClassName != null &&

                         beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length()&&

                         !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {

                      aliases.add(beanClassName);

                   }

                }

                if (logger.isDebugEnabled()) {

                   logger.debug("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;

   }

 

(a)其中调用spring框架中的StringUtils类,并使用Java.util.StringTokenizer类进行字符串分割获得有用数据,然后添加到alisases:list中;

(b)先删除掉该beanName(id),然后再检测在当前的beandefinition nest中没有使用该bean,然后解析。

(c)  AbstractBeanDefinition beanDefinition =parseBeanDefinitionElement(ele, beanName,containingBean);

获得一个beandefinition,只不过这里将该对象引用给了它的抽象的父类,

该方法首先是

This.parseState.push(newBeanEntry(beanName));

 new  BeanEntry(String beanName)是beanEntry的一个构造方法,该类主要表示一个BeanDefinition 。


BeanDefinition是一个接口,其中定义了一些在xml中,bean<bean>定义的标签的对应的属性,其中有我们熟悉的lazyInit,

 

public interfaceBeanDefinition extends AttributeAccessor, BeanMetadataElement {

   StringSCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

   StringSCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

int ROLE_APPLICATION = 0;

   int ROLE_SUPPORT= 1;

   int ROLE_INFRASTRUCTURE= 2;

   StringgetParentName();

   void setParentName(String parentName);

   StringgetBeanClassName();

   void setBeanClassName(StringbeanClassName);

   StringgetFactoryBeanName();

   voidsetFactoryBeanName(String factoryBeanName);

   StringgetFactoryMethodName();

   voidsetFactoryMethodName(String factoryMethodName);

   StringgetScope();

   void setScope(String scope);

   boolean isLazyInit();

   void setLazyInit(boolean lazyInit);

   String[]getDependsOn();

   void setDependsOn(String[] dependsOn);

   boolean isAutowireCandidate();

   void setAutowireCandidate(boolean autowireCandidate);

   boolean isPrimary();

   void setPrimary(boolean primary);

   ConstructorArgumentValuesgetConstructorArgumentValues();

   MutablePropertyValuesgetPropertyValues();

   boolean isSingleton();

   boolean isPrototype();

   boolean isAbstract();

   int getRole();

   StringgetDescription();

   StringgetResourceDescription();

   BeanDefinitiongetOriginatingBeanDefinition();

 

}

AbstractBeanDefintion则是对于BeanDefinition接口的实现类,实现了其中操作属性的方法,可以将<bean> 中属性加载到该类中,是xml文件的一种对象转换。

 

之后className = ele.getAttribute(CLASS_ATTRIBUTE).trim();获得其classname.

并获得其父类string parent,然后用

AbstractBeanDefinition db =creatBeanDefinition(className,parent);

创建出beandefinition,该create方法则是利用了BeanDefinitionReaderUitls工具类的createBeanDefinition(parentName,className,this.readerContext.getBeanClassLoader())实现的,具体如下:

public staticAbstractBeanDefinitioncreateBeanDefinition(

         StringparentName,String className,ClassLoader classLoader)throwsClassNotFoundException {

      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;

   }

之后是:

public AbstractBeanDefinition parseBeanDefinitionElement(

         Elementele,String beanName,BeanDefinition containingBean) {

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

      StringclassName= null;

      if (ele.hasAttribute(CLASS_ATTRIBUTE)){

         className = ele.getAttribute(CLASS_ATTRIBUTE).trim();

      }

      try {

         Stringparent= null;

         if (ele.hasAttribute(PARENT_ATTRIBUTE)){

            parent = ele.getAttribute(PARENT_ATTRIBUTE);

         }

         AbstractBeanDefinitionbd =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;

      }……

接着是如上的解析beandefinition的属性,设置description,解析metaelements,并且解析subElements,解析替代方法子元素parseReplacedMethodSubElements,解析构造器中参数elements,解析属性elements,设置资源等等。

然后返回到parseBeanDefinitionElement():,这些解析的具体的内容可以参考郝佳编著的《spring源码深度解析》中第三章的内容。BeanDefintionParseDelegate中继续执行,

最后将这个beandefinition和beanname都放到beandefinitionholder中,返回。即返回到DefaultBeanDefinitionDocumentReader类下的processBeanDefintion()方法。

(2)  对于holder进行修饰(装饰)

bdHolder= delegate.decorateBeanDefinitionIfRequired(ele,bdHolder);

里面利用了NamespaceHandler,命名空间的修饰,是不是默认的标签还是用户自定义的,可以通过其内容之进行判断。默认的标志为"http://www.springframework.org/schema/beans"

,其他用户自定义的标签由相应的NamespaceHandler进行处理。

 

(3)  注册最终的装饰后的bdholder类,

// Register the final decorated instance.

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

使用相应的beandefinitionfactory进行相应的holder注册

public staticvoidregisterBeanDefinition(

         BeanDefinitionHolderdefinitionHolder,BeanDefinitionRegistry registry)

         throwsBeanDefinitionStoreException {

 

      // Register bean definition under primary name.

      StringbeanName= 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);

         }

      }

   }

DefaultListBeanFactory中有一个实现了registryBeanDefinition()的方法,可以参考。一种是通过beanName注册,另外一种是通过alias别名进行注册。

beanName注册是将BeanName和BeanDefinition一起以Map <key value>形式加入到BeanDefintionMap中,其步骤为

(a1)进行一些验证(方法属性是否有);

(a2)然后判断是否可以覆盖,不可则抛出异常;

(a3)然后添加beanName到map中;

(a4)最后则是重置所有对应的缓存。

存在于DefaultListableBeanFactory中:

   public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

         throwsBeanDefinitionStoreException {

      Assert.hasText(beanName, "Bean name must not be empty");

      Assert.notNull(beanDefinition, "BeanDefinition must not be null");

      if (beanDefinition instanceofAbstractBeanDefinition) {

         try {

            ((AbstractBeanDefinition)beanDefinition).validate();

         }

         catch(BeanDefinitionValidationException ex) {

            throw newBeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

                   "Validation of bean definition failed", ex);

         }

      }

 

      BeanDefinitionoldBeanDefinition;

 

      synchronized (this.beanDefinitionMap){

         oldBeanDefinition= this.beanDefinitionMap.get(beanName);

         if (oldBeanDefinition!= null){

            if (!this.allowBeanDefinitionOverriding) {

                throw newBeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,

                      "Cannot register bean definition [" + beanDefinition+ "] for bean '" + beanName+

                      "': There is already ["+ oldBeanDefinition+ "] bound.");

            }

            else {

                if (this.logger.isInfoEnabled()) {

                   this.logger.info("Overriding bean definition for bean '" + beanName+

                         "': replacing ["+ oldBeanDefinition+ "] with [" + beanDefinition+ "]");

                }

            }

         }

         else {

            this.beanDefinitionNames.add(beanName);

            this.frozenBeanDefinitionNames= null;

         }

         this.beanDefinitionMap.put(beanName, beanDefinition);

      }

 

      if (oldBeanDefinition!= null|| containsSingleton(beanName)) {

         resetBeanDefinition(beanName);

      }

   }

 

 

通过alias别名注册的情况则是SimpleAliasRegistry中的实现了该方法:

public voidregisterAlias(String name, String alias){

      Assert.hasText(name, "'name' must not be empty");

      Assert.hasText(alias, "'alias' must not be empty");

      if (alias.equals(name)) {

         this.aliasMap.remove(alias);

      }

      else {

         if(!allowAliasOverriding()) {

            StringregisteredName= this.aliasMap.get(alias);

            if (registeredName != null && !registeredName.equals(name)) {

                throw new IllegalStateException("Cannot register alias '" + alias+ "' for name '" +

                      name + "': It is already registered for name '" + registeredName+ "'.");

            }

         }

         checkForAliasCircle(name, alias);

         this.aliasMap.put(alias, name);

      }

   }

(b1)如果有alias别名和beanName相同的先从aliasmap中移除,

(b2)如果不允许相同别名的覆盖,则会抛出异常

(b3)检查是否有循环的情况A->B ,A->C->B的情况

(b4)将alias和name添加到别名map中

(4)注册事件传递(注册监听)// Send registration event.

         getReaderContext().fireComponentRegistered(newBeanComponentDefinition(bdHolder));

      readercontext中注册该监听事件

public voidfireComponentRegistered(ComponentDefinitioncomponentDefinition){

      this.eventListener.componentRegistered(componentDefinition);

   }

其中的参数可以是如下构造,显示本身,然后是内部的beandefinition和参考设置。

public BeanComponentDefinition(BeanDefinitionHolderholder){

      super(holder);

      findInnerBeanDefinitionsAndBeanReferences(holder.getBeanDefinition());

   }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值