/**
* Create the "<strong>root</strong>" application context to be provided to the
* {@code ContextLoaderListener}.
* <p>The returned context is delegated to
* {@link ContextLoaderListener#ContextLoaderListener(WebApplicationContext)} and will
* be established as the parent context for any {@code DispatcherServlet} application
* contexts. As such, it typically contains middle-tier services, data sources, etc.
* @return the root application context, or {@code null} if a root context is not
* desired
* @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer
*/
protected abstract WebApplicationContext createRootApplicationContext();
/**
* Specify application context initializers to be applied to the root application
* context that the {@code ContextLoaderListener} is being created with.
* @since 4.2
* @see #createRootApplicationContext()
* @see ContextLoaderListener#setContextInitializers
*/
protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
return null;
}
}
注意的是这里我们跳过了AbstractDispatcherServletInitializer抽象类(看uml图),这个类主要配置DispatcherServlet,这里就是spring mvc等功能的实现了。
那谁来加载AbstractContextLoaderInitializer?WebApplicationInitializer已经是接口,不会再有一个抽象类来调用了,于是我尝试性地搜WebApplicationInitializer接口,因为spring这种大项目肯定是面向接口的,所以调用的地方一般是写接口,然后我们找到了SpringServletContainerInitializer类,它实现了ServletContainerInitializer接口,这个类大概是说把所有WebApplicationInitializer都startUp一遍,可以说这个类很接近我们的目标了。下面贴下SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@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);
}
}
}
在最后的foreach把所有的WebApplicationInitializer都启动一遍。那么问题来了,谁来启动SpringServletContainerInitializer,spring肯定不能自己就能启动的,在