private static class ServletConfigPropertyValues extends MutablePropertyValues {
/** * Create new ServletConfigPropertyValues. * @param config the ServletConfig we'll use to take PropertyValues from * @param requiredProperties set of property names we need, where * we can't accept default values * @throws ServletException if any required properties are missing */ public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) throws ServletException { // 获得缺失的属性的集合 Set<String> missingProps = (!CollectionUtils.isEmpty(requiredProperties) ? new HashSet<>(requiredProperties) : null);
// Fail if we are still missing properties. // <2> 如果存在缺失的属性,抛出 ServletException 异常 if (!CollectionUtils.isEmpty(missingProps)) { throw new ServletException( "Initialization from ServletConfig for servlet '" + config.getServletName() + "' failed; the following required properties were missing: " + StringUtils.collectionToDelimitedString(missingProps, ", ")); } }
// 打日志 if (logger.isDebugEnabled()) { String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data"; logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value); }
// 打日志 if (logger.isInfoEnabled()) { logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms"); } }
// <2> 获得 WebApplicationContext wac 变量 WebApplicationContext wac = null; // 第一种情况,如果构造方法已经传入 webApplicationContext 属性,则直接使用 if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it // 赋值给 wac 变量 wac = this.webApplicationContext; // 如果是 ConfigurableWebApplicationContext 类型,并且未激活,则进行初始化 if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // 未激活 // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc // 设置 wac 的父 context 为 rootContext 对象 if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } // 配置和初始化 wac configureAndRefreshWebApplicationContext(cwac); } } } // 第二种情况,从 ServletContext 获取对应的 WebApplicationContext 对象 if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id wac = findWebApplicationContext(); } // 第三种,创建一个 WebApplicationContext 对象 if (wac == null) { // No context instance is defined for this servlet -> create a local one wac = createWebApplicationContext(rootContext); }
// <3> 如果未触发刷新事件,则主动触发刷新事件 if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. onRefresh(wac); }
// <4> 将 context 设置到 ServletContext 中 if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); }
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) { // <1> 如果 wac 使用了默认编号,则重新设置 id 属性 if (ObjectUtils.identityToString(wac).equals(wac.getId())) { // The application context id is still set to its original default value // -> assign a more useful id based on available information // 情况一,使用 contextId 属性 if (this.contextId != null) { wac.setId(this.contextId); // 情况二,自动生成 } else { // Generate default id... wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName()); } }
// <4> TODO 芋艿,暂时忽略 // The wac environment's #initPropertySources will be called in any case when the context // is refreshed; do it eagerly here to ensure servlet property sources are in place for // use in any post-processing or initialization that occurs below prior to #refresh ConfigurableEnvironment env = wac.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig()); }