SpringMVC源码(二)DispatcherServlet

来源:互联网 发布:eclipse js文件格式化 编辑:程序博客网 时间:2024/05/23 13:30

当ContextLoaderListener初始化完springweb容器的时候,接下来便是springmvc初始化自己的容器。

springmvc将springweb容器作为父容器。web.xml中DispatcherServlet具体配置:

 <servlet>    <servlet-name>springServlet</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>      <param-name>contextConfigLocation</param-name>      <param-value>classpath*:/spring-mvc*.xml</param-value>    </init-param><!--再启动之前 -->    <load-on-startup>1</load-on-startup>  </servlet>

DispatcherServlet类, extends FrameworkServlet.

而FrameworkServlet  extends HttpServletBean implementsApplicationContextAware  。

            

ApplicationContextAware 主要来设置ApplicationContext中的所有bean,当一个类实现了ApplicationContextAware

那么这个类就会直接获取到spring 配置文件中所有的引用bean对象。接口实现方法:

void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

HttpServletBean  继承 HttpServlet 。在web容器启动时调用它的init()方法,其主要工作就是设置我们在web.xml中配置的

contextConfigLocation 属性(文件加载地址),然后调用initServletBean(),该方法由FrameworkServlet 覆盖。

具体代码:

public final void init() throws ServletException {if (logger.isDebugEnabled()) {logger.debug("Initializing servlet '" + getServletName() + "'");}// Set bean properties from init parameters.try {//加载spring-mvc的配置文件PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);//属性访问器存取Bean对象的属性,所有spring创建的Bean对象,都使用该接口存取Bean属性值BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//获取服务器信息  ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));//模板方法,并没有具体实现initBeanWrapper(bw);//将初始化值放到DispatcherServlet中  bw.setPropertyValues(pvs, true);}catch (BeansException ex) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);throw ex;}// 又子类FrameworkServlet 覆盖initServletBean();if (logger.isDebugEnabled()) {logger.debug("Servlet '" + getServletName() + "' configured successfully");}}


FrameworkServlet 继承 HttpServletBean 。是springmvc 初始化容器的核心,通过加载springmvc配置文件具体信息

和 bean的注入 ,然后调用initServletBean()来完成容器的初始化,其核心是initWebApplicationContext()方法。

具体代码:

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();//提供子类扩展方法 (并没有实现)initFrameworkServlet();}catch (ServletException ex) {//省略部分代码}}
initWebApplicationContext()具体代码:

protected WebApplicationContext initWebApplicationContext() {//springweb 容器 (父容器)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();}if (wac == null) {//没找到,则创建,拿springweb的rootContext 为父容器wac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {//刷新容器 (执行一些初始化,在子类DispatcherServlet中实现)onRefresh(wac);}if (this.publishContext) {// Publish the context as a servlet context attribute.String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);if (this.logger.isDebugEnabled()) {this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +"' as ServletContext attribute with name [" + attrName + "]");}}return wac;}

createWebApplicationContext()具体代码:

protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {Class<?> contextClass = getContextClass();if (this.logger.isDebugEnabled()) {this.logger.debug("Servlet with name '" + getServletName() +"' will try to create custom WebApplicationContext context of class '" +contextClass.getName() + "'" + ", using parent context [" + parent + "]");}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");}//实例化容器ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);//环境属性wac.setEnvironment(getEnvironment());//父亲 rootwac.setParent(parent);//springmvc 配置文件wac.setConfigLocation(getContextConfigLocation());//各种相关配置configureAndRefreshWebApplicationContext(wac);return wac;}
通过FrameworkServlet 完成了springmvc 容器的初始化,并在初始化之后调用onRefresh(wac)来进行属性的初始化

通过模板方式在子类DispatcherServlet进行。

DispatcherServlet 类中具体方法:

protected void onRefresh(ApplicationContext context) {initStrategies(context);}
initStrategies()具体方法:
protected void initStrategies(ApplicationContext context) {initMultipartResolver(context); //文件上传解析,用来支持文件上传initLocaleResolver(context);//本地化解析,支持国际化 默认解析器AcceptHeaderLocaleResolver 通过解析客户端Locale信息initThemeResolver(context);//主题解析,动态样式支持,列如换肤initHandlerMappings(context);//处理器映射器,返回HandlerExecutionChain对象(一个Handler、多个HandlerInterceptor)initHandlerAdapters(context);//处理器适配器,将处理器进行包装,从而支持多种类型的处理器initHandlerExceptionResolvers(context);//处理器异常解析,将异常映射到统一的页面initRequestToViewNameTranslator(context);//处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;initViewResolvers(context);//视图解析,将逻辑视图名解析为具体视图initFlashMapManager(context);//链接跳转,通常为重定向}

调用initStrategies()里面的各种属性初始化方法,springmvc的容器初始化工作也便慢慢结束。

阅读全文
1 0
原创粉丝点击