看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead

代码过宽,可以shift + 鼠标滚轮 左右滑动查看

AbstractApplicationContext类中refresh()方法的第一个调用方法prepareRefresh()的跟踪。

@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing.
// 准备上下文的刷新
prepareRefresh();
···
}

直接进入。

prepareRefresh(零)

prepareRefresh方法在AbstractApplicationContext类中,此类是XmlWebApplicationContext的上层父类

// Prepare this context for refreshing.
// 准备 context 的刷新
prepareRefresh(); /**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*
* 准备 context 的刷新,设置他的启动数据、激活标志以及执行一些属性源的初始化
*/
protected void prepareRefresh() { // 启动时间
this.startupDate = System.currentTimeMillis(); // 此 context 是否已经被关闭
this.closed.set(false); // active 表示这个 context 当前是否处于活跃状态
this.active.set(true); if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
} // Initialize any placeholder property sources in the context environment // 1.在 context 的 environment 中初始化占位符属性源
initPropertySources(); // Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties // 验证所有被标记为必要的属性是否可解析,如果有遗失属性则不能解析并抛出异常,
// 可以参考setRequiredProperties方法
getEnvironment().validateRequiredProperties(); // Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available... // 一旦有可利用的广播,允许早期的ApplicationEvents集合被发布
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

1.initPropertySources

跟踪标记1的方法

initPropertySources 方法在 AbstractApplicationContext 中默认不做任何事情,具体业务流程由其子类覆盖完成,也就是在 AbstractRefreshableWebApplicationContext 类中进行,AbstractRefreshableWebApplicationContext 是XmlWebApplicationContext的父类

// Initialize any placeholder property sources in the context environment
// 1.在 context environment 中初始化占位符属性源
initPropertySources(); /**
* {@inheritDoc}
* <p>Replace {@code Servlet}-related property sources.
*
* 替换Servlet相关的属性源
*/
@Override
protected void initPropertySources() { // 在设置 root web application context 的 contextConfigLocation 属性时,已经调用过此方法。
// 在ContextLoader类中的configureAndRefreshWebApplicationContext方法中,
// 又调用了 initPropertySources 方法对 environment 进行了初始化
// 此时 environment 已存在,直接返回。
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) { // 1.1初始化属性源
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig);
}
}

1.1 initPropertySources

跟踪标记1.1的方法

env(也就是environment对象)调用了initPropertySources方法,该方法的具体实现由ConfigurableWebEnvironment的子类StandardServletEnvironment进行。

environment对象是StandardServletEnvironment类的实例。

//1.1初始化属性源
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig); /**
* Replace any {@linkplain
* org.springframework.core.env.PropertySource.StubPropertySource stub property source}
* instances acting as placeholders with real servlet context/config property sources
* using the given parameters.
*
* 用真正的servlet context/config 属性源来替换作为占位符存在的 stub 属性源
*/
@Override
public void initPropertySources(ServletContext servletContext, ServletConfig servletConfig) { // 工具类来初始化属性源,进入这个方法
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
} /**
* Replace {@code Servlet}-based {@link StubPropertySource stub property sources} with
* actual instances populated with the given {@code servletContext} and
* {@code servletConfig} objects.
* <p>This method is idempotent with respect to the fact it may be called any number
* of times but will perform replacement of stub property sources with their
* corresponding actual property sources once and only once.
*
* 用<由servletContext和servletConfig对象填充的>实例去替换基于servlet的 stub 属性源。
* 这个方法幂等遵守这个情况:他可能被调用任意次数,但是有且仅会执行一次 stub 属性源与它所匹配
* 的实际属性源的替换
*/
public static void initServletPropertySources(
MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) { Assert.notNull(propertySources, "'propertySources' must not be null"); // 此条件第三项不通过。
// 在ContextLoader类的configureAndRefreshWebApplicationContext方法中
// 已调用过一次StandardServletEnvironment对象的initPropertySources方法,
// 完成了根属性源的替换,所以第三项不再通过
if (servletContext != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) &&
propertySources.get(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext));
} //此处servletConfig为空,所以跳过
if (servletConfig != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) &&
propertySources.get(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig));
}
}

prepareRefresh方法只有这么多,接下来跟踪obtainFreshBeanFactory方法:

https://www.jianshu.com/p/144af98965d9

总结

  • 设置 context 关闭状态、激活标志等
  • 在 context 的 environment 中初始化占位符属性源,用真正的servlet context/config 属性源来替换作为占位符存在的 stub 属性源
  • 验证所有被标记为必要的属性是否可解析

最新文章

  1. 【BZOJ 1061】【Vijos 1825】【NOI 2008】志愿者招募
  2. Sublime text追踪函数插件:ctags
  3. URL验证
  4. Sass学习之路(2)——Sass环境安装(windows版)
  5. codevs3031 最富有的人
  6. 获取MSSQL Server中的相关信息(视图、存储过程、触发器、表)
  7. Codeforces Round #367 (Div. 2)---水题 | dp | 01字典树
  8. React Native技术知识总结(不定期补充)
  9. Java JSON数据处理
  10. kuangbin 基础DP集合
  11. 特殊篮子问题——C语言暴力破解
  12. 使用 Navicate 连接 Oracle9i 数据库
  13. es6 数组实例的 find() 和 findIndex()
  14. 开发工具-Eclipse
  15. python + pyqt5 QlineEdit QMessageBox实现信息录入和消息弹框提醒
  16. vue-router配置之通用路径
  17. IO流-递归遍历目录下指定后缀名结尾的文件名称
  18. 开启Tomcat APR运行模式,优化并发性能
  19. DDD精彩
  20. 再谈hive-1.0.0与hive-1.2.1到JDBC编程忽略细节问题

热门文章

  1. 前端学习 之 JavaScript 之 JSON
  2. selenium webdriver 操作RadioButton
  3. ubuntu13.10设置永久静态IP重启不失效
  4. MySQL之可视化软件
  5. js中的原生Ajax和JQuery中的Ajax
  6. php实现简单链式操作mysql数据库类
  7. 设计模式课程 设计模式精讲 14-2 组合模式coding
  8. Python 爬取 北京市政府首都之窗信件列表-[数据处理]
  9. LeetCode刷题--21.合并两个有序链表(简单)
  10. nmap 速查命令