springmvc源码解析之配置加载SpringServletContainerInitializer

说在前面web

本次主要介绍springmvc配置解析,关注“天河聊架构”微信公众号更多源码解析文章。spring

 

springmvc配置解析微信

sdervlet容器启动的时候会加载org.springframework.web.SpringServletContainerInitializer这个类,调用初始化类的onStartup方法架构

@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
      throws ServletException {

   List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
   if (webAppInitializerClasses != null) {
      for (Class<?> waiClass : webAppInitializerClasses) {
         // Be defensive: Some servlet containers provide us with invalid classes,
         // no matter what @HandlesTypes says...
         if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
               WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
            try {
               initializers.add((WebApplicationInitializer) waiClass.newInstance());
            }
            catch (Throwable ex) {
               throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
            }
         }
      }
   }

   if (initializers.isEmpty()) {
      servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
      return;
   }

   servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
   AnnotationAwareOrderComparator.sort(initializers);
   for (WebApplicationInitializer initializer : initializers) {
      initializer.onStartup(servletContext);
   }
}

进入到DispatcherServlet初始化器 org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这个方法mvc

@Override
 public void onStartup(ServletContext servletContext) throws ServletException {
//调用上下文加载器初始化类的onStartup方法
super.onStartup(servletContext);
//注册DispatcherServlet
registerDispatcherServlet(servletContext);
 }

进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#onStartup,执行ContextLoader初始化器app

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
   registerContextLoaderListener(servletContext);
}

进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#registerContextLoaderListener,注册ContextLoader监听器异步

protected void registerContextLoaderListener(ServletContext servletContext) {
// 获取上层应用上下文对象 ->
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
// 建立上下文加载监听器
 ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
 listener.setContextInitializers(getRootApplicationContextInitializers());
// 把上下文加载监听器加载到servlet容器
 servletContext.addListener(listener);
}
      else {
         logger.debug("No ContextLoaderListener registered, as " +
               "createRootApplicationContext() did not return an application context");
}
   }

进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createRootApplicationContextide

@Override
 protected WebApplicationContext createRootApplicationContext() {
//从子类实现中或者从@Configuration、@Component注解配置中获取配置类
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
// 若是没有配置就默认初始化基于注解的web应用上下文类
 AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
 rootAppContext.register(configClasses);
 return rootAppContext;
}
      else {
         return null;
}
   }

进入到这个方法org.springframework.web.context.AbstractContextLoaderInitializer#getRootApplicationContextInitializersspa

protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
   return null;
}

返回到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#onStartup这一行debug

// 注册DispatcherServlet
registerDispatcherServlet(servletContext);

进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerDispatcherServlet

protected void registerDispatcherServlet(ServletContext servletContext) {
//获取servletName,默认名称是dispatcher
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return empty or null");
//建立servlet程序上下文 ->
WebApplicationContext servletAppContext = createServletApplicationContext();
Assert.notNull(servletAppContext,
"createServletApplicationContext() did not return an application " +
            "context for servlet [" + servletName + "]");
//建立DispatcherServlet
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
//注册servlet上下文初始化器,这里是模板实现
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
//添加DispatcherServlet到servlet容器
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
Assert.notNull(registration,
"Failed to register servlet with name '" + servletName + "'." +
            "Check if there is another servlet registered under the same name.");
registration.setLoadOnStartup(1);
//获取servletMapping实现,这里是抽象实现,注册mapping
registration.addMapping(getServletMappings());
//设置是否支持异步,默认支持
registration.setAsyncSupported(isAsyncSupported());
//获取servletFilter,这里是模板实现
Filter[] filters = getServletFilters();
if (!ObjectUtils.isEmpty(filters)) {
         for (Filter filter : filters) {
//注册filter ->
registerServletFilter(servletContext, filter);
 }
      }

//定制化注册,默认是模板实现
customizeRegistration(registration);
 }

进入到这个方法org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer#createServletApplicationContext

@Override
 protected WebApplicationContext createServletApplicationContext() {
//建立基于注解的web应用上下文
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
//从子类实现中或者从@Configuration、@Component注解配置中获取配置类
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
// 注册@Configuration配置的配置加载类到AnnotationConfigWebApplicationContext
 servletAppContext.register(configClasses);
}
      return servletAppContext;
 }

进入到这个方法org.springframework.web.servlet.support.AbstractDispatcherServletInitializer#registerServletFilter

protected FilterRegistration.Dynamic registerServletFilter(ServletContext servletContext, Filter filter) {
//获取filteName
String filterName = Conventions.getVariableName(filter);
//添加filter到servlet容器
Dynamic registration = servletContext.addFilter(filterName, filter);
//若是filter注册失败
if (registration == null) {
         int counter = -1;
 while (counter == -1 || registration == null) {
            counter++;
//添加filter#0 到servlet容器
registration = servletContext.addFilter(filterName + "#" + counter, filter);
//提示有一样的名字的filter已注册过
Assert.isTrue(counter < 100,
"Failed to register filter '" + filter + "'." +
                  "Could the same Filter instance have been registered already?");
 }
      }
//是否支持异步,默认是
registration.setAsyncSupported(isAsyncSupported());
registration.addMappingForServletNames(getDispatcherTypes(), false, getServletName());
return registration;
 }

回退到这个方法org.springframework.web.SpringServletContainerInitializer#onStartup

 

说到最后

本次源码解析仅表明我的观点,仅供参考。

相关文章
相关标签/搜索