参考文献

SpringMVC执行流程

  • DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心.用户发出请求,DispatcherServlet接收请求并拦截请求.
  • HandlerMapping为处理器映射.DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler
  • HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器
  • HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
  • HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
  • Handler让具体的Controller执行
  • Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
  • HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
  • DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
  • 视图解析器将解析的逻辑视图名传给DispatcherServlet
  • DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
  • 最终视图呈现给用户

启动流程

SpringBoot部分

入口run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
// 创建并启动计时器
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置系统属性 java.awt.headless.
configureHeadlessProperty();
// TODO 1 获取并启动监听器
// 创建运行监听器组,先根据spring.factories中的配置创建要使用的运行监听实例,再把这些运行监听实例封装为运行监听器组
SpringApplicationRunListeners listeners = getRunListeners(args);
// 执行运行监听器的starting()回调方法
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 构建应用参数
// 应用参数指的是传给main()方法的参数arg 这一步会将main()方法的参数封装为ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// TODO 2 根据SpringApplicationRunListeners 以及参数来准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置spring.beaninfo.ignore属性
configureIgnoreBeanInfo(environment);
// 准备Banner打印器 -SpringBoot启动的时候打印在console上的内容
Banner printedBanner = printBanner(environment);
// TODO 3 创建Spring容器(创建应用上下文)
// 一般web应用,最终会执行 new AnnotationConfigServletWebServerApplicationContext()来创建context
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// TODO 4 Spring容器前置处理
// (准备上下文,主要对上一步创建好的上下文进行配置、完善,这一步会加载所有的bean定义)
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// TODO 5 刷新容器
// (刷新上下文,主要调用高级容器的refresh()刷新上下文,这一步会实例化所有的单例bean,懒加载的除外)
refreshContext(context);
// TODO 6 Spring容器后置处理
//(执行刷新后处理,这个方法是protected修饰的空方法,作为预留的扩展点可被子类重写,可以在上下文刷新之后做一些自定义的操作)
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// TODO 7 发出结束执行的事件
// (运行监听器的started()回调方法)
listeners.started(context, timeTakenToStartup);
// TODO 8 执行Runners
//(执行Runner回调,这也是一个扩展点,可以在应用启动后,根据main()参数做一些自定义的处理)
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
// 1、执行运行监听器的failed()回调方法;
// 2、使用异常报告器 SpringBootExceptionReporter 打印\记录异常信息
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}

SpringMVC部分

  • SpringMVC启动过程和SpringBoot启动流程的区别主要在刷新上下文的实现
  • WebApplicationType.SERVLET为例,即创建的上下文为org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
1
2
3
4
5
6
7
8
9
10
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
// 第一次进来webServer servletContext都是null
if (webServer == null && servletContext == null) {
// 这里只是做个标记
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
// 这里就会来查找ServletWebServerFactory,也就是web容器的工厂,
// 具体看下getWebServerFactory()方法,还是ServletWebServerApplicationContext这个类的方法
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
//这里就是具体创建tomcat了,这里的入参getSelfInitializer()是个lambda表达式,这个后续很重要
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
	/**
* Returns the {@link ServletWebServerFactory} that should be used to create the
* embedded {@link WebServer}. By default this method searches for a suitable bean in
* the context itself.
* @return a {@link ServletWebServerFactory} (never {@code null})
*/
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
// 从beanFactory中查找ServletWebServerFactory类型的bean的定义,返回对应bean的名字
// ServletWebServerFactory的加载通过Springboot的自动装配来完成,
// 通过配置在org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中的ServletWebServerFactoryAutoConfiguration来
// org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
// org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
// 这个类会导入
// ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
// ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
// ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
// ServletWebServerFactoryConfiguration.EmbeddedUndertow.class
// 一般场景使用Tomcat作为Web容器,EmbeddedTomcat最终创建TomcatServletWebServerFactory
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new MissingWebServerFactoryBeanException(getClass(), ServletWebServerFactory.class,
WebApplicationType.SERVLET);
}
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
// 这里的逻辑实际上会执行ServletWebServerFactoryConfiguration.EmbeddedTomcat类的tomcatServletWebServerFactory方法,
// 返回TomcatServletWebServerFactory对象
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}

创建DispatcherServlet

  • org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class)
// 关注这ConditionalOnWebApplication、ConditionalOnClass注解
// ConditionalOnWebApplication是根据type来判断指定类是否存在
// 当前的type是 Type.SERVLET,是来查找org.springframework.web.context.support.GenericWebApplicationContext类是否存在,
// 这个类存在于spring-web中,所以这个条件是true
@ConditionalOnWebApplication(type = Type.SERVLET)
// 就是查找指定的类是否存在,这个是查找DispatcherServlet.class是否存在,这里也会返回true
@ConditionalOnClass(DispatcherServlet.class)
public class DispatcherServletAutoConfiguration {

/**
* The bean name for a DispatcherServlet that will be mapped to the root URL "/".
*/
public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

/**
* The bean name for a ServletRegistrationBean for the DispatcherServlet "/".
*/
public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";

@Configuration(proxyBeanMethods = false)
// DefaultDispatcherServletCondition这个类就在当前这个文件里,matches判断的结果也是true
@Conditional(DefaultDispatcherServletCondition.class)
// ServletRegistration.class这个类存在于tomcat-embed-core里面,这个结果也是true
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {

// beanFactory会创建这个DispatcherServletBean的定义,bean的名字就是dispatcherServlet
@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
return dispatcherServlet;
}

@Bean
@ConditionalOnBean(MultipartResolver.class)
// multipartResolver
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
// Detect if the user has created a MultipartResolver but named it incorrectly
return resolver;
}

}

@Configuration(proxyBeanMethods = false)
@Conditional(DispatcherServletRegistrationCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
@Import(DispatcherServletConfiguration.class)
protected static class DispatcherServletRegistrationConfiguration {

// dispatcherServletRegistration
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
// dispatcherServlet
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
webMvcProperties.getServlet().getPath());
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
multipartConfig.ifAvailable(registration::setMultipartConfig);
return registration;
}

}

// ...略
}
  • 初始化各个组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}

/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
// 初始化MultipartResolver MultipartResolver主要处理文件上传
initMultipartResolver(context);
// 初始化LocaleResolver 本地化解析器 处理国际化配置
initLocaleResolver(context);
// 初始化ThemeResolver 主题解析器
initThemeResolver(context);
// 初始化HandlerMappings HandlerMapping处理器映射器
initHandlerMappings(context);
// 初始化HandlerAdapters HandlerAdapter处理器适配器
initHandlerAdapters(context);
// 初始化HandlerExceptionResolvers 异常解析器
initHandlerExceptionResolvers(context);
// 初始化RequestToViewNameTranslator 视图解析器
initRequestToViewNameTranslator(context);
// 初始化ViewResolvers
initViewResolvers(context);
// 初始化FlashMapManager
initFlashMapManager(context);
}