Spring源码学习

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

a)Spring 初始化的时候首先要运行的类为: org.springframework.web.context. ContextLoaderListener 或 org.springframework.web.context. ContextLoaderServlet 。

它们在初始化函数里无一例外地实例化了 ContextLoader 类 , 然后调用了它的函数 public WebApplicationContext initWebApplicationContext(ServletContext ) 。

接下来看一下在这个方法里干了写什么

b)在他的方法体内,关键是“ this.context = createWebApplicationContext(servletContext, parent); ”新建了一个“ ConfigurableWebApplicationContext ”类型的对象,在这一步实例化中几乎完成了所有的 spring 初始化工作。读取了所有的 spring 配置文件。它的工作步骤如下所述。

c)首先,在将“ ConfigurableWebApplicationContext ”类型的对象实例化以后(这个对象实际的类型是这个包内的 XmlWebApplicationContext ),然后又给这个实例设置了三个属性,“ wac.setParent(parent); ”在默认的初始化过程中这一步设置了一个 null 值,然后又设置了一个“ wac.setServletContext(servletContext); ”,将系统默认的上下文设置进来,比较重要的是下面这一段:

if (configLocation != null) {

// 读取 spring 的应用配置文件

wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));

}

它将我们的配置文件名放置到 wac 变量中,以待在后续的操作中使用。然后调用 “ wac.refresh(); ”完成主要的初始化 BeanFactory 的操作。如下。

d)首先我们应该看一下我们实例化的对象

org.springframework.web.context.support.XmlWebApplicationContext 的类图:

20191102100692\_1.png

e)“ wac.refresh(); ”从类结构里我们能找到这个方法来自它的父类: AbstractApplicationContext 在它的 refresh() 方法内我们可以看到 spring 的复杂逻辑。

首先执行了 refreshBeanFactory(); (来自 AbstractRefreshableApplicationContext )见 f),

f)refreshBeanFactory(); 这个方法由负责维护变量 beanFactory 的子类 AbstractRefreshableApplicationContext 实现,默认情况下这个方法直接实例化一个新的 DefaultListableBeanFactory 类型的 BeanFacorty, 然后调用一个起缓冲作用的配置函数生成一个将 beanFacroty 包装起来的对象 beanDefinitionReader ,然后对这个对象进行属性配置,实际上该方法主要负责生成一个临时的操作对象,对应调用的函数为“ loadBeanDefinitions(beanFactory); ”该方法为初始化期间较为重要的一个。 该方法来自其子类: AbstractRefreshableWebApplicationContext 对应的函数:

protected void loadBeanDefinitions(DefaultListableBeanFactory) ,然后这里又调用了自己定义的 protected void loadBeanDefinitions(XmlBeanDefinitionReader) 方法。此时,它就使用到了在 c) 中设置了的( wac.setConfigLocations(……)) 我们开发中密切相关的配置文件。(同时也要记住此时这个函数的参数 beanDefinitionReader ,之前已经设置了“ beanDefinitionReader.setResourceLoader(this);”这里的 this 是我们在前面见到的 XmlWebApplicationContext(一个定义好了的上下文))。接着往下:

“ reader.loadBeanDefinitions(configLocations[i]); ” reader 开始加载我们配置文件内的东西了,不过真正复杂的实现此时才开始,我们继续往下走,在接下来的方法内默认情况下会执行:

if (resourceLoader instanceof ResourcePatternResolver) (该判断条件为 true ) , 由于从上面我们知道: beanDefinitionReader.setResourceLoader(this);而 this 的类型为: XmlWebApplicationContext所以 ((ResourcePatternResolver) resourceLoader).getResources(location);得到一个 Resource[] 数组,接下来调用:

int loadCount = loadBeanDefinitions(resources);该函数继续调用自己子类定义的一系列临时接口最终执行到 return doLoadBeanDefinitions(inputSource, encodedResource.getResource());在这个函数内初始化了处理 xml 文件的一些对象并将用户的配置文件解析为一个 Document 对象。然后又执行了一系列函数直到

return parser.registerBeanDefinitions(this, doc, resource);这个函数来自我们新建的 DefaultXmlBeanDefinitionParser ,在这个类里最终执行了对 xml 文件的解析工作和对 beanFacroty 变量执行了设置工作。

g)终于我们从这些繁杂的逻辑中跳了出来,继续执行 AbstractApplicationContext.refresh() 下面的工作,后续的代码主要仍旧是往一些常量里面设值。

此时 spring 初始化过程就结束了。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring源码学习

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏