• DispatcherServlet是如何进行初始化的呢?


    转自:

    DispatcherServlet是如何进行初始化的呢?

    下文笔者讲述DispatcherServlet的初始化顺序,如下所示:

    Web容器启动时将调用HttpServletBean的init方法

    public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{
        @Override
        public final void init() throws ServletException {
           //省略部分代码
           //1、如下代码的作用是将Servlet初始化参数设置到该组件上
           //如contextAttribute、contextClass、namespace、contextConfigLocation;
           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, this.environment));
               initBeanWrapper(bw);
               bw.setPropertyValues(pvs, true);
           }
           catch (BeansException ex) {
               //…………省略其他代码
           }
           //2、提供给子类初始化的扩展点,该方法由FrameworkServlet覆盖
           initServletBean();
           if (logger.isDebugEnabled()) {
               logger.debug("Servlet '" + getServletName() + "' configured successfully");
           }
        }
        //…………省略其他代码
    }
    
    将Servlet初始化参数(init-param)设置到该组件上(如contextAttribute、contextClass、namespace、contextConfigLocation)
    通过BeanWrapper简化设值过程,方便后续使用;
    为子类初始化扩展点initServletBean()该方法由FrameworkServlet覆盖
    

    FrameworkServlet通过initServletBean()进行Web上下文初始化

    public abstract class FrameworkServlet extends HttpServletBean {
    	@Override
        protected final void initServletBean() throws ServletException {
            //省略部分代码
           try {
                 //1、初始化Web上下文
               this.webApplicationContext = initWebApplicationContext();
                 //2、提供给子类初始化的扩展点
               initFrameworkServlet();
           }
            //省略部分代码
        }
    }
    
    initFrameworkServlet方法主要作用如下:
    初始化web上下文; 
    提供给子类初始化扩展点;
    
    protected WebApplicationContext initWebApplicationContext() {
    	//ROOT上下文(ContextLoaderListener加载的)
       WebApplicationContext rootContext =
    		  WebApplicationContextUtils.getWebApplicationContext(getServletContext());
       WebApplicationContext wac = null;
       if (this.webApplicationContext != null) {
    	   // 1、在创建该Servlet注入的上下文
    	   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) {
    		 //2、查找已经绑定的上下文
    	   wac = findWebApplicationContext();
       }
       if (wac == null) {
    		//3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener
    	   wac = createWebApplicationContext(rootContext);
       }
       if (!this.refreshEventReceived) {
    		 //4、刷新上下文(执行一些初始化)
    	   onRefresh(wac);
       }
       if (this.publishContext) {
    	   // Publish the context as a servlet context attribute.
    	   String attrName = getServletContextAttributeName();
    	   getServletContext().setAttribute(attrName, wac);
    	   //省略部分代码
       }
       return wac;
    }
    
    initWebApplicationContext()方法的功能,
    如果ContextLoaderListener加载了上下文
    将作为根上下文(DispatcherServlet的父容器)
    最后调用了onRefresh()方法执行容器的一些初始化
     这个方法由子类实现,来进行扩展
    

    DispatcherServlet实现了onRefresh()方法提供一些前端控制器相关的配置

    public class DispatcherServlet extends FrameworkServlet {
         //实现子类的onRefresh()方法,该方法委托为initStrategies()方法。
        @Override
        protected void onRefresh(ApplicationContext context) {
           initStrategies(context);
        }
    
        //初始化默认的Spring Web MVC框架使用的策略(如HandlerMapping)
        protected viod initStrategies(ApplicationContext context){
    		initMultipartResolver(context);//初始化上传文件解析器
    		initLocaleResolver(context);//初始化本地解析器
    		initThemeResolver(context);//初始化主题解析器
    		initHandlerMapping(context);
    		//初始化处理器映射器,将请求映射到处理器
    		initHandlerAdapters(context);//初始化处理器适配器
    		initHandlerExceptionResolver(context);
    		//初始化处理器异常解析器,如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
    		initRequestToViewNameTranslator(context);
    		//初始化请求到具体视图名称解析器
    		initViewResolvers(context);
    		//初始化视图解析器,通过ViewResolver解析逻辑视图名到具体视图实现
    		initFlshMapManager(context);//初始化flash映射管理
    	}
    }
    
    initStrategies方法
      将在WebApplicationContext初始化后自动执行
      自动扫描上下文的Bean
     根据名称或者类型匹配的机制查找自定义组件
    如果没有找到则会装配一套Spring的默认组件
    在org.springframework.web.servlet路径下有一个DispatcherServlet.properties配置文件
    该文件指定了DispatcherServlet所使用的默认组件
    DispatcherServlet启动时会进行我们需要的Web层Bean的配置
    如HandlerMapping、HandlerAdapter等,而且如果我们没有配置,还会给我们提供默认的配置
    
    DispatcherServlet主要完成以下工作:
     初始化Spring Web MVC使用的Web上下文
     初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。
  • 相关阅读:
    Three.js中实现一个OBBHelper
    mysql源码学习
    【Java】封装、继承、多态
    【教学类-40-02】A4骰子纸模制作2.0(统计表、棋盘)
    极坐标系下的交换积分次序
    CSP-J第二轮试题-2022年-3题
    FPGA - 7系列 FPGA内部结构之Clocking -02- 时钟布线资源
    微信收款码费率0.38太坑了
    元服务那些事儿 | 舞刀解决隐私声明,斩断上架牵绊
    koa2+vue3通过exceljs实现数据导出excel文档
  • 原文地址:https://blog.csdn.net/qq_25073223/article/details/127829939