SpringMVC --- DispatcherServlet的初始化过程

SpringMVC --- DispatcherServlet的初始化过程

1. DispatcherServlet的继承关系图

在这里插入图片描述

2. 具体的初始化步骤

  1. DispatcherServlet 本质上还是一个Servlet,所以初始化的时候还是遵循着Servlet的初始化过程,Servlet在初始化的过程中,容器将调用servlet的init(ServletConfig config) 方法初始化这个对象,DispatcherServlet 的初始化实际上就是调用Servlet 的 init(ServletConfig config) 方法

  2. 在GenericServlet 中 对 init (ServletConfig config) 方法进行了实现,并在 init (ServletConfig config)方法中调用了 init() 方法(方法重载),而在GenericServlet 中并没有对 init() 方法有具体的代码实现,而在HttpServletBean类中对 init() 方法进行了重写

    /**
     * 实现了Servlet接口中的方法,并调用了 init() 方法
     */
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    
  3. 而在HttpServletBean中 调用 init() 方法,其中最主要的是,在 init() 方法中,又调用了initServletBean() 方法,该方法是由 HttpServletBean定义,但是HttpServletBean 并没有对 initServletBean() 方法进行代码实现,而是由它的子类 FrameworkServlet进行重写实现

    HttpServletBean:init() 方法

    @Override
    public final void init() throws ServletException {
        
       PropertyValues pvs = 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) {
             if (logger.isErrorEnabled()) {
                logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
             }
             throw ex;
          }
       }
    
       // 在 HttpServletBean 中的 init() 方法中调用了 initServletBean(); 方法
       initServletBean();
    }
    
  4. FrameworkServlet 重写并调用 initServletBean(),在initServletBean()方法中进行了创建并初始化 WebApplicationContext(上下文),并刷新(onRefresh(WebApplication wac) 方法),在FrameworkServlet 中没有对 onRefresh(WebApplication wac) 方法进行具体的代码实现,而是由DispatcherServlet 进行重写并调用 onRefresh(WebApplication wac) 方法,在方法中调用了具体的初始化方法 调用了initStrategies(context)方法,初始化策略,即初始化DispatcherServlet的各个组件

    FrameworkServlet :initServletBean() 方法

    @Override
    	protected final void initServletBean() throws ServletException {
    		getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
    		if (logger.isInfoEnabled()) {
    			logger.info("Initializing Servlet '" + getServletName() + "'");
    		}
    		long startTime = System.currentTimeMillis();
    
    		try {
                //通过调用 initWebApplicationContext();来初始化并获取 WebApplicationContext对象
    			this.webApplicationContext = initWebApplicationContext();
    			initFrameworkServlet();
    		}
    		catch (ServletException | RuntimeException ex) {
    			logger.error("Context initialization failed", ex);
    			throw ex;
    		}
    
    		if (logger.isDebugEnabled()) {
    			String value = this.enableLoggingRequestDetails ?
    					"shown which may lead to unsafe logging of potentially sensitive data" :
    					"masked to prevent unsafe logging of potentially sensitive data";
    			logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
    					"': request parameters and headers will be " + value);
    		}
    
    		if (logger.isInfoEnabled()) {
    			logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
    		}
    	}
    
    1. 创建并初始化 WebApplicationContext 是在 initWebApplicationContext(); 方法中完成的

    2. 而调用 onRefresh(WebApplication wac) 方法是在 initWebApplicationContext(); 中

      FrameworkServlet :initWebApplicationContext() 方法

      protected WebApplicationContext initWebApplicationContext() {
         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) {
         	  //创建一个 WebApplicationContext 对象,并将它赋给 wac
            wac = createWebApplicationContext(rootContext);
         }
      
         if (!this.refreshEventReceived) {
            synchronized (this.onRefreshMonitor) {
               //调用 刷新的方法,该方法具体是在 DispatcherServlet中实现
               onRefresh(wac);
            }
         }
      
         if (this.publishContext) {
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
         }
      
         return wac;
      }
      
  5. 通过 DispatcherServlet 调用 init(ServletConfig config)方法,到最后调用到 initStrategies(context)方法(初始化策略,是 DispatcherServlet 具体的初始化代码,里面对 DispatcherServlet 各种组件进行了初始化)

    DispatcherServlet :onRefresh(ApplicationContext context)方法

    @Override
    protected void onRefresh(ApplicationContext context) {
       //调用了初始化策略方法
       initStrategies(context);
    }
    

DispatcherServlet :initStrategies(context)方法

/**
 * 进行具体的初始化过程
 */
protected void initStrategies(ApplicationContext context) {
   initMultipartResolver(context);
   initLocaleResolver(context);
   initThemeResolver(context);
   initHandlerMappings(context);
   initHandlerAdapters(context);
   initHandlerExceptionResolvers(context);
   initRequestToViewNameTranslator(context);
   initViewResolvers(context);
   initFlashMapManager(context);
}

以上就是 DispatcherServlet 的初始化的一个大致的过程。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值