spring源码分析-springweb项目的初始化原理

在servlet3之前,所有的java web项目都需要存在一份web.xml的配置文件
servlet3提供了一种直接用java代码配置的方式。在第三方组件中,实现接口javax.servlet.ServletContainerInitializer。

1
2
3
4
public interface ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}

之后在这个实现类中使用注解@HandlesTypes标记钩子类型(姑且这么叫吧,所有被注解@HandlesTypes标记的类都会在容器启动时被传递给onStartup方法的Set<Class<?>>参数),在这之前还需要第三方jar包在/META-INF/services/javax.servlet.ServletContainerInitializer文件中定义ServletContainerInitializer实现类的全类名。如spring-web中定义在spring-web-4.3.18.RELEASE.jar!/META-INF/services/javax.servlet.ServletContainerInitializer文件中的实现类为org.springframework.web.SpringServletContainerInitializer

spring中的servlet容器初始化类

spring实现的servlet容器启动初始化类org.springframework.web.SpringServletContainerInitializer。可以看到spring中定义的钩子类型为WebApplicationInitializer

1
2
3
4
5
6
7
8
9
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
// ... 省略具体代码
}

}

spring项目的配置及初始化流程

先来看看在spring中怎么样利用ServletContainerInitializer进行初始化,在spring项目中一般通过继承org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer来定义一个配置类,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}

@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

继承关系如下
image

下面分析一下在servlet容器启动时,spring是如何进行初始化的。

  • 初始化root WebApplicationContext
    image
  • 初始化servlet WebApplicationContext
    image