前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入分析Spring 与 Spring MVC容器

深入分析Spring 与 Spring MVC容器

作者头像
用户1263954
发布2018-01-30 17:27:53
7450
发布2018-01-30 17:27:53
举报
文章被收录于专栏:IT技术精选文摘IT技术精选文摘

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {

//PS : ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE=WebApplicationContext.class.getName() + ".ROOT" 根上下文的名称

//PS : 默认情况下,配置文件的位置和名称是: DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"

//在整个web应用中,只能有一个根上下文

if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {

throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!");

}

Log logger = LogFactory.getLog(ContextLoader.class);

servletContext.log("Initializing Spring root WebApplicationContext");

if (logger.isInfoEnabled()) {

logger.info("Root WebApplicationContext: initialization started");

}

long startTime = System.currentTimeMillis();

try {

// Store context in local instance variable, to guarantee that

// it is available on ServletContext shutdown.

if (this.context == null) {

// 在这里执行了创建WebApplicationContext的操作

this.context = createWebApplicationContext(servletContext);

}

if (this.context instanceof ConfigurableWebApplicationContext) {

ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;

if (!cwac.isActive()) {

// The context has not yet been refreshed -> provide services such as

// setting the parent context, setting the application context id, etc

if (cwac.getParent() == null) {

// The context instance was injected without an explicit parent ->

// determine parent for root web application context, if any.

ApplicationContext parent = loadParentContext(servletContext);

cwac.setParent(parent);

}

configureAndRefreshWebApplicationContext(cwac, servletContext);

}

}

// PS: 将根上下文放置在servletContext中

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

ClassLoader ccl = Thread.currentThread().getContextClassLoader();

if (ccl == ContextLoader.class.getClassLoader()) {

currentContext = this.context;

} else if (ccl != null) {

currentContextPerThread.put(ccl, this.context);

}

if (logger.isDebugEnabled()) {

logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +

WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");

}

if (logger.isInfoEnabled()) {

long elapsedTime = System.currentTimeMillis() - startTime;

logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");

}

return this.context;

} catch (RuntimeException ex) {

logger.error("Context initialization failed", ex);

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);

throw ex;

} catch (Error err) {

logger.error("Context initialization failed", err);

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);

throw err;

}

}

protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {

//根据web.xml中的配置决定使用何种WebApplicationContext。默认情况下使用XmlWebApplicationContext

//web.xml中相关的配置context-param的名称“contextClass”

Class<?> contextClass = determineContextClass(sc);

if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {

throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");

}

//实例化WebApplicationContext的实现类

ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

// Assign the best possible id value.

if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {

// Servlet <= 2.4: resort to name specified in web.xml, if any.

String servletContextName = sc.getServletContextName();

if (servletContextName != null) {

wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName);

} else {

wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX);

}

} else {

// Servlet 2.5's getContextPath available!

wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + sc.getContextPath());

}

wac.setParent(parent);

wac.setServletContext(sc);

//设置spring的配置文件

wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));

customizeContext(sc, wac);

//spring容器初始化

wac.refresh();

return wac;

}

  1. ContextLoaderListener构建Root Context时序图:

protected WebApplicationContext initWebApplicationContext() {

//先从web容器的ServletContext中查找WebApplicationContext

WebApplicationContext wac = findWebApplicationContext();

if (wac == null) {

// No fixed context defined for this servlet - create a local one.

//从ServletContext中取得根上下文

WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

//创建Spring MVC的上下文,并将根上下文作为起双亲上下文

wac = createWebApplicationContext(parent);

}

if (!this.refreshEventReceived) {

// Apparently not a ConfigurableApplicationContext with refresh support:

// triggering initial onRefresh manually here.

onRefresh(wac);

}

if (this.publishContext) {

// Publish the context as a servlet context attribute.

// 取得context在ServletContext中的名称

String attrName = getServletContextAttributeName();

//将Spring MVC的Context放置到ServletContext中

getServletContext().setAttribute(attrName, wac);

if (this.logger.isDebugEnabled()) {

this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]");

}

}

return wac;

}

  1. DispatcherServlet初始化的大体流程:
  1. 控制器DispatcherServlet的类图及继承关系:

servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT技术精选文摘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档