看這篇文章以前能夠先了解以前的跟蹤流程,https://www.jianshu.com/p/4934233f0eadjava
代碼過寬,能夠shift + 鼠標滾輪 左右滑動查看web
AbstractApplicationContext類中refresh()方法的第一個調用方法prepareRefresh()的跟蹤。spring
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 準備上下文的刷新 prepareRefresh(); ··· }
直接進入。app
prepareRefresh方法在AbstractApplicationContext類中,此類是XmlWebApplicationContext的上層父類ide
// 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 方法在 AbstractApplicationContext 中默認不作任何事情,具體業務流程由其子類覆蓋完成,也就是在 AbstractRefreshableWebApplicationContext 類中進行,AbstractRefreshableWebApplicationContext 是XmlWebApplicationContext的父類ui
// 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的方法this
env(也就是environment對象)調用了initPropertySources方法,該方法的具體實現由ConfigurableWebEnvironment的子類StandardServletEnvironment進行。code
environment對象是StandardServletEnvironment類的實例。orm
//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