Spring源码解析之xml解析

Xml解析

首先进入AbstractApplicationContext的构造方法,追踪找到refresh()方法,这个方法是IOC容器初始化的核心方法。我们需要关注下obtainFreshBeanFactory()方法,主要是解析xml配置文件并封装成BeanDefinition对象

public void refresh() throws BeansException, IllegalStateException {
   
     ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 进去
     // ...
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   
   refreshBeanFactory(); // 进去
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   return beanFactory;
}

创建BeanFactory对象,它是DefaultListableBeanFactory类型。

// org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
   
   try {
   
      DefaultListableBeanFactory beanFactory = createBeanFactory(); // 创建BeanFactory对象
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory); // 进去
   }
}

接着把beanFactory委托(委托模式)给XmlBeanDefinitionReader对象去处理,这个reader对象主要用来加载所有的spring配置文件,接着reader把xml封装成document,交给(又是委托模式)BeanDefinitionDocumentReader对象去解析。spring配置文件中有两种类型的标签,一是默认标签,使用的默认命名空间,如<Bean/><import/><alias/>等,二是自定义标签,使用的自定义的命名空间,如<context:component-scan/>。解析xml的标签,会根据标签类型来决定走默认标签解析还是自定义标签解析。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 委托模式
   loadBeanDefinitions(beanDefinitionReader); // 进去,关注类似xxxBeanDefintions的方法
}

进入loadBeanDefinitions方法后,关注类似xxxBeanDefintions的方法,一直走下去,跳了n多层,果然大佬和我们不一样,如果是我,可能一个loadBeanDefinitions方法就搞定了。我们跳到了registerBeanDefinitions方法,这里又使用了委托模式,还是关注类似xxxBeanDefintions的方法

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

找到了parseBeanDefinitions方法,它会根据标签是默认标签还是自定义标签分别做不同处理。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   
   if (delegate.isDefaultNamespace(root)) {
   
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
   
         Node node = nl.item(i);
         if (node instanceof Element) {
   
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
   
               parseDefaultElement(ele, delegate); // 解析默认标签
            }
            else {
   
               delegate.parseCustomElement(ele); // 解析自定义标签
            }
         }
      }
   }
   else {
   
      delegate.parseCustomElement(root); // 解析自定义标签
   }
}
默认标签的解析

我们先看下默认标签解析,重点看下<bean/>标签的解析

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
   
      importBeanDefinitionResource(ele); //import标签解析
   }
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
   
      processAliasRegistration(ele); //alias标签解析
   }
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
   
      processBeanDefinition(ele, delegate); // 重点看bean标签的解析
   }
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
   
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

解析bean标签的属性,如id、name、class、parent、scope、abstract等属性,然后封装到BeanDefinition对象中,解析完毕,再封装成BeanDefinitionHolder对象。

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   
   // 解析并返回BeanDefinitionHolder
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
   
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); // 对BeanDefinitionHolder进行装饰,装饰者模式
      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));
   }
}

解析并返回BeanDefinitionHolder

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

   // ...
   // 进一步解析
   AbstractBeanDefinition beanDefinition 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值