Spring MVC 的源码分析(1)
Spring MVC 初始化设计分析
总结: 外部容器通过监听器传给spring mvc初始化,这个初始化我们是以分散重写初始化逻辑进入spring ioc 初始化,然后在返回到Spring MVC自己的上下文九大组件初始化
Spring MVC 底层是设计原理是 前端控制模式
我们拿着总结和上面这张图去看具体实现过程,不然在细节过程,我们很容易就迷糊了,拿到总结让我们有一种一览众山小的视角去俯瞰细节.
1.--------Spring MVC实现了Servlert规范--------
这个是Servlet的相关方法
为什么说Spring MVC是实现了Servlet的方法呢?我们去看一下源码
我们知道DispatchServlet是Spring Mvc的核心控制器,由源码可以看出,它的父类就是 GenericServlet,而GenericServlet的父类也是Servlert,所以说,Spring Mvc是实现了Servlet的规范
2.------Spring MVC初始化的过程--------
容器启动的时候初始化,既然上面说了Spring MVC实现了Servlet规范,那么它肯定也会有相应的 init , service , destroy.
不过区别是在 这三个方法是在不同的类实现的,并不是每个类都重写了这三个方法,每个类都会有自己专注的事情来做.
来,我们看下面这几张图,有以下几张图我们可以分析出父类的GenericServlet的init初始化方法,其实最后是第三张图中HttpServlert子类给重写了
(1)GenericServlet进行初始化(爷爷辈)
(2)HttpServlet 做了service方法(儿子辈)
(3)进行了init初始化的方法重写 (孙子辈)
3.------HttpServletBean的初始化方法细节-------------
(1)init初始化方法
(2)真正的初始化方法 initServletBean方法
(3)构建Spring Mvc自己的上下文环境
//这个方法主要是构建Spring mvc自己的上下文 protected WebApplicationContext initWebApplicationContext() { //拿到根上下文环境 spring ioc WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); //创建spring mvc自己的上下文,但是没有实例化 WebApplicationContext wac = null; //如果不为空说明已经通过构造方法设置了一个上下文对象 if(this.webApplicationContext != null) { wac = this.webApplicationContext; if(wac instanceof ConfigurableWebApplicationContext) { //当前的spring mvc的上下文 ConfigurableWebApplicationContext attrName = (ConfigurableWebApplicationContext)wac; //这里判断这个上下文有没有被**过,Bean关系有没有更新一次 if(!attrName.isActive()) { if(attrName.getParent() == null) { //设置属性 attrName.setParent(rootContext); } //没有**就重新**一下 我们在看一下**的具体实现 this.configureAndRefreshWebApplicationContext(attrName); } } } if(wac == null) { wac = this.findWebApplicationContext(); } if(wac == null) { wac = this.createWebApplicationContext(rootContext); } if(!this.refreshEventReceived) { //调用这个方法初始化Spring Mvc 的九大组件 this.onRefresh(wac); } if(this.publishContext) { String attrName1 = this.getServletContextAttributeName(); this.getServletContext().setAttribute(attrName1, wac); if(this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet \'" + this.getServletName() + "\' as ServletContext attribute with name [" + attrName1 + "]"); } } return wac; }
(4)**上下文的方法
//这里是**上下文的方法 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(this.getServletContext().getContextPath()) + "/" + this.getServletName()); } } //设置上下文环境 wac.setServletContext(this.getServletContext()); //设置配置信息 wac.setServletConfig(this.getServletConfig()); //设置命名空间 wac.setNamespace(this.getNamespace()); wac.addApplicationListener(new SourceFilteringListener(wac, new FrameworkServlet.ContextRefreshListener(null))); ConfigurableEnvironment env = wac.getEnvironment(); if(env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources(this.getServletContext(), this.getServletConfig()); } this.postProcessWebApplicationContext(wac); this.applyInitializers(wac); //刷下上下文 wac.refresh(); }
(5)我们再来看初始化的最后一步
至此spring mvc的初始化结束