step1
SpringServletContainerInitializer.java
该类继承ServletContainerInitializer,实现了与servlet容器的集成。
在class上添加了注解@HandlesTypes,指定了我们我们的应用程序要启动加载的类型。
onStartup方法的第一个参数是一个set集合,集合中的class对应就是注解@HandlesTypes中指定的类型。
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
//存储WebApplicationInitializer实例。在本项目中有两个实例:WebContextInitializer.java和SecurityWebApplicationInitializer.java
List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
...
initializers.add((WebApplicationInitializer) waiClass.newInstance());
...
}
}
...
AnnotationAwareOrderComparator.sort(initializers);
servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
//遍历WebApplicationInitializer实例,依次调用实例的onStartup方法。
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
step2:
SecurityWebApplicationInitializer.java
调用改类的onStartup方法。
调用父类的onStartup方法:AbstractSecurityWebApplicationInitializer.java
public final void onStartup(ServletContext servletContext) throws ServletException {
...
//registerFilter(servletContext, true, filterName, springSecurityFilterChain);
//向ServletContext中注册spring安全框架的Filter,在web.xml中配置过springSecurity框架的应该都知道
insertSpringSecurityFilterChain(servletContext);
...
}
step3:
WebContextInitializer.java
调用该类的onStartup方法。
调用父类AbstractContextLoaderInitializer.java的onstartup方法
//注册ContextLoaderListener,在web.xml中配置过spring框架的人都知道
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
registerContextLoaderListener(servletContext);
}
protected void registerContextLoaderListener(ServletContext servletContext) {
//创建spring的根应用上下文
WebApplicationContext rootAppContext = createRootApplicationContext();
if (rootAppContext != null) {
ContextLoaderListener listener = new ContextLoaderListener(rootAppContext);
listener.setContextInitializers(getRootApplicationContextInitializers());
servletContext.addListener(listener);
}
else {
logger.debug("No ContextLoaderListener registered, as " +
"createRootApplicationContext() did not return an application context");
}
}
调用父类AbstractDispatcherServletInitializer.java的onstartup方法
//注册DispatcherServlet,在web.xml中配置过springMVC框架的人都知道
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
registerDispatcherServlet(servletContext);
}
protected void registerDispatcherServlet(ServletContext servletContext) {
String servletName = getServletName();
Assert.hasLength(servletName, "getServletName() must not return empty or null");
//创建springMVC的应用上下文
WebApplicationContext servletAppContext = createServletApplicationContext();
...
FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
...
}
//创建spring应用上下文和创建springMVC应用上下文的实现在AbstractAnnotationConfigDispatcherServletInitializer.java中
//根上下文的创建
@Override
protected WebApplicationContext createRootApplicationContext() {
//获取要加载的class,由子类实现
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}
//springMVC上下文的创建
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
//获取要加载的class,由子类实现
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}
step4
listener,filter,servlet通过编码的方式配置到ServletContext后,后面的启动过程和xml配置一直,spring容器的启动入口在ContextLoaderListener,springMVC的启动入口在DispatchServlet,springSecurity的启动入口在SecurityFilterChain