springmvc初始化过程

在看完spring源码后,有个疑问handlerMappings以及的handlerAdapters是何时被初始化的?

1.看到DispatcherServletinitHandlerMappings方法:这个方法初始化了handlerMappings

private void initHandlerMappings(ApplicationContext context) {
   this.handlerMappings = null;
   if (this.detectAllHandlerMappings) {
       Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
       if (!matchingBeans.isEmpty()) {
           this.handlerMappings = new ArrayList(matchingBeans.values());
           AnnotationAwareOrderComparator.sort(this.handlerMappings);
       }
   } else {
       try {
           HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
           this.handlerMappings = Collections.singletonList(hm);
       } catch (NoSuchBeanDefinitionException var3) {。。。 }
   if (this.handlerMappings == null) {
       this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
。。。

在该类中发现,是在initStrategies方法中执行初始化的,同时发现好多组件都是在这个方法中执行,比如另一个重要的对象handler适配器。而initStrategies又是在onRefresh中执行

 protected void initStrategies(ApplicationContext context) {
     this.initMultipartResolver(context);
     this.initLocaleResolver(context);
     this.initThemeResolver(context);
     //初始化所有HandlerMapping
     this.initHandlerMappings(context);
     //初始化所有HandlerAdapter
     this.initHandlerAdapters(context);
     this.initHandlerExceptionResolvers(context);
     this.initRequestToViewNameTranslator(context);
     this.initViewResolvers(context);
     this.initFlashMapManager(context);
 }
 protected void onRefresh(ApplicationContext context) {
     this.initStrategies(context);
 }

归根究底,其springMVC的初始化是在onRefresh()这个方法中执行的。

2.下面首先通过时序图来探索springMVC的初始化流程:(图片来源于网络)
在这里插入图片描述
2.1 servlet初始化会调用 init 方法,换句话说就是springMVC进行初始化的时候首先会去执行HttpServletBeaninit方法, 下面看看HttpServletBeaninit方法源码:

 public final void init() throws ServletException {
。。。
       //从init参数设置bean属性
        PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
        if (!pvs.isEmpty()) {
            try {
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
                bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
                this.initBeanWrapper(bw);
                bw.setPropertyValues(pvs, true);
            } catch (BeansException var4) {
。。。。。
        }
       //让子类FrameworkServlet实现
        this.initServletBean();
。。。。

果然出现了流程图中的initServletBean

2.2 接下来 FramworkServlet 会执行 initServletBean 这个方法,下面就继续看看 initServletBean 方法源码:

protected final void initServletBean() throws ServletException {
      this.getServletContext().log("Initializing Spring FrameworkServlet '" + this.getServletName() + "'");
。。。
      long startTime = System.currentTimeMillis();
      try {
          this.webApplicationContext = this.initWebApplicationContext();
          this.initFrameworkServlet();
      } 
。。。

可以看到 initServletBean 方法中就调用了一个 initFrameworkServlet 方法和 initWebApplicationContext 方法,其中initFrameworkServlet方法是由子类实现,这个不多说,直接看 initWebApplicationContext 方法源码。

2.3 initWebApplicationContext 方法源码:

 protected WebApplicationContext initWebApplicationContext() {
 
//此处的 rootContext便是springioc容器, 在你配置web.xml的ContextLoaderListener的时候注入的
//通过分析ContextLoaderListenr的源码,可以看到
//ContextLoaderListener通过ContextLoader根据ApplicationContext.xml的配置会创建一个xmlWebApplicationContext
//如果没有配置ContextLoaderListener,本处将为null,但不影响springMVC,为何?通过接下来的分析,就能看到原因
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
       
       //当webApplicationContext已经存在,即springmvc容器已经存在,那么就直接使用,使用之前会先设置rootContext,为其根
       //配置完成之后refresh一次,refresh会涉及到IOC的内容,本处不做探讨。
        if (this.webApplicationContext != null) {
            wac = this.webApplicationContext;
            if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
                if (!cwac.isActive()) {
                    if (cwac.getParent() == null) {
                    //设置springIOC容器为spring mvc容器的父同期
                        cwac.setParent(rootContext);
                    }
                    this.configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }
        //如果不存在webApplicationContext,那么先去ServletContext中查找
        if (wac == null) {
            wac = this.findWebApplicationContext();
        }
        //如果上述没有查到,那么就创建webApplicationContext
        if (wac == null) {
            //创建springmvc容器
            wac = this.createWebApplicationContext(rootContext);
        }
        if (!this.refreshEventReceived) {
             //此方法由DispatcherServlet调用,初始化创建好的springmvc容器
            this.onRefresh(wac);
        }
        //将webApplicationContext保存在ServletContext
        if (this.publishContext) {
            //将上下文发布为servlet上下文属性。
            String attrName = this.getServletContextAttributeName();
            this.getServletContext().setAttribute(attrName, wac);
。。。
        }
        return wac;
    }

FrameworkServlet初始化web应用上下文的时候会调用onRefresh()方法,这个方法是留给其子类DispatcherServlet调用的, 最后就该看看DispatcherServlet里面的 onRefresh 方法了:

 protected void onRefresh(ApplicationContext context) {
        this.initStrategies(context);
    }
     //初始化此servlet使用的策略对象。
     //可以在子类中重写以初始化其他策略对象
    protected void initStrategies(ApplicationContext context) {
        this.initMultipartResolver(context);
        this.initLocaleResolver(context);
        this.initThemeResolver(context);
        this.initHandlerMappings(context);
        this.initHandlerAdapters(context);
        this.initHandlerExceptionResolvers(context);
        this.initRequestToViewNameTranslator(context);
        this.initViewResolvers(context);
        this.initFlashMapManager(context);
    }

可以看到onRefresh方法就一句话,调用initStrategies方法, 上面给出了 initStrategies 源码, 很直观,就是在初始化springMVC 的一系列组件, 但是此处你要明白,SpringMVC的组件其实已经在webApplicationContext创建时就已经实例化了, 此处所谓的初始化只是在选择合适的组件(每一个组件都对应了几个不同的实现)。

到此,就可以很清楚知道,HandlerMappingsHandlerAdapter等是在什么时候初始化的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值