首页 > 其他分享 >DispatcherServlet初始化顺序详解

DispatcherServlet初始化顺序详解

时间:2023-10-24 10:32:44浏览次数:37  
标签:初始化 上下文 Web wac 详解 context DispatcherServlet

1. 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覆盖。

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

public abstract class FrameworkServlet extends HttpServletBean {
	@Override
    protected final void initServletBean() throws ServletException {
        //省略部分代码
       try {
             //1、初始化Web上下文
           this.webApplicationContext = initWebApplicationContext();
             //2、提供给子类初始化的扩展点
           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()方法执行容器的一些初始化,这个方法由子类实现,来进行扩展。

3. 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初始化的过程具体主要做了如下两件事情:
1. 初始化Spring Web MVC使用的Web上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文);
2. 初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。

DispatcherServlet初始化顺序详解_子类

标签:初始化,上下文,Web,wac,详解,context,DispatcherServlet
From: https://blog.51cto.com/u_16248220/8001202

相关文章

  • ScyllaDB详解
    2ScyllaDB号称下一代NoSQL,C++编写充分利用Linux底层原语优势,利用现代多核、多处理器NUMA服务器硬件,卓越性能,API兼容Cassandra和DynamoDB:支持和Cassandra一样的CQL查询语言和驱动,一样的SSTable存储格式同样支持和DynamoDB一样的JSON-style查询和驱动2.1......
  • 一文详解|支付宝小程序跳转(超详细版)
    开发过程中经常遇到支付宝小程序跳转的问题,这里总结一下支付宝小程序跳转的常见场景和方式,希望可以对大家有所帮助。话不多说,上干货!     支付宝小程序跳转的三种行为支付宝小程序跳转可以拆分为三种行为,即:外部跳转支付宝小程序支付宝小程序内部页面之间跳转......
  • Makefile基础使用和实战详解
    一、基础Makefile其实只是一个指示make程序如何为我们工作的命令文件,我们说Makefile其实是在说make。而对于项目来说,Makefile是指软件项目的编译环境。Makefile的好坏对于项目开发有些什么影响呢?设计得好的Makefile,当我们重新编译时,只需编译那些上次编译成功后修改过的......
  • Go语言代码断行规则详解
    本文深入探讨了Go语言中代码断行的各个方面,从基础概念到实际应用实践。关注【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业......
  • jenkins 原理篇——pipeline流水线 声明式语法详解
    大家好,我是蓝胖子,相信大家平时项目中或多或少都有用到jenkins,它的piepeline模式能够对项目的发布流程进行编排,优化部署效率,减少错误的发生,如何去写一个pipeline脚本呢,今天我们就来简单看看pipeline的语法。先拿一个helloworld的pipeline脚本举例,我们来看看pipeline脚本的组成......
  • crontab 命令详解非常详细
    crontab命令详解crontab 是一个用于创建、编辑和管理用户的定时任务的命令,它可以让用户在指定的时间自动执行指定的命令或脚本。基本语法crontab[选项]文件名-e:编辑用户的crontab文件;-l:列出用户当前的crontab内容;-r:删除用户的crontab文件;-i:在删除......
  • [GAA系列]详解台积电2纳米制程中的全环绕栅极(Gate-All-Around)晶体管技术
    SectionⅠ半导体技术发展史的本质就是晶体管尺寸的缩小史。从上世纪七十年代的10微米节点开始,遵循着摩尔定律一步一步走到了今天的5纳米。在这一过程中,每当摩尔定律遭遇困境,总会有新的技术及时出现并引领着摩尔定律继续前行。自22纳米节点上被英特尔首次采用,鳍式场效应晶体管(Fin......
  • Go笔记(3)-3种go语言的键盘输入详解
    go语言的键盘输入详解go语言中有三种输入函数,分别是:fmt.Scanf()可以按照指定的格式进行输入fmt.Scanln()通过指针将值赋值给变量fmt.Scan()(1)fmt.ScanScan从标准输入扫描文本,读取空白符分隔的值保存到传递给本函数的参数中,将换行符视为空白符使用......
  • Python 函数:定义、调用、参数、递归和 Lambda 函数详解
    函数是一段代码块,只有在调用时才会运行。您可以将数据(称为参数)传递给函数。函数可以返回数据作为结果。创建函数在Python中,使用def关键字定义函数:示例defmy_function():print("Hellofromafunction")调用函数要调用函数,请使用函数名称后跟括号:示例defmy_function......
  • Python 函数:定义、调用、参数、递归和 Lambda 函数详解
    函数是一段代码块,只有在调用时才会运行。您可以将数据(称为参数)传递给函数。函数可以返回数据作为结果。创建函数在Python中,使用def关键字定义函数:示例defmy_function():print("Hellofromafunction")调用函数要调用函数,请使用函数名称后跟括号:示例defmy_function(......