spring源码解读 spring如何读取xml文件

本例以spring中的 ClassPathXmlApplicationContext 为例 :

 1.介绍一下ClassPathXmlApplicationContext  : 从名字上就能看出这个applicationContext 是按照类路径读取文件的容器。如果想知道applicationContext 和 beanFactory 的区别请baidu,

 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("LetsGo-servlet.xml"); 通过重载最后会调用下面的构造方法:

   public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
               super(parent);
              setConfigLocations(configLocations);
               if (refresh) {
             refresh();
         }
  }

 

 这个方法是这个容器的初始化方法:spring内的容器初始化都依靠refresh()

  下面介绍一下refresh()方法 这个方法存在于AbstractApplicationContext 这个基类中


public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

......

    }


  重点关注obtainFreshBeanFactory()读取xml文件的步骤就是在初始换beanFactory中实现的
   
  protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
             //Tell the subclass to refresh the internal bean factory.
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;

}


  继续关注refreshBeanFactory();这个方法在AbstractApplicationContext 的子类AbstractRefreshableApplicationContext中

  

protected final void refreshBeanFactory() throws BeansException {

if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory(); 
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); // 重点
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}

}


  通过上段代码的createBeanFactory()可发现对于这个ClassPathXmlApplicationContext 实际底层运用的是 DefaultListableBeanFactory 这个容器。
  loadBeanDefinitions(beanFactory); 这个方法就是读取xml的关键:这个方法的实现方法在ClassPathXmlApplicationContext 的直接基类 AbstractXmlApplicationContext 中。

 

  protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {

// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
       ......
       ......
loadBeanDefinitions(beanDefinitionReader);

}


    从上段代码中我们能看出spring是使用XmlBeanDefinitionReader 去读取xml ,当然其他形式的配置文件,应该使用其他的reader,继续加载beanDefinitions,
   经过一些列的loadBeanDefinitions 最终实现在XmlBeanDefinitionReader的loadBeanDefinitions()

    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}

Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
    咱们的xml文件的形式由Resource -》encodedResource,InputSource 最终调用 doLoadBeanDefinitions(encodedResource,InputSource)方法
   把咱们的Resource 转化为 Document 。 至此spring 将一个外部xml文件转化为一个内部的document对象 ,详细解析步骤下次再研究。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值