1.当应用启动时,web容器会创建一个ServletContainerInitializer实例,
2.框架提供的jar包的META-INF/service目录下的javax.ServletServletContainerInitializer内容就是指向ServletContainerInitializer的实现
3.spring mvc框架提供的是org.springframework.web.SpringServletContainerInitailizer实现
4.SpringServletContainerInitializer的@HandlesTypes注解值为WebApplicationInitializer.class,表示它对所有实现了此接口的类感兴趣,他们将会传入onStartup方法的第一个参数
onStartup方法的源码:
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);
}
}
从源码可以看出,所有的Initialize共用一个servletContext,一个一个区启动它们的onStartup方法,可以通过@Order注解改变顺序(数值越低越靠前)
5.基于Java-config的配置只要找到合适的WebApplicationInitializer的子类,重写它的onStartup发方法即可(一般会选择继承AbstractAnnotationConfigDispatherServletInitializer,它帮我们注册了DispatherServlet)