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

 

說到最後

本次源碼解析僅表明我的觀點,僅供參考。

相關文章
相關標籤/搜索