还搞不清Spring 与 Spring MVC 容器之间的关系?

在使用Spring MVC的时候,标准的配置是如下这样的:

还搞不清Spring 与 Spring MVC 容器之间的关系?

文章插图
 
注意注意:小编整理了一份Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC,有需要的朋友可以私信“spring”免费领取
1.ContextLoaderListener配置: <!-- Spring读取Spring的配置文件 --> <context-param> <!-- 名称 --> <param-name>contextConfigLocation</param-name> <!-- 文件的位置 --> <param-value>classpath:Application-context.xml</param-value> </context-param><context-param> <param-name>webAppRootKey</param-name> <param-value>meipian</param-value></context-param> <!-- Spring 的监听器配置 --> <listener> <!-- 在Spring-web包下 context --> <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class> </listener>2.DispatcherServlet的配置:<servlet> <servlet-name>meipian</servlet-name> <!-- 配置SpringMVC核心控制器 --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>meipian</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息 。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法 。
Spring MVC的使用的容器是WebApplicationContext 。那么他和ContextLoaderListener所初始化的ApplicationContext有什么关系呢?
可以从DispatcherServlet的初始化过程说起:DispatcherServlet拦截了所有的请求,所以访问任何一个接口都会初始化DispatcherServlet对象 。
初始化DispatcherServlet只是做了一个很简单的事:
【还搞不清Spring 与 Spring MVC 容器之间的关系?】public DispatcherServlet() { super(); setDispatchOptionsRequest(true); }其父类FrameworkServlet初始化什么也没有:
public FrameworkServlet() { }然后Tomcat会调用DispatcherServlet的init方法,在 Servlet 的生命期中,仅执行一次 init() 方法 。它是在服务器装入 Servlet 时执行的 。可以配置服务器,以在启动服务器或客户机首次访问 Servlet 时装入 Servlet 。无论有多少客户机访问 Servlet,都不会重复执行 init()。别问我为什么会调用init方法,这是servlet的规范 。DispatcherServlet的init方法是在父类FrameworkServlet的父类HttpServlet中实现的:
@Override public final void init() throws ServletException { if (logger.isDebugEnabled()) { logger.debug("Initializing servlet '" + getServletName() + "'"); } // Set bean properties from init parameters. try { PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); 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) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); throw ex; } // Let subclasses do whatever initialization they like. initServletBean(); if (logger.isDebugEnabled()) { logger.debug("Servlet '" + getServletName() + "' configured successfully"); } }会调用DispatcherServlet的initServletBean()方法就是初始化WebApplicationContext的方法 。这个方法在其子类FrameServlet方法中实现:
@Override protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); if (this.logger.isInfoEnabled()) { this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started"); } long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext(); //初始化WebApplicationContext对象 initFrameworkServlet(); } catch (ServletException ex) { this.logger.error("Context initialization failed", ex); throw ex; } catch (RuntimeException ex) { this.logger.error("Context initialization failed", ex); throw ex; } if (this.logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + elapsedTime + " ms"); } }


推荐阅读