SpringBoot源码分析 - 启动过程

基于SpringBoot 2.3.4

main#SpringApplication.run()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SpringBoot Web服务入口
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

// SpringApplication#run
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 先构造SpringApplication实例,再调用run方法
return new SpringApplication(primarySources).run(args);
}

先构造SpringApplication实例,再调用run方法。

SpringApplication#构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 设置SpringApplication#primarySources,注意这里primarySources参数就是run方法的第一个参数
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); //#1
// 判断当前应用是JAVA应用,SERVLET应用或REACTIVE应用。
this.webApplicationType = WebApplicationType.deduceFromClasspath(); //#2
// 加载spring.factories中配置的ApplicationContextInitializer实现类,将结果存放到SpringApplication#initializers
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); //#3
// 加载spring.factories中配置的ApplicationListener实现类,将结果存放到SpringApplication#listeners
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //#4
// 获取main方法所在Class
this.mainApplicationClass = deduceMainApplicationClass(); //#5
}

deduceFromClasspath - webApplicationType

Springboot 项目的程序类型有三种:

  1. WebApplicationType.NONE
    非 web 应用程序(不内嵌服务器)
  2. WebApplicationType.SERVLET
    内嵌基于 servlet 的 web 服务器(如:Tomcat,Jetty,Undertow 等,其实现在大多Java网站应用都是采用的基于 Tomcat 的 servlet 类型服务器)
  3. WebApplicationType.REACTIVE
    内嵌基于反应式的 web 服务器(如: Netty)

deduceMainApplicationClass - mainApplicationClass

获取main方法所在Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 使用异常堆栈来判断 当前主类
*/
private Class<?> deduceMainApplicationClass() {
try {

StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}

spring-boot的启动主类,一切都是由spring自己推导的,所以我们不要所以然的认为主类是我们传给spring容器的。

SpringApplication#getSpringFactoriesInstances

spring-boot:SpringApplication#getSpringFactoriesInstances
spring-core:SpringFactoriesLoader#loadSpringFactories

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
// SpringApplication#getSpringFactoriesInstances
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// SpringFactoriesLoader.loadFactoryNames(type, classLoader)
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

// SpringFactoriesLoader#loadFactoryNames
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
// SpringFactoriesLoader#loadSpringFactories
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}

try {
// FACTORIES_RESOURCE_LOCATION就是字符串"META-INF/spring.factories",这里读取jar中META-INF/spring.factories文件内容
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// 加载spring.factories文件(格式为Properties)
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
// 读取Properties内容,缓存结果
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
spring.factories
1
2
3
4
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.haier.updaterecord.mybatis.plus.spring.boot.autoconfigure.UpdateRecordAutoConfiguration,\
com.haier.updaterecord.core.factory.UpdateRecordServiceFactory

key为spring扩展接口(或声明功能的注解),value为对应的功能实现类的列表

SpringApplication#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
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 监视器启动,计算初始化需要花费多少时间
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
// 配置java.awt.headless
this.configureHeadlessProperty();
// 从 META-INF/spring.factories 中获取 SpringApplicationRunListener 实现类,并调用starting()
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();

Collection exceptionReporters;
try {
// 命令行参数处理
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 构建Environment,准备环境变量配置
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
// 通过 spring.beaninfo.ignore 配置是否忽略bean信息 暂不明觉厉
this.configureIgnoreBeanInfo(environment);
// 打印SpringBoot控制台启动图案
Banner printedBanner = this.printBanner(environment);
// 创建应用上下文ApplicationContext
context = this.createApplicationContext();
// 从 META-INF/spring.factories 中获取异常报告处理器,用作处理启动异常
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
/**
* 准备应用上下文
* 1 设置上下文环境配置
* 2 注册 beanNameGenerator 等
* 3 执行 ApplicationContextInitializer#initialize()初始化
*/
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

// 刷新上下文 重要!!!
this.refreshContext(context);

// 容器初始化之后 开始执行 ApplicationRunner 和 CommandLineRunner 自定义初始化执行器
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}

listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}

try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}

run#prepareEnvironment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
// 创建一个Environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 将SpringApplication#run中的可变参数列表传递给Environment
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// 发送ApplicationEnvironmentPreparedEvent事件
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
关于SpringApplication#run中的args参数

我们在启动SpringBoot时,可以添加命令行参数,如java -jar app.jar –spring.profiles.active=dev
命令行参数--spring.profiles.active=dev会传递给main方法,main方法中需要将其传递给SpringApplication#run方法,
这里将命令行参数添加Environment中,作为一个PropertySource。

run#createApplicationContext

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
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// SERVLET应用,选择AnnotationConfigServletWebServerApplicationContext
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
// REACTIVE应用,选择AnnotationConfigReactiveWebServerApplicationContext
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
// JAVA应用,选择AnnotationConfigApplicationContext
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
// 构造对应的Spring Context
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

一般我们的SringBoot Web应用webApplicationTypeSERVLET,所以会创建AnnotationConfigServletWebServerApplicationContext
其父类ServletWebServerApplicationContext,通过ServletWebServerFactory创建并初始化WebServer。
WebServer兼容不同的servlet容器(tomcat,jetty,netty),提供统一的start,stop操作。

run#prepareContext

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
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置context上下文环境
context.setEnvironment(environment);
// ApplicationContext的后置处理
postProcessApplicationContext(context);
// 调用ApplicationContextInitializer#initialize,执行initialize
applyInitializers(context);
// 调用SpringApplicationRunListener#contextPrepared方法,发布contextPrepared事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
// 打印项目启动日志
logStartupInfo(context.getParent() == null);
// 打印profile
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// 获取到DefaultListableBeanFactory实例
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 注册名为springApplicationArguments,值为applicationArguments的命令行参数单例bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
// 如果banner不为空,那么注册名为springBootBanner,值为printedBanner的单例bean
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
// allowBeanDefinitionOverriding默认为false
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 当前sources列表中只有一个main启动方法所在的Application.class对象,在此处加载springboot启动类
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
// SpringApplication#load
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 实例化BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
loader.load();
}

run#refreshContext

参照Spring源码解析的refreshContext部分。

AbstractApplicationContext#refresh()#invokeBeanFactoryPostProcessors(beanFactory),自动装配在此完成
当前applicationContext是AnnotationConfigServletWebServerApplicationContext。

SpringBoot源码分析 - 启动过程 - Tomcat启动

Tomcat和Spring、Spring MVC的关系

为什么默认是Tomcat

spring-boot-starter-web最原始依赖的是tomcat。

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
<!--引入springboot父依赖-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>

<dependencies>
<!--引入启动器依赖 里面就有默认的tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<dependencies>
<!--引入启动器依赖 里面就有默认的tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--排除tomcat-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入Jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--引入Netty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--引入Undertow-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>

createApplicationContext -> AnnotationConfigServletWebServerApplicationContext

因为我们的应用是 Web Servlet 类型,
所以实例化的是AnnotationConfigServletWebServerApplicationContext。

refreshContext -> tomcat启动

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
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}

public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);

try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
/** 主要关系 onRefresh() 方法 ------------- **/
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}

this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}

}
}

protected void onRefresh() {
super.onRefresh();

try {
this.createWebServer();
} catch (Throwable var2) {
throw new ApplicationContextException("Unable to start web server", var2);
}
}

private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = this.getServletContext();
if (webServer == null && servletContext == null) {
/** 得到Servlet WebServer工厂 **/
ServletWebServerFactory factory = this.getWebServerFactory();
this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
} else if (servletContext != null) {
try {
this.getSelfInitializer().onStartup(servletContext);
} catch (ServletException var4) {
throw new ApplicationContextException("Cannot initialize servlet context", var4);
}
}
this.initPropertySources();
}

SpringBoot源码分析 - 启动过程 - Spring MVC自动配置

即Spring MVC的核心组件DispatcherServlet的注册过程。
DispatcherServlet 如何通过自动配置注册到ServletWebServer中。

1. 自动配置DispatcherServlet和DispatcherServletRegistry

  1. DispatcherServletAutoConfiguration自动配置类
    SpringBoot的自动配置基于SPI机制,实现自动配置的核心要点就是添加一个自动配置的类,SpringBoot MVC的自动配置自然也是相同原理。
    先找到对应的自动配置类:

    1
    2
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    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
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Configuration(proxyBeanMethods = false) // @Configuration表明这是一个配置类,将会被spring给解析。
    @ConditionalOnWebApplication(type = Type.SERVLET) //意味着当是一个web项目,且是Servlet项目的时候才会被解析
    @ConditionalOnClass(DispatcherServlet.class) // 指明DispatcherServlet这个核心类必须存在才解析该类
    @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) // 指明在ServletWebServerFactoryAutoConfiguration这个类之后再解析,设定了一个顺序
    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)
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties(WebMvcProperties.class)
    protected static class DispatcherServletConfiguration {

    @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)
    @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 {

    @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
    @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;
    }

    }

    //... 省略后续代码
    }

    DispatcherServletAutoConfiguration类主要包含了两个内部类,分别是:

    • DispatcherServletConfiguration
      配置DispatcherServlet。
    • DispatcherServletRegistrationConfiguration
      配置DispatcherServlet的注册类
      DispatcherServletRegistrationConfiguration将生成一个DispatcherServletRegistrationBean负责将DispatcherServlet给注册到ServletContext中
  2. 配置DispatcherServletConfiguration

  3. 配置DispatcherServletRegistrationConfiguration

2. 注册DispatcherServlet到ServletContext

DispatcherServletRegistrationBean负责将DispatcherServlet注册到ServletContext当中。

总的来说,其实就是触发了初始化ServletContext时候的回调接口onStartup方法,而后直接将DispatcherServlet作为一个Servlet给add到ServletContext当中。

3. 初始化mvc的组件


根据类图可以看到两部分的设计:
第一部分是Servlet到HttpServlet,也就是Servlet容器相关的内部设计。
第二部分是Spring在HttpServlet的基础上扩展了框架相关的内容,而最终DispatcherServlet将扩展springMVC的内容。

DispatcherServlet作为一个Servlet的实现,在Servlet被调用init方法以后最终将会调用DispatcherServlet的initStrategies方法,该方法将会初始化各个组件。
初始化组件基本就是把各个Bean对象从BeanFactory中拿出来组合到DispatcherServlet中,供后续使用。

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
public class DispatcherServlet extends FrameworkServlet {

@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) {
// 九大组件
// 文件上传的解析器
initMultipartResolver(context);
// 国际化解析器
initLocaleResolver(context);
// 主题解析器
initThemeResolver(context);
// HandlerMapping 根据请求对象找到Hander处理器对象
initHandlerMappings(context);
// HandlerAdapter 处理器的适配器
initHandlerAdapters(context);
// 异常解析器
initHandlerExceptionResolvers(context);
// 视图名称解析器
initRequestToViewNameTranslator(context);
// 视图解析器
initViewResolvers(context);
// 通过redirect携参的请求
initFlashMapManager(context);
}
}