SpringIOC源码解析(7)—— xml配置的资源定位、加载、解析、注册全链路分析

本文阅读 4 分钟
首页 代码,Java 正文

调用过程复现:

在DefaultListableBeanFactory的registerBeanDefinition里打上断点,运行Entrance,观察调用栈:

img

Entrance源码:阅读Spring源码第一步:源码编译与创建调试入口

注册是从主函数开始的: img 之后进入到FileSystemXmlApplicationContext的构造函数:

public FileSystemXmlApplicationContext(String configLocation) throws BeansException { 
   this(new String[] { configLocation}, true, null);
}

又调用了另外一个构造函数:

public FileSystemXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException { 

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) { 
      refresh();
   }
}

对应变量的值: img 其中configLocations是个数组,所以猜测最后调用了加载多个资源的方法。

又调用refresh()方法进行容器的初始化,此时又来到AbstractApplicationContext的refresh方法里: img

又调用了obtainFreshBeanFactory方法,跳进去会发现它是调用了子类的refreshBeanFactory方法,以刷新子类的容器

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 
   refreshBeanFactory();
   return getBeanFactory();
}

再往前进会发现实现refreshBeanFactory方法的是AbstractRefreshableApplicationContext类: img 先创建了容器实例,再将实例传入到loadBeanDefinitions里

进入到loadBeanDefinitions,该方法是由AbstractXmlApplicationContext实现的:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { 
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   // 为给定的BeanFactory创建一个新的XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   // 将容器本身"献祭"
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

img 先是定义了XmlBeanDefinitionReader的实例变量beanDefinitionReader,变量的构造函数便是传入的DefaultListableBeanFactory实例;

此外beanDefinitionReader还给自己的ResourceLoader设置上FileSystemXmlApplicationContext;

因此FileSystemXmlApplicationContext实例和DefaultListableBeanFactory实例便是通过beanDefinitionReader对象串联到了一起,这也就表明了打通了资源加载和BeanDefinition之间的通路。

再前进一步就是加载资源的配置流程了(AbstractXmlApplicationContext.java):

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { 
   Resource[] configResources = getConfigResources();
   if (configResources != null) { 
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();   // 从这里继续进
   if (configLocations != null) { 
      reader.loadBeanDefinitions(configLocations);
   }
}

进入到getConfigLocations方法里:

@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { 
   Assert.notNull(locations, "Location array must not be null");
   int count = 0;
   for (String location : locations) { 
      count += loadBeanDefinitions(location);
   }
   return count;
}

这里就是根据location来逐个调用loadBeanDefinitions去加载。

继续进到loadBeanDefinitions方法里: img 可以看到确实是使用了ResourcePatternResolver来进行加载的,和上面的推断一样是用可以同时加载多个资源的。

再进入两层到loadBeanDefinitions方法里: img 发现到了对resource包裹上EncodedResource这一步

再进入一层,此时就是对资源进行编码处理了: img

进入到实际干活的doLoadBeanDefinitions中: img 这里面主要就是将xml解析成document对象了,解析完成之后就进入到注册阶段

注册阶段: img先是将Document对象解析成一个个的BeanDifinitions img

继续进入到doRegisterBeanDefinitions里: img 就会发现这里开始解析BeanDefinition了,并且此处的delegate对象是BeanDefinitionParserDelegate对象

之后就会进入解析逻辑里面进行BeanDefinition的解析了: img 因为我们遵循的是xml定义的规范,所以会执行parseDefaultElement方法,方法之前已经分析过了,这一步会递归执行多次。

再往深一点就会看到调用了delegate的parseBeanDefinitionElement方法区解析出包含了BeanDefinition实例的BeanDefinitionHolder包装实例 img 之后就来到了 SpringIOC源码解析(5)—— BeanDefinition的注册中的BeanDefinition的注册环节了,最终将BeanDefinition实例注册到容器里,同时,如果BeanDefinition先前已经注册过了,就需要清空先前的注册信息,如果是单例,将先前已经创建出来的bean实例给清除掉,因为bean实例赖以生存的BeanDefinition已经改变了。

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://wangjiawei.blog.csdn.net/article/details/120926404
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复