Spring源码解读-XmlBeanDefinitionReader解析

本文深入剖析Spring框架中XML Bean定义的加载过程,详细解读从加载XML文件、解析Bean定义到注册Bean定义的全过程。重点讲解XmlBeanDefinitionReader、DefaultBeanDefinitionDocumentReader及BeanDefinitionParserDelegate类的角色与功能。
首先是加载XML文件:
   DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
   new XmlBeanDefinitionReader(factory).loadBeanDefinitions(RETURNS_NULL_CONTEXT);
其中RETURNS_NULL_CONTEXT为:
   Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");

    这一篇先分析XmlBeanDefinitionReader,所以讲factory看为register,就是给XmlBeanDefinitionReader读取Bean后,将Beandefinition保存的地方,一个BeanDefinition就是一个你在配置文件配置的Bean标签里的所有数据。

   直接Debug loadBeanDefinitions()方法, 

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   return loadBeanDefinitions(new EncodedResource(resource));
}

   其实将resource包一层的作用只是Spring对resource的统一封装,由名字可以知道,你可以指定编码去读取它。但所有Resource其实本质都可以看做是一个xml文件流。

  直接进入XmlBeanDefinitionReader类的loadBeanDefinitions方法,同样这个方法前面一部分以上对这个resource进行处理,我们直接找到

 doLoadBeanDefinitions(inputSource, encodedResource.getResource())进入这个方法:
   Document doc = doLoadDocument(inputSource, resource);
   return registerBeanDefinitions(doc, resource);

可以看到这个方法是将xml文件解析为一个Document文档,然后解析这个doc对象去获取我们的Bean信息,看registerBeanDefinitions方法:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   int countBefore = getRegistry().getBeanDefinitionCount();
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

 这里getRegistry()就是前面说的DefaultListableBeanFactory,也就是将从doc中解析的BeanDefinition注册到这个factory。

   这里主要会初始化一个DefaultBeanDefinitionDocumentReader

对象:

protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
   return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}

用这个DefaultBeanDefinitionDocumentReader去解析doc里面的节点内容。

  之后进入DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions方法,然后直接进入

doRegisterBeanDefinitions(Element root)方法,一个Element元素其实就是Beans标签的儿子节点的内容有bean标签,import标签等。在这个方法就有一个新对象:
 

protected void doRegisterBeanDefinitions(Element root) {
   BeanDefinitionParserDelegate parent = this.delegate;
   this.delegate = createDelegate(getReaderContext(), root, parent);

   //   校验格式  xmlns="http://www.springframework.org/schema/beans"
   if (this.delegate.isDefaultNamespace(root)) {
      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
      if (StringUtils.hasText(profileSpec)) {
         String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
               profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
         if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
            if (logger.isInfoEnabled()) {
               logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                     "] not matching: " + getReaderContext().getResource());
            }
            return;
         }
      }
   }

   preProcessXml(root);
   parseBeanDefinitions(root, this.delegate);
   postProcessXml(root);

   this.delegate = parent;
}

即BeanDefinitionParserDelegate,现在就是两个具体解析的关键类了DefaultBeanDefinitionDocumentReader、BeanDefinitionParserDelegate,这两个一个是解析Beans标签的儿子节点的,一个是解析儿子节点的具体内容的,

     

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {

   public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;

   public static final String NESTED_BEANS_ELEMENT = "beans";

   public static final String ALIAS_ELEMENT = "alias";

   public static final String NAME_ATTRIBUTE = "name";

   public static final String ALIAS_ATTRIBUTE = "alias";

   public static final String IMPORT_ELEMENT = "import";

   public static final String RESOURCE_ATTRIBUTE = "resource";

   public static final String PROFILE_ATTRIBUTE = "profile";
public class BeanDefinitionParserDelegate {

   public static final String TRUE_VALUE = "true";

   public static final String FALSE_VALUE = "false";

   public static final String DEFAULT_VALUE = "default";

   public static final String DESCRIPTION_ELEMENT = "description";

   public static final String AUTOWIRE_NO_VALUE = "no";

   public static final String AUTOWIRE_BY_NAME_VALUE = "byName";

   public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";

   public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";

   public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";

   public static final String NAME_ATTRIBUTE = "name";

   public static final String BEAN_ELEMENT = "bean";

   public static final String META_ELEMENT = "meta";

   public static final String ID_ATTRIBUTE = "id";

        等等。

    经过调用,我们来到DefaultBeanDefinitionDocumentReader类的:

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

在这里我们可以看到 delegate.parseBeanDefinitionElement(ele);即解析element产生一个BeanDefinitionHolder:

    

public class BeanDefinitionHolder implements BeanMetadataElement {

   private final BeanDefinition beanDefinition;

   private final String beanName;

   @Nullable
   private final String[] aliases;

  包含一个Bean产生的三个数据,即一个保存BeanDefinition,它保存这个bean标签的id、name、class属性等。还有用于注册到factory容器的key即beanName、aliases。

    然后,通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());注册

      进入方法registerBeanDefinition():

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

   // Register bean definition under primary name.
   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);
      }
   }
}

可以看到从BeanDefinitionHolder提取,Beandefinition、beanName、aliases去factory容器去注册。

                                                               完结

       

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值