SpringMVC源码分析(一)

这一篇记录SpringMvc的初始化过程

Springmvc的入口在DispacherServlet,这个类是配置在web.xml中的,容器启动时就会加载

<servlet>
        <servlet-name>springmvc</servlet-name>
        <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>
        <load-on-startup>1</load-on-startup> //如果不配置默认会在servlet第一次被访问时初始化,导致第一请求耗时较长
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
DispatcherServlet的初始化

通过以上的配置,Tomcat容器启动时默认会执行Servlet的init方法,查看DispactherServlet发现并没有这个方法,其初始化方法是在父类及其祖父类中逐步实现的。先看一下DispatcherServlet的继承关系
红色框中为spring框架内容
从上面可以看到DispatcherServlet的继承关系,红色框内为spring 框架内容。

  • 首先,容器启动,会默认执行servlet的init方法,在这里我理解为,tomcat的启动执行了这么两行代码
Servlet servlet = new DispatcherServlet
servlet.init()

这是一种java多态的体现,DispatcherServlet没有init方法,那么就会执行执行父类的,层层往上找。第一个抽象类GenericServlet实现了Servlet接口中的init方法,一个空实现和init(ServletConfig config),这里分两个方法是方便编程人员对init的操作。

  • 接下来是spring框架对init方法的实现。HttpServletBean中实现了GenericServlet的init方法
@Override
	public final void init() throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("Initializing servlet '" + getServletName() + "'");
		}

		// Set bean properties from init parameters.
		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;
			}
		}

		// Let subclasses do whatever initialization they like.
		initServletBean();

		if (logger.isDebugEnabled()) {
			logger.debug("Servlet '" + getServletName() + "' configured successfully");
		}
	}

在这里将配置在web.xml中的init-param参数设置到bean中,然后执行initServletBean(),但是这个方法也是个空实现,具体实现在其子类FrameworkServlet中

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(); //初始化web上下文。
			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");
		}
	}

在这里开始执行初始化web应用上下文

在这里插入图片描述
web上下文创建完成后执行onRefresh方法,最后由DispatcherServlet实现了onRefresh方法,开始对Springmvc的九大组件进行初始化,到此所有初始化工作完成。

@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	/**
	 * Initialize the strategy objects that this servlet uses.
	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
	 */
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}
总结

在这里插入图片描述
web框架用了三个类分别执行了部分初始化工作
HttpServletBean:读取web,xml中的init-param参数设置到servlet中
FrameworkServlet:将spring容器和servlet进行关联。WebApplicationContext是Servlet的一个属性,然后将ContextLoaderListener获取的上下文作为父上下文。
DispatcherServlet:ch:初始化组件,包括HandlerMapping,HandlerAdapter等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值