看这篇文章之前可以先了解之前的跟踪流程,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 属性源
  • 验证所有被标记为必要的属性是否可解析

prepareRefresh方法源码跟踪的更多相关文章

  1. prepareRefresh()方法源码探究

    该方法目的是做刷新上下文前的准备工作: 首先清空bean扫描器map中的内容,然后调用父类的prepareRefresh方法: 父类的准备刷新方法,主要做了3个工作: 1.简单的标志赋值----> ...

  2. loadBeanDefinitions方法源码跟踪(一)

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractBeanDe ...

  3. postProcessBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  4. prepareBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  5. loadBeanDefinitions方法源码跟踪(三)

    因为字数超过了限制,所以分成了三篇,承接上篇: https://www.jianshu.com/p/46e27afd7d96 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 4.parseCus ...

  6. obtainFreshBeanFactory方法源码跟踪

    看这篇文章之前可以先了解之前的跟踪流程,https://www.jianshu.com/p/4934233f0ead 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 AbstractApplic ...

  7. loadBeanDefinitions方法源码跟踪(二)

    因为字数超过了限制,所以分成了三篇,承接上篇: https://www.jianshu.com/p/a0cfaedf3fc5 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 3.parseDef ...

  8. erlang下lists模块sort(排序)方法源码解析(一)

    排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...

  9. Java源码跟踪阅读技巧

    转:https://www.jianshu.com/p/ab865109070c 本文基于Eclipse IDE 1.Quick Type Hierarchy 快速查看类继承体系. 快捷键:Ctrl ...

随机推荐

  1. 理解API和SDK的区别

    API--功能的集成(封装等级低) SDK--任务的集成(封装等级高) 比如,App中完成微信支付.整个过程下来需要三次与微信服务器的访问,一次block回调.这四个步骤可以当作是4个api,如果把这 ...

  2. Do You Know These Plastic Bottle Processing Terms?

    The molding process of a plastic bottle refers to a process of making a final plastic article from a ...

  3. springboot 模板

    参考:https://blog.csdn.net/wangb_java/article/details/71775637

  4. python爬虫(七) mozillacookiejar

    MozillaCookiejar 保存百度得Cookiejar信息: from urllib import request from urllib import parse from http.coo ...

  5. IDEA启动项目的时候,控制台中显示的都是乱码

    解决办法: 找到intellij idea安装目录,bin文件夹下面idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,分别在这两个文件中添加:-Dfile.en ...

  6. Windows下载编译Qt5 Gui

    安装工具 Python 这个安装的时候没记录下来,网上查一下,大把, 就不补了. ActivePerl https://www.cnblogs.com/dilex/p/10591579.html 下载 ...

  7. Celeste 机制研究

    0. 简介.惯例.总论 Celeste (塞莱斯特) 是一个具有优秀手感的平台跳跃游戏. 虽然操作所使用的按键很少, 但是却有着复杂的组合机制. 在游戏实现上, Celeste 是一个锁定 60 帧 ...

  8. Day11 - L - 邂逅明下 HDU - 2897

    当日遇到月,于是有了明.当我遇到了你,便成了侣.那天,日月相会,我见到了你.而且,大地失去了光辉,你我是否成侣?这注定是个凄美的故事.(以上是废话)小t和所有世俗的人们一样,期待那百年难遇的日食.驻足 ...

  9. 122、Java面向对象之直接输出对象本身

    01.代码如下: package TIANPAN; class Book { public void print() { // 调用print()方法的对象就是当前对象,this就自动与此对象指向同一 ...

  10. System.Diagnostics.Conditional 的妙用 -- 把文档放在代码中

    最近的工作跟 UI 打交道比较多, 各种坑. 今天从 Prefab 的序列化功能来说说 System.Diagnostics.Conditional 的妙用. 我们做 UI 面对各种按钮, 组件的获取 ...