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

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

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

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

直接进入。

prepareRefresh(零)

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

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

1.initPropertySources

跟踪标记1的方法

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

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

1.1 initPropertySources

跟踪标记1.1的方法

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

environment对象是StandardServletEnvironment类的实例。

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

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. php 基础知识 post 和get 两种传输方式的区别

    1.post更安全(不会作为url的一部分,不会被缓存.保存在服务器日志.以及浏览器浏览记录中) 2.post发送的数据量更大(get有url长度限制) 3.post能发送更多的数据类型(get只能发 ...

  2. 概念 - 抖脚(Fidgeting)

    参考 https://cn.nytimes.com/health/20161220/why-fidgeting-is-good-medicine/dual/ https://baike.baidu.c ...

  3. TimeSeriesEditor时间序列编辑软件之实战ReoGrid表格控件和Zedgraph绘图控件

    最近用ReoGrid表格控件和Zedgraph绘图控件写了一个TimeSeriesEditor时间序列编辑软件,如下图. 目的就是体验一下这两个空间的用法,感觉还是挺好用的, 关于软件的使用说明可以访 ...

  4. P1029最大公约数和最小公倍数

    P1029最大公约数和最小公倍数 #include <iostream> #include <cmath> #include <algorithm> #define ...

  5. RedHat OpenShift QuickStart 1.2

    一.在容器中传入/出文件 1. 创建一个初始化项目 oc login -u developer -p developer oc new-project myproject 2. 在容器中下载文件 先通 ...

  6. Maven项目-Tomcat - 方法无法为jsp编译类ClassFormatException的解决

    解决方法:

  7. Codeforces1300D. Aerodynamic

    本题题目有点绕,结合图例大概可知,P(x,y)是以点给出的一个凸包,T是一个点集合,也构成一个凸包,构成的方法就是将原点(0,0)在P(x,y)的边上跑,移动坐标轴,其构成的最远点是个凸包,我们可以画 ...

  8. django 模版内置的过滤器

    一.add 将传进来的参数添加到原来的值上面.这个过滤器会尝试将“值”和“参数”转换成整形然后进行相加.如果转换成整形过程中失败了,那么将会将“值”和“参数”进行拼接.如果是字符串,那么会拼接成字符串 ...

  9. js 表格操作----添加删除

    js 表格操作----添加删除 书名:<input type="text" id="name"> 价格:<input type="t ...

  10. Centos7 VNC远程桌面服务安装配置

    1.服务器版本 CentOS Linux release 7.7.1908 (Core) 首先系统安装了GUI界面 # ln -sf /lib/systemd/system/graphical.tar ...