基於4.1.7.RELEASE
ServletContainerInitializer
前面都是Spring內部WebApplicationInitializer的實現,下面來看一個Servlet包中ServletContainerInitializer的實現。
首先看類申明
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer
出現了一個@HandlesTypes的註解,這個註解的作用是指明在ServletContainerInitializer的實現類中其onStartup方法中所傳進來的Class類型。
onStart的方法主要是創建WebApplicationInitializer並進行調用。
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}catch (Throwable ex) {
}
}
}
}
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
在上面的代碼中,首先進行了WebApplicationInitializer的實例化工作,爲什麼waiClass.newInstance()能夠生效呢,是因爲Servlet(3.0+)的容器在啓動時掃描了所有@HandlesTypes指定的Class的實現類,然後封裝在webAppInitializerClasses的Set裏傳遞進來。
初始化完畢之後對所有的initializers進行了排序,如果initializer有@Order註解或者實現了Order接口,那麼排序會依照Order指定的順序完成。
排序之後則是調用了所有的initializer的onStartup方法,這些方法裏或初始化DispatchServlet,或ConextLoaderListener,或Filter則根據各類不同的實現規則而定,由此可以看出Spring初始化的一些端倪。