动力节点旗下在线教育品牌  |  咨询热线:400-8080-105 学Java全栈,上蛙课网
首页 > 文章

实例讲解 Spring MVC容器初始化

08-19 17:48 185浏览
举报 T字号
  • 大字
  • 中字
  • 小字

在讲Spring MVC容器初始化之前,我们先来温故知新,重新认识一下容器技术:有效的将单个操作系统的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使用需求,这种技术就是容器技术。

Spring MVC容器的存在大大提高了Spring MVC框架的工作效率,作为Spring MVC框架的核心技术之一,Spring MVC容器初始化也就显得至关重要了。

大家知道Servlet生命周期都是从init方法开始,desctory方法结束,由JVM负责垃圾回收。而DispatcherServlet也是一个普通的Servlet,先看一下DispatcherServlet的继承关系图,对整个继承关系有个了解。

   既然说起Servlet,那就从Servlet的初始化(init)方法入手

//HttpServletBean.java

@Override

public final void init() throws ServletException {

PropertyValuespvs=new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);

if (!pvs.isEmpty()) {

try {

BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);

ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());

bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));

initBeanWrapper(bw);

bw.setPropertyValues(pvs, true);

}

catch (BeansException ex) {

throw ex;

}

}



//交给子类重写

initServletBean();

}



//FrameworkServlet.java

@Override

protected final void initServletBean() throws ServletException {

try {

this.webApplicationContext = initWebApplicationContext();

initFrameworkServlet();

}

catch (ServletException | RuntimeException ex) {

throw ex;

}

}



//FrameworkServlet.java

//初始化MVC容器

protected WebApplicationContext initWebApplicationContext() {

    //从ServletContext取出根上下文

WebApplicationContext rootContext =

WebApplicationContextUtils.getWebApplicationContext(getServletContext());

WebApplicationContext wac = null;



if (this.webApplicationContext != null) {

wac = this.webApplicationContext;

if (wac instanceof ConfigurableWebApplicationContext) {

ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;

if (!cwac.isActive()) {

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

cwac.setParent(rootContext);

}

configureAndRefreshWebApplicationContext(cwac);

}

}

}

if (wac == null) {

wac = findWebApplicationContext();

}



//如果还没有webApplicatioinContext,创建webApplicationContext

if (wac == null) {

wac = createWebApplicationContext(rootContext);

}



//子类自定义对servlet子上下文后续操作,在DispatcherServlet中实现

if (!this.refreshEventReceived) {

synchronized (this.onRefreshMonitor) {

//执行子类扩展方法onRefresh,在DispatcherServlet内初始化所有web相关组件

onRefresh(wac);

}

}



//发布servlet子上下文到ServletContext

if (this.publishContext) {

String attrName = getServletContextAttributeName();

//将servlet子上下文以org.springframework.web.servlet.FrameworkServlet.CONTEXT. + servletName的属性名称注册到ServletContext中

getServletContext().setAttribute(attrName, wac);

}



return wac;

}



protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {

return createWebApplicationContext((ApplicationContext) parent);

}



protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {

    //获取WebApplicationContext实现类,此处其实就是XmlWebApplicationContext

Class contextClass = getContextClass();

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

throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +

"': custom WebApplicationContext class [" + contextClass.getName() +

"] is not of type ConfigurableWebApplicationContext");

}



//生成XmlWebApplicationContext实例

ConfigurableWebApplicationContext wac =

(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);



wac.setEnvironment(getEnvironment());

//设置根容器为父容器

wac.setParent(parent);

String configLocation = getContextConfigLocation();

if (configLocation != null) {

    //设置配置文件

wac.setConfigLocation(configLocation);

}



//配置webApplicationContext

configureAndRefreshWebApplicationContext(wac);



return wac;

}



protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {

if (ObjectUtils.identityToString(wac).equals(wac.getId())) {

if (this.contextId != null) {

wac.setId(this.contextId);

}

else {

wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(getServletContext().getContextPath()) + '/' + getServletName());

}

}



wac.setServletContext(getServletContext());

wac.setServletConfig(getServletConfig());

wac.setNamespace(getNamespace());

wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));



ConfigurableEnvironment env = wac.getEnvironment();

if (env instanceof ConfigurableWebEnvironment) {

((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());

}



postProcessWebApplicationContext(wac);

applyInitializers(wac);



//开始处理bean

wac.refresh();

}

上面的关键代码都在FrameworkServlet类中,有几个关键点:取根上下文,创建子上下文并设置父上下文,完成刷新,把子上下文发布到ServletContext中。 到这里可以说子容器(子上下文)已经创建完成。 并把其他初始化web组件的相关工作交给onRefresh方法完成,由DispatcherServlet来重写onRefresh方法,这就又回到了我们熟悉的initStrategies方法。

总之,看完了上面的实例,相信你对Spring MVC容器初始化有了一定的认知,没有我们想象的那么简单,结合实际的例子我们可能在短时间内仍然不能独立完成Spring MVC容器初始化。没有关系。可以通过观看本站的Spring MVC视频教程来学习,名师指导,学习思路更清晰!

0人推荐
共同学习,写下你的评论
0条评论
十年
程序员十年

13篇文章贡献72369字

作者相关文章更多>

推荐相关文章更多>

DOM渲染的详细过程

QCode09-04 14:38

CSS水平和垂直居中技巧大梳理

Code大师09-04 14:50

mui的input框在IOS系统下无法聚焦或点击多次才能聚焦

不写代码你养我啊08-23 11:14

推荐的-视.频播放器以及在线客服

不写代码你养我啊09-17 18:02

谈谈java多线程的三大特性

要学习了06-18 18:13

发评论

举报

0/150

取消